diff options
Diffstat (limited to 'Source/JavaScriptCore')
85 files changed, 4063 insertions, 1895 deletions
diff --git a/Source/JavaScriptCore/API/APIShims.h b/Source/JavaScriptCore/API/APIShims.h index 0b49d70..26db2dc 100644 --- a/Source/JavaScriptCore/API/APIShims.h +++ b/Source/JavaScriptCore/API/APIShims.h @@ -39,8 +39,11 @@ protected: : m_globalData(globalData) , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable)) { + UNUSED_PARAM(registerThread); +#if ENABLE(JSC_MULTIPLE_THREADS) if (registerThread) - globalData->heap.registerThread(); + globalData->heap.machineStackMarker().registerThread(); +#endif m_globalData->heap.activityCallback()->synchronize(); m_globalData->timeoutChecker.start(); } diff --git a/Source/JavaScriptCore/API/JSBase.h b/Source/JavaScriptCore/API/JSBase.h index 2e16720..d962b01 100644 --- a/Source/JavaScriptCore/API/JSBase.h +++ b/Source/JavaScriptCore/API/JSBase.h @@ -63,21 +63,22 @@ typedef const struct OpaqueJSValue* JSValueRef; typedef struct OpaqueJSValue* JSObjectRef; /* JavaScript symbol exports */ +/* These rules should stay the same as in WebKit2/Shared/API/c/WKBase.h */ #undef JS_EXPORT #if defined(JS_NO_EXPORT) - #define JS_EXPORT +#define JS_EXPORT #elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) - #define JS_EXPORT __attribute__((visibility("default"))) -#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE) - #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) - #define JS_EXPORT __declspec(dllexport) - #else - #define JS_EXPORT __declspec(dllimport) - #endif +#define JS_EXPORT __attribute__((visibility("default"))) +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE) || defined(__CC_ARM) || defined(__ARMCC__) +#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) +#define JS_EXPORT __declspec(dllexport) #else - #define JS_EXPORT +#define JS_EXPORT __declspec(dllimport) #endif +#else /* !defined(JS_NO_EXPORT) */ +#define JS_EXPORT +#endif /* defined(JS_NO_EXPORT) */ #ifdef __cplusplus extern "C" { diff --git a/Source/JavaScriptCore/API/JSCallbackObject.cpp b/Source/JavaScriptCore/API/JSCallbackObject.cpp index abd2adc..b8e5843 100644 --- a/Source/JavaScriptCore/API/JSCallbackObject.cpp +++ b/Source/JavaScriptCore/API/JSCallbackObject.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "JSCallbackObject.h" -#include "Collector.h" +#include "Heap.h" #include <wtf/text/StringHash.h> namespace JSC { diff --git a/Source/JavaScriptCore/Android.mk b/Source/JavaScriptCore/Android.mk index 579451b..ba6437b 100644 --- a/Source/JavaScriptCore/Android.mk +++ b/Source/JavaScriptCore/Android.mk @@ -84,7 +84,8 @@ LOCAL_SRC_FILES := \ runtime/BooleanObject.cpp \ runtime/BooleanPrototype.cpp \ runtime/CallData.cpp \ - runtime/Collector.cpp \ + runtime/MarkedSpace.cpp \ + runtime/Heap.cpp \ runtime/CommonIdentifiers.cpp \ runtime/Completion.cpp \ runtime/ConstructData.cpp \ @@ -131,6 +132,7 @@ LOCAL_SRC_FILES := \ runtime/JSWrapperObject.cpp \ runtime/LiteralParser.cpp \ runtime/Lookup.cpp \ + runtime/MachineStackMarker.cpp \ runtime/MarkStack.cpp \ runtime/MarkStackPosix.cpp \ runtime/MathObject.cpp \ @@ -200,6 +202,7 @@ LOCAL_SRC_FILES := \ \ wtf/unicode/icu/CollatorICU.cpp \ \ +<<<<<<< HEAD wtf/url/src/URLCharacterTypes.cpp \ wtf/url/src/URLEscape.cpp \ wtf/url/src/URLSegments.cpp \ @@ -207,6 +210,12 @@ LOCAL_SRC_FILES := \ yarr/RegexInterpreter.cpp \ yarr/RegexJIT.cpp \ yarr/RegexPattern.cpp +======= + yarr/YarrPattern.cpp \ + yarr/YarrInterpreter.cpp \ + yarr/YarrJIT.cpp \ + yarr/YarrSyntaxChecker.cpp +>>>>>>> WebKit.org @ r75993 # generated headers JSC_OBJECTS := $(addprefix $(intermediates)/runtime/, \ diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index f8b4d1e..29de8a7 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -87,7 +87,8 @@ SET(JavaScriptCore_SOURCES runtime/BooleanObject.cpp runtime/BooleanPrototype.cpp runtime/CallData.cpp - runtime/Collector.cpp + runtime/MarkedSpace.cpp + runtime/Heap.cpp runtime/CommonIdentifiers.cpp runtime/Completion.cpp runtime/ConstructData.cpp @@ -135,6 +136,7 @@ SET(JavaScriptCore_SOURCES runtime/JSZombie.cpp runtime/LiteralParser.cpp runtime/Lookup.cpp + runtime/MachineStackMarker.cpp runtime/MarkStack.cpp runtime/MathObject.cpp runtime/NativeErrorConstructor.cpp @@ -166,9 +168,10 @@ SET(JavaScriptCore_SOURCES runtime/TimeoutChecker.cpp runtime/UString.cpp - yarr/RegexPattern.cpp - yarr/RegexInterpreter.cpp - yarr/RegexJIT.cpp + yarr/YarrPattern.cpp + yarr/YarrInterpreter.cpp + yarr/YarrJIT.cpp + yarr/YarrSyntaxChecker.cpp wtf/DateMath.cpp wtf/PageAllocationAligned.cpp @@ -219,7 +222,7 @@ ADD_CUSTOM_COMMAND( MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/create_regex_tables COMMAND ${PYTHON_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/create_regex_tables > ${DERIVED_SOURCES_DIR}/RegExpJitTables.h VERBATIM) -ADD_SOURCE_DEPENDENCIES(${JAVASCRIPTCORE_DIR}/yarr/RegexPattern.cpp ${DERIVED_SOURCES_DIR}/RegExpJitTables.h) +ADD_SOURCE_DEPENDENCIES(${JAVASCRIPTCORE_DIR}/yarr/YarrPattern.cpp ${DERIVED_SOURCES_DIR}/RegExpJitTables.h) diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 54ac1e9..9d92e9d 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,1316 @@ +2011-01-17 Jarred Nicholls <jarred@sencha.com> + + Reviewed by Csaba Osztrogonác. + + REGRESSION(r75709): Return value of fscanf() shouldn't be ignored. + https://bugs.webkit.org/show_bug.cgi?id=52585 + + gcc 4.4.4+ has warn_unused_value attribute on fscanf, so we should check + the return value to get around the gcc warning + + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::maybeModifyVMPoolSize): + +2011-01-17 Michael Saboff <msaboff@apple.com> + + Reviewed by Oliver Hunt. + + [regexfuzz] Crash running regex with lookahead + https://bugs.webkit.org/show_bug.cgi?id=52548 + + Eliminated agressive chaining of backtracks. This code was overwriting + already valid backtrack information. + + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::ParenthesesTail::processBacktracks): + +2011-01-17 Tony Gentilcore <tonyg@chromium.org> + + Reviewed by Alexey Proskuryakov. + + Fix some headers with missing or misspelled #ifndef guards + https://bugs.webkit.org/show_bug.cgi?id=52545 + + * wtf/RefPtrHashMap.h: + +2011-01-17 Dan Bernstein <mitz@apple.com> + + Rubber-stamped by Mark Rowe. + + Update xcodeproj svn:ignore to include xcuserdata. + + * JavaScriptCore.xcodeproj: Modified property svn:ignore. + +2011-01-16 Adam Barth <abarth@webkit.org> + + Rubber-stamped by Eric Seidel. + + Move WebKit into Source + https://bugs.webkit.org/show_bug.cgi?id=52530 + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2011-01-16 Oliver Hunt <oliver@apple.com> + + Reviewed by Sam Weinig. + + [jsfunfuzz] Parser doesn't correctly validate for-loop syntax + https://bugs.webkit.org/show_bug.cgi?id=52516 + + Ensure that we always check for a semicolon after encountering + multiple declarations in the initialiser portion of a for-loop. + + * parser/JSParser.cpp: + (JSC::JSParser::parseForStatement): + +2011-01-16 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Strict mode restrictions on arguments and eval usage aren't complete + https://bugs.webkit.org/show_bug.cgi?id=52528 + + Fix a few bugs in strict mode where we incorrect allow mutation of + arguments and eval in the parser. + + Alas the "optimisation" used by the syntax checker for validating + binary and unary expressions was too aggressive: we do actually need + a stack for operations and operands although it needn't be as complete + as that used for the full AST builder. + + Also disallow assignment to arguments in all cases as allowing arguments + to be assignable is always an error in strict mode, regardless of context. + + * parser/ASTBuilder.h: + (JSC::ASTBuilder::BinaryExprContext::BinaryExprContext): + (JSC::ASTBuilder::UnaryExprContext::UnaryExprContext): + * parser/JSParser.cpp: + (JSC::JSParser::parseAssignmentExpression): + (JSC::JSParser::parseBinaryExpression): + (JSC::JSParser::parseUnaryExpression): + * parser/SyntaxChecker.h: + (JSC::SyntaxChecker::BinaryExprContext::BinaryExprContext): + (JSC::SyntaxChecker::BinaryExprContext::~BinaryExprContext): + (JSC::SyntaxChecker::UnaryExprContext::UnaryExprContext): + (JSC::SyntaxChecker::UnaryExprContext::~UnaryExprContext): + (JSC::SyntaxChecker::appendBinaryExpressionInfo): + (JSC::SyntaxChecker::operatorStackPop): + +2011-01-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Rolled back in r75886. + https://bugs.webkit.org/show_bug.cgi?id=52527 + + r75886 broke the GTK Linux bot because Linux was -- quite surprisingly -- + set up to use the constants for embedded devices. + + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::maybeModifyVMPoolSize): Separated Linux constants from embedded + constants. + +2011-01-15 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r75886. + http://trac.webkit.org/changeset/75886 + https://bugs.webkit.org/show_bug.cgi?id=52526 + + "Broke GTK+ 64bit" (Requested by xan_ on #webkit). + + * jit/ExecutableAllocatorFixedVMPool.cpp: + +2011-01-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + <rdar://problem/8870429> Shrink the executable pool on embedded devices + + * jit/ExecutableAllocatorFixedVMPool.cpp: Dropped the pool size from 32MB + to 16MB. + +2011-01-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Incorrect behavior changing attributes of an accessor + https://bugs.webkit.org/show_bug.cgi?id=52515 + + defineProperty doesn't correctly handle changing attributes of an accessor + property. This is because we don't pass the full descriptor to the + putDescriptor helper function, which means we have insufficient information + to do the right thing. Once that's passed the correct behavior is relatively + simple to implement. + + * runtime/JSObject.cpp: + (JSC::putDescriptor): + (JSC::JSObject::defineOwnProperty): + +2011-01-14 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + [jsfunfuzz] Incorrect handling of consecutive duplicate labels + https://bugs.webkit.org/show_bug.cgi?id=52505 + + Compare StringImpl*'s instead of Identifier*'s when looking for duplicate + labels. + + * parser/JSParser.cpp: + (JSC::JSParser::parseExpressionOrLabelStatement): + +2011-01-14 Simon Fraser <simon.fraser@apple.com> + + No review. + + Initialize m_operationInProgress after r75855. + + * runtime/Heap.cpp: + (JSC::Heap::Heap): + +2011-01-14 Geoffrey Garen <ggaren@apple.com> + + Reverted accidentally committed code from my last checkin. + + * runtime/Heap.cpp: + (JSC::Heap::markRoots): + +2011-01-14 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Try to fix the GTK bot. + + * runtime/Heap.cpp: + (JSC::Heap::Heap): + (JSC::Heap::markRoots): Kids, remember to initialize your data members. + Knowing is half the battle. + +2011-01-14 Oliver Hunt <oliver@apple.com> + + Reviewed by Stephanie Lewis. + + [jsfunfuzz] We should be clearing the lexers temporary character buffers when switching to strict mode + https://bugs.webkit.org/show_bug.cgi?id=52501 + + Clear the temporary character buffers used for reading escaped characters and + numbers. + + * parser/Lexer.h: + (JSC::Lexer::setOffset): + +2011-01-14 Geoffrey Garen <ggaren@apple.com> + + Try to fix non-Dtrace builds: #include Tracing.h instead of TracingDtrace.h. + + * runtime/Heap.cpp: + +2011-01-13 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Split out a MarkedSpace strategy object from Heap. + https://bugs.webkit.org/show_bug.cgi?id=52421 + + SunSpider reports no change. + + * Android.mk: + * CMakeLists.txt: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: Updated our 7 build systems. Which is cool. + + * runtime/Heap.cpp: + (JSC::Heap::Heap): + (JSC::Heap::destroy): + (JSC::Heap::recordExtraCost): + (JSC::Heap::allocate): + (JSC::Heap::markConservatively): + (JSC::Heap::markRoots): + (JSC::Heap::objectCount): + (JSC::Heap::statistics): + (JSC::Heap::size): + (JSC::Heap::isBusy): + (JSC::Heap::collectAllGarbage): + (JSC::Heap::primaryHeapBegin): + (JSC::Heap::primaryHeapEnd): + * runtime/Heap.h: + (JSC::Heap::globalData): + (JSC::Heap::markedSpace): + (JSC::Heap::isCellMarked): + (JSC::Heap::checkMarkCell): + (JSC::Heap::markCell): Moved all code pertaining to managing chunks of + collector memory out of this class. Heap now just delegates to MarkedSpace. + + * runtime/JSCell.h: + (JSC::JSCell::Heap::heap): Updated for MarkedSpace delegation. + + * runtime/JSValue.h: Moved the ValueStringPair typedef to help with #includes. + + * runtime/MarkedSpace.cpp: Copied from runtime/Heap.cpp. + (JSC::MarkedSpace::MarkedSpace): + (JSC::MarkedSpace::destroy): + (JSC::MarkedSpace::allocateBlock): + (JSC::MarkedSpace::freeBlock): + (JSC::MarkedSpace::allocate): + (JSC::MarkedSpace::resizeBlocks): + (JSC::MarkedSpace::growBlocks): + (JSC::MarkedSpace::shrinkBlocks): + (JSC::MarkedSpace::markConservatively): + (JSC::MarkedSpace::clearMarkBits): + (JSC::MarkedSpace::markedCells): + (JSC::MarkedSpace::sweep): + (JSC::MarkedSpace::objectCount): + (JSC::MarkedSpace::addToStatistics): + (JSC::MarkedSpace::statistics): + (JSC::MarkedSpace::size): + (JSC::MarkedSpace::reset): + (JSC::MarkedSpace::primaryHeapBegin): + (JSC::MarkedSpace::primaryHeapEnd): + * runtime/MarkedSpace.h: Copied from runtime/Heap.h. + (JSC::MarkedSpace::globalData): + (JSC::MarkedSpace::didShrink): + (JSC::MarkedSpace::cellBlock): + (JSC::MarkedSpace::cellOffset): + (JSC::MarkedSpace::isCellMarked): + (JSC::MarkedSpace::checkMarkCell): + (JSC::MarkedSpace::markCell): Moved all code pertaining to managing chunks of + collector memory into this class. + + * runtime/MemoryStatistics.cpp: + (JSC::heapStatistics): + * runtime/MemoryStatistics.h: Updated for MarkedSpace delegation. + +2011-01-14 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + [jsfunfuzz] parser doesn't enforce continue restrictions correctly. + https://bugs.webkit.org/show_bug.cgi?id=52493 + + This patch reworks handling of break, continue and label statements + to correctly handle all the valid and invalid cases. Previously certain + errors would be missed by the parser in strict mode, but the bytecode + generator needed to handle those cases for non-strict code so nothing + failed, it simply became non-standard behaviour. + + Now that we treat break and continue errors as early faults in non-strict + mode as well that safety net has been removed so the parser bugs result in + crashes at codegen time. + + * parser/JSParser.cpp: + (JSC::JSParser::ScopeLabelInfo::ScopeLabelInfo): + (JSC::JSParser::next): + (JSC::JSParser::nextTokenIsColon): + (JSC::JSParser::continueIsValid): + Continue is only valid in loops so we can't use breakIsValid() + (JSC::JSParser::pushLabel): + We now track whether the label is for a loop (and is therefore a + valid target for continue. + (JSC::JSParser::popLabel): + (JSC::JSParser::getLabel): + Replace hasLabel with getLabel so that we can validate the target + when parsing continue statements. + (JSC::JSParser::Scope::continueIsValid): + (JSC::JSParser::Scope::pushLabel): + (JSC::JSParser::Scope::getLabel): + (JSC::JSParser::JSParser): + (JSC::JSParser::parseBreakStatement): + (JSC::JSParser::parseContinueStatement): + (JSC::LabelInfo::LabelInfo): + (JSC::JSParser::parseExpressionOrLabelStatement): + Consecutive labels now get handled iteratively so that we can determine + whether they're valid targets for continue. + * parser/Lexer.cpp: + (JSC::Lexer::nextTokenIsColon): + * parser/Lexer.h: + (JSC::Lexer::setOffset): + +2011-01-14 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Adam Roben. + + Use the Windows thread pool instead of an extra thread for FastMalloc scavenging + https://bugs.webkit.org/show_bug.cgi?id=45186 + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::scheduleScavenger): Added missing this pointer to CreateTimerQueueTimer(). + +2011-01-14 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Adam Roben. + + Use the Windows thread pool instead of an extra thread for FastMalloc scavenging + https://bugs.webkit.org/show_bug.cgi?id=45186 + + r75819 accidentally changed the initial state of the scavenge timer. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::initializeScavenger): Changed initial state of m_scavengingSuspended to true. + +2011-01-14 Patrick Gansterer <paroga@webkit.org> + + Unreviewed Windows Release build fix. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::scavengerTimerFired): + +2011-01-14 Patrick Gansterer <paroga@webkit.org> + + Unreviewed Windows Release build fix. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::scavengerTimerFired): + +2011-01-14 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Adam Roben. + + Use the Windows thread pool instead of an extra thread for FastMalloc scavenging + https://bugs.webkit.org/show_bug.cgi?id=45186 + + Use CreateTimerQueueTimer() to start periodicScavenge() and stop it with DeleteTimerQueueTimer(). + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::initializeScavenger): + (WTF::TCMalloc_PageHeap::isScavengerSuspended): + (WTF::TCMalloc_PageHeap::scheduleScavenger): + (WTF::TCMalloc_PageHeap::rescheduleScavenger): + (WTF::TCMalloc_PageHeap::suspendScavenger): + (WTF::scavengerTimerFired): + (WTF::TCMalloc_PageHeap::periodicScavenge): + (WTF::TCMalloc_PageHeap::signalScavenger): + +2011-01-14 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Align import/export directives + https://bugs.webkit.org/show_bug.cgi?id=52208 + + * API/JSBase.h: Align import/export directives with + WebKit2/Shared/API/c/WKBase.h + +2011-01-14 Michael Saboff <msaboff@apple.com> + + Reviewed by Oliver Hunt. + + Incorrect backtracking for nested alternatives + https://bugs.webkit.org/show_bug.cgi?id=52387 + + In the process of propigating a datalabel it wasn't getting connected + to a destination when the destination was an indirect jump. Added + code to recognize a direct backtrack destination that was an indirect + jump and added mechanism to associate DataLabelPtrs with indirect + jump entries. + Removed dead method + BacktrackDestination::linkDataLabelToHereIfExists() + + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::IndirectJumpEntry::IndirectJumpEntry): + (JSC::Yarr::YarrGenerator::IndirectJumpEntry::addDataLabel): + (JSC::Yarr::YarrGenerator::GenerationState::addIndirectJumpEntry): + (JSC::Yarr::YarrGenerator::GenerationState::emitIndirectJumpTable): + Changes to link indirect jumps with DataLabelPtr's. + (JSC::Yarr::YarrGenerator::BacktrackDestination::clearSubDataLabelPtr): + (JSC::Yarr::YarrGenerator::TermGenerationState::linkDataLabelToBacktrackIfExists): + Updated to handle immediate linking of indirect jumps to + DataLabelPtr. + (JSC::Yarr::YarrGenerator::generateParenthesesDisjunction): Changed to + reflect updated linkDataLabelToBacktrackIfExists(). + +2011-01-14 Pavel Podivilov <podivilov@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: provide script column offset to frontend. + https://bugs.webkit.org/show_bug.cgi?id=52377 + + * parser/SourceCode.h: + (JSC::SourceCode::SourceCode): + (JSC::SourceCode::firstColumn): + +2011-01-13 Darin Adler <darin@apple.com> + + Reviewed by Geoff Garen. + + <rdar://problem/5469576> Use __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0 if available. + + * DerivedSources.make: Create a header file, HeaderDetection.h, that tells + us whether pthread_machdep.h is available. + * wtf/FastMalloc.cpp: If __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0 is available, then + don't do the pthread_getspecific_function_pointer trick. + (WTF::setThreadHeap): Ditto, but set thread-specific data. + (WTF::TCMalloc_ThreadCache::GetThreadHeap): Ditto, but get rather than set. + +2011-01-13 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gavin Barraclough. + + JIT requires VM overcommit (particularly on x86-64), Linux does not by default support this without swap? + https://bugs.webkit.org/show_bug.cgi?id=42756 + + The FixedVMPool Allocator does not work well on systems where + allocating very large amounts of memory upfront is not reasonable, + like Linux without overcommit enabled. As a workaround, on Linux, + default to the values used in embedded environments (in the MB + range), and only jump to the GB range if we detect at runtime that + overcommit is enabled. Should fix crashes on Linux/x86_64 with + less than 3 or 4GB of RAM. + + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::FixedVMPoolAllocator::free): use new variables for VM pool + size and coalesce limit. + (JSC::ExecutableAllocator::isValid): swap the variables from + embedded to generic values at runtime, on linux, if overcommit is + enabled. + (JSC::ExecutableAllocator::underMemoryPressure): use new variables + for VM pool size and coalesce limit. + +2011-01-12 Xan Lopez <xlopez@igalia.com> + + Reviewed by Martin Robinson. + + Add new Yarr.h header to the list file. + + * GNUmakefile.am: ditto. + +2011-01-12 Martin Robinson <mrobinson@igalia.com> + + Missing Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h in WebKitGtk tarball + https://bugs.webkit.org/show_bug.cgi?id=52299 + + * GNUmakefile.am: Fix the GTK+ build on ARMv7 by including missing source + files in the source list. + +2011-01-12 Peter Varga <pvarga@webkit.org> + + Reviewed by Gavin Barraclough. + + Add Yarr.h to YARR + https://bugs.webkit.org/show_bug.cgi?id=51021 + + Move other common constants and functions from YARR's different files + to Yarr.h. + Use Yarr.h header instead of including other YARR headers where it + is possible. + + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/RegExp.cpp: + * yarr/Yarr.h: Added. + * yarr/YarrInterpreter.cpp: + * yarr/YarrInterpreter.h: + * yarr/YarrJIT.cpp: + (JSC::Yarr::jitCompile): + (JSC::Yarr::execute): + * yarr/YarrJIT.h: + * yarr/YarrParser.h: + * yarr/YarrPattern.cpp: + (JSC::Yarr::YarrPattern::compile): + (JSC::Yarr::YarrPattern::YarrPattern): + * yarr/YarrPattern.h: + +2011-01-12 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r75595. + http://trac.webkit.org/changeset/75595 + https://bugs.webkit.org/show_bug.cgi?id=52286 + + It broke fast/regex/pcre-test-1.html (Requested by Ossy on + #webkit). + + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/RegExp.cpp: + * yarr/Yarr.h: Removed. + * yarr/YarrInterpreter.cpp: + * yarr/YarrInterpreter.h: + * yarr/YarrJIT.cpp: + (JSC::Yarr::jitCompile): + * yarr/YarrJIT.h: + (JSC::Yarr::execute): + * yarr/YarrParser.h: + * yarr/YarrPattern.cpp: + (JSC::Yarr::compile): + (JSC::Yarr::YarrPattern::YarrPattern): + * yarr/YarrPattern.h: + +2011-01-12 Peter Varga <pvarga@webkit.org> + + Reviewed by Gavin Barraclough. + + Add Yarr.h to YARR + https://bugs.webkit.org/show_bug.cgi?id=51021 + + Move other common constants and functions from YARR's different files + to Yarr.h. + Use Yarr.h header instead of including other YARR headers where it + is possible. + + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/RegExp.cpp: + * yarr/Yarr.h: Added. + * yarr/YarrInterpreter.cpp: + * yarr/YarrInterpreter.h: + * yarr/YarrJIT.cpp: + (JSC::Yarr::jitCompile): + (JSC::Yarr::execute): + * yarr/YarrJIT.h: + * yarr/YarrParser.h: + * yarr/YarrPattern.cpp: + (JSC::Yarr::YarrPattern::compile): + (JSC::Yarr::YarrPattern::YarrPattern): + * yarr/YarrPattern.h: + +2011-01-11 Michael Saboff <msaboff@apple.com> + + Reviewed by Geoffrey Garen. + + Missing call to popTempSortVector() for exception case in JSArray::sort. + https://bugs.webkit.org/show_bug.cgi?id=50718 + + Fix to patch of 50718 that added pushTempSortVector() and + popTempSortVector() to JSArray::sort() to mark elements during sort. + Need to add popTempSortVector() for the return case if toString() + had an exception. + + * runtime/JSArray.cpp: + (JSC::JSArray::sort): Added popTempSortVector() + +2011-01-11 Xan Lopez <xlopez@igalia.com> + + Reviewed by Darin Adler. + + Microoptimization in ~JSString + https://bugs.webkit.org/show_bug.cgi?id=52222 + + The case where m_fibers is 0 seems to be the most common one + (almost 1/2 of the time, followed at some distance by m_fibers = 1 + in 1/4 of the cases in a typical SunSpider execution). We can save + one comparison in this common case by doing a bit of refactoring + in the JSString destructor; overall a 0.3% progression, but only + the string tests show improvement. + + * runtime/JSString.h: + (JSC::RopeBuilder::~JSString): + +2011-01-10 Michael Saboff <msaboff@apple.com> + + Reviewed by Geoffrey Garen. + + ASSERTION Failure in JSC::binaryChop + https://bugs.webkit.org/show_bug.cgi?id=25614 + + Changed JITStubs::cti_register_file_check() to use the current stack's + return PC to find the bytecode for handling the exception in the prior + frame. Also added the appropriate arrity check routine call to the + JIT to bytecode vector (m_callReturnIndexVector) in the CodeBlock. + + * jit/JIT.cpp: + (JSC::JIT::privateCompile): Changed the arrity check call location + so that it gets added to the m_calls list so that it's included in + CodeBlock::m_callReturnIndexVector. + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): Use the current call frame's return PC. + +2011-01-10 Daniel Bates <dbates@rim.com> + + Reviewed by Martin Robinson. + + Remove extraneous COMPILER(GCC) condition when checking GCC_VERSION_AT_LEAST() + https://bugs.webkit.org/show_bug.cgi?id=52178 + + It is sufficient to test GCC_VERSION_AT_LEAST() instead of both COMPILER(GCC) and + GCC_VERSION_AT_LEAST(). Notice GCC_VERSION_AT_LEAST() is defined to be 0 when we + are not compiling with GCC. + + Fixes style issues at the callsites (i.e. replace comma with comma-space in + macro function argument list). Also, makes a spelling correction in a comment. + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + * wtf/Platform.h: + +2011-01-10 Geoffrey Garen <ggaren@apple.com> + + Build fix: removed some uses of nextNumber that I missed last time. + + * runtime/Heap.cpp: + (JSC::Heap::reset): + (JSC::Heap::collectAllGarbage): + +2011-01-10 Daniel Bates <dbates@rim.com> + + Reviewed by Darin Adler. + + Use __builtin_expect when compiling using RVCT in GNU mode + https://bugs.webkit.org/show_bug.cgi?id=51866 + + We should only use __builtin_expect if we are compiling with GCC or RVCT 3 or higher in GNU mode + as pointed out by Siddharth Mathur per <http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0202h/Cjabddedbde.html>. + + * wtf/AlwaysInline.h: + * wtf/Platform.h: Removed define WTF_COMPILER_RVCT4_OR_GREATER. Instead added macro + function RVCT_VERSION_AT_LEAST so that we can test for an arbitrary minimum RVCT + version. + +2011-01-10 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Moved Collector.* => Heap.*, since the file contains a class named "Heap". + + * API/JSCallbackObject.cpp: + * Android.mk: + * CMakeLists.txt: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * interpreter/Interpreter.cpp: + * interpreter/RegisterFile.h: + * jit/JITStubs.cpp: + * runtime/Collector.cpp: Removed. + * runtime/Collector.h: Removed. + * runtime/CollectorHeapIterator.h: + * runtime/GCActivityCallbackCF.cpp: + * runtime/Heap.cpp: Copied from JavaScriptCore/runtime/Collector.cpp. + * runtime/Heap.h: Copied from JavaScriptCore/runtime/Collector.h. + * runtime/InitializeThreading.cpp: + * runtime/JSCell.h: + * runtime/JSGlobalData.cpp: + * runtime/JSGlobalData.h: + * runtime/JSLock.cpp: + * runtime/JSNumberCell.h: + * runtime/MachineStackMarker.cpp: + * runtime/MemoryStatistics.h: + * runtime/Protect.h: + * runtime/UString.cpp: + * runtime/WeakGCMap.h: + * runtime/WeakGCPtr.h: + +2011-01-10 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gavin Barraclough. + + Remove unused isString() case in JSString::toPrimitiveString() + https://bugs.webkit.org/show_bug.cgi?id=52167 + + We never call toPrimitiveString() with strings, so remove the + check and add an ASSERT ensuring this never happens. 0.7% overall + progression in sunspider, since one of the call sites is very hot. + + * runtime/JSString.h: + (JSC::JSValue::toPrimitiveString): + +2011-01-10 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + Rename the existing YARR files and classes + https://bugs.webkit.org/show_bug.cgi?id=51872 + + Replace the "Regex" prefix with "Yarr" in the name of YARR files and classes. + + * Android.mk: + * CMakeLists.txt: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/RegExp.cpp: + (JSC::RegExp::compile): + (JSC::RegExp::match): + (JSC::RegExp::printTraceData): + * yarr/YarrInterpreter.cpp: Renamed from Source/JavaScriptCore/yarr/RegexInterpreter.cpp. + (JSC::Yarr::Interpreter::appendParenthesesDisjunctionContext): + (JSC::Yarr::Interpreter::popParenthesesDisjunctionContext): + (JSC::Yarr::Interpreter::DisjunctionContext::DisjunctionContext): + (JSC::Yarr::Interpreter::DisjunctionContext::operator new): + (JSC::Yarr::Interpreter::allocDisjunctionContext): + (JSC::Yarr::Interpreter::freeDisjunctionContext): + (JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::ParenthesesDisjunctionContext): + (JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::operator new): + (JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::restoreOutput): + (JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::getDisjunctionContext): + (JSC::Yarr::Interpreter::allocParenthesesDisjunctionContext): + (JSC::Yarr::Interpreter::freeParenthesesDisjunctionContext): + (JSC::Yarr::Interpreter::InputStream::InputStream): + (JSC::Yarr::Interpreter::InputStream::next): + (JSC::Yarr::Interpreter::InputStream::rewind): + (JSC::Yarr::Interpreter::InputStream::read): + (JSC::Yarr::Interpreter::InputStream::readPair): + (JSC::Yarr::Interpreter::InputStream::readChecked): + (JSC::Yarr::Interpreter::InputStream::reread): + (JSC::Yarr::Interpreter::InputStream::prev): + (JSC::Yarr::Interpreter::InputStream::getPos): + (JSC::Yarr::Interpreter::InputStream::setPos): + (JSC::Yarr::Interpreter::InputStream::atStart): + (JSC::Yarr::Interpreter::InputStream::atEnd): + (JSC::Yarr::Interpreter::InputStream::checkInput): + (JSC::Yarr::Interpreter::InputStream::uncheckInput): + (JSC::Yarr::Interpreter::InputStream::isNotAvailableInput): + (JSC::Yarr::Interpreter::testCharacterClass): + (JSC::Yarr::Interpreter::checkCharacter): + (JSC::Yarr::Interpreter::checkCasedCharacter): + (JSC::Yarr::Interpreter::checkCharacterClass): + (JSC::Yarr::Interpreter::tryConsumeBackReference): + (JSC::Yarr::Interpreter::matchAssertionBOL): + (JSC::Yarr::Interpreter::matchAssertionEOL): + (JSC::Yarr::Interpreter::matchAssertionWordBoundary): + (JSC::Yarr::Interpreter::backtrackPatternCharacter): + (JSC::Yarr::Interpreter::backtrackPatternCasedCharacter): + (JSC::Yarr::Interpreter::matchCharacterClass): + (JSC::Yarr::Interpreter::backtrackCharacterClass): + (JSC::Yarr::Interpreter::matchBackReference): + (JSC::Yarr::Interpreter::backtrackBackReference): + (JSC::Yarr::Interpreter::recordParenthesesMatch): + (JSC::Yarr::Interpreter::resetMatches): + (JSC::Yarr::Interpreter::parenthesesDoBacktrack): + (JSC::Yarr::Interpreter::matchParenthesesOnceBegin): + (JSC::Yarr::Interpreter::matchParenthesesOnceEnd): + (JSC::Yarr::Interpreter::backtrackParenthesesOnceBegin): + (JSC::Yarr::Interpreter::backtrackParenthesesOnceEnd): + (JSC::Yarr::Interpreter::matchParenthesesTerminalBegin): + (JSC::Yarr::Interpreter::matchParenthesesTerminalEnd): + (JSC::Yarr::Interpreter::backtrackParenthesesTerminalBegin): + (JSC::Yarr::Interpreter::backtrackParenthesesTerminalEnd): + (JSC::Yarr::Interpreter::matchParentheticalAssertionBegin): + (JSC::Yarr::Interpreter::matchParentheticalAssertionEnd): + (JSC::Yarr::Interpreter::backtrackParentheticalAssertionBegin): + (JSC::Yarr::Interpreter::backtrackParentheticalAssertionEnd): + (JSC::Yarr::Interpreter::matchParentheses): + (JSC::Yarr::Interpreter::backtrackParentheses): + (JSC::Yarr::Interpreter::lookupForBeginChars): + (JSC::Yarr::Interpreter::matchDisjunction): + (JSC::Yarr::Interpreter::matchNonZeroDisjunction): + (JSC::Yarr::Interpreter::interpret): + (JSC::Yarr::Interpreter::Interpreter): + (JSC::Yarr::ByteCompiler::ParenthesesStackEntry::ParenthesesStackEntry): + (JSC::Yarr::ByteCompiler::ByteCompiler): + (JSC::Yarr::ByteCompiler::compile): + (JSC::Yarr::ByteCompiler::checkInput): + (JSC::Yarr::ByteCompiler::assertionBOL): + (JSC::Yarr::ByteCompiler::assertionEOL): + (JSC::Yarr::ByteCompiler::assertionWordBoundary): + (JSC::Yarr::ByteCompiler::atomPatternCharacter): + (JSC::Yarr::ByteCompiler::atomCharacterClass): + (JSC::Yarr::ByteCompiler::atomBackReference): + (JSC::Yarr::ByteCompiler::atomParenthesesOnceBegin): + (JSC::Yarr::ByteCompiler::atomParenthesesTerminalBegin): + (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternBegin): + (JSC::Yarr::ByteCompiler::atomParentheticalAssertionBegin): + (JSC::Yarr::ByteCompiler::atomParentheticalAssertionEnd): + (JSC::Yarr::ByteCompiler::popParenthesesStack): + (JSC::Yarr::ByteCompiler::dumpDisjunction): + (JSC::Yarr::ByteCompiler::closeAlternative): + (JSC::Yarr::ByteCompiler::closeBodyAlternative): + (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd): + (JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd): + (JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd): + (JSC::Yarr::ByteCompiler::regexBegin): + (JSC::Yarr::ByteCompiler::regexEnd): + (JSC::Yarr::ByteCompiler::alternativeBodyDisjunction): + (JSC::Yarr::ByteCompiler::alternativeDisjunction): + (JSC::Yarr::ByteCompiler::emitDisjunction): + (JSC::Yarr::byteCompile): + (JSC::Yarr::interpret): + * yarr/YarrInterpreter.h: Renamed from Source/JavaScriptCore/yarr/RegexInterpreter.h. + (JSC::Yarr::ByteTerm::ByteTerm): + (JSC::Yarr::ByteTerm::BOL): + (JSC::Yarr::ByteTerm::CheckInput): + (JSC::Yarr::ByteTerm::EOL): + (JSC::Yarr::ByteTerm::WordBoundary): + (JSC::Yarr::ByteTerm::BackReference): + (JSC::Yarr::ByteTerm::BodyAlternativeBegin): + (JSC::Yarr::ByteTerm::BodyAlternativeDisjunction): + (JSC::Yarr::ByteTerm::BodyAlternativeEnd): + (JSC::Yarr::ByteTerm::AlternativeBegin): + (JSC::Yarr::ByteTerm::AlternativeDisjunction): + (JSC::Yarr::ByteTerm::AlternativeEnd): + (JSC::Yarr::ByteTerm::SubpatternBegin): + (JSC::Yarr::ByteTerm::SubpatternEnd): + (JSC::Yarr::ByteTerm::invert): + (JSC::Yarr::ByteTerm::capture): + (JSC::Yarr::ByteDisjunction::ByteDisjunction): + (JSC::Yarr::BytecodePattern::BytecodePattern): + (JSC::Yarr::BytecodePattern::~BytecodePattern): + * yarr/YarrJIT.cpp: Renamed from Source/JavaScriptCore/yarr/RegexJIT.cpp. + (JSC::Yarr::YarrGenerator::optimizeAlternative): + (JSC::Yarr::YarrGenerator::matchCharacterClassRange): + (JSC::Yarr::YarrGenerator::matchCharacterClass): + (JSC::Yarr::YarrGenerator::jumpIfNoAvailableInput): + (JSC::Yarr::YarrGenerator::jumpIfAvailableInput): + (JSC::Yarr::YarrGenerator::checkInput): + (JSC::Yarr::YarrGenerator::atEndOfInput): + (JSC::Yarr::YarrGenerator::notAtEndOfInput): + (JSC::Yarr::YarrGenerator::jumpIfCharEquals): + (JSC::Yarr::YarrGenerator::jumpIfCharNotEquals): + (JSC::Yarr::YarrGenerator::readCharacter): + (JSC::Yarr::YarrGenerator::storeToFrame): + (JSC::Yarr::YarrGenerator::storeToFrameWithPatch): + (JSC::Yarr::YarrGenerator::loadFromFrame): + (JSC::Yarr::YarrGenerator::loadFromFrameAndJump): + (JSC::Yarr::YarrGenerator::IndirectJumpEntry::IndirectJumpEntry): + (JSC::Yarr::YarrGenerator::IndirectJumpEntry::addJump): + (JSC::Yarr::YarrGenerator::AlternativeBacktrackRecord::AlternativeBacktrackRecord): + (JSC::Yarr::YarrGenerator::GenerationState::GenerationState): + (JSC::Yarr::YarrGenerator::GenerationState::addIndirectJumpEntry): + (JSC::Yarr::YarrGenerator::GenerationState::emitIndirectJumpTable): + (JSC::Yarr::YarrGenerator::GenerationState::incrementParenNestingLevel): + (JSC::Yarr::YarrGenerator::GenerationState::decrementParenNestingLevel): + (JSC::Yarr::YarrGenerator::GenerationState::addParenthesesTail): + (JSC::Yarr::YarrGenerator::GenerationState::emitParenthesesTail): + (JSC::Yarr::YarrGenerator::GenerationState::addJumpToNextInteration): + (JSC::Yarr::YarrGenerator::GenerationState::addJumpsToNextInteration): + (JSC::Yarr::YarrGenerator::GenerationState::addDataLabelToNextIteration): + (JSC::Yarr::YarrGenerator::GenerationState::linkToNextIteration): + (JSC::Yarr::YarrGenerator::BacktrackDestination::BacktrackDestination): + (JSC::Yarr::YarrGenerator::BacktrackDestination::clear): + (JSC::Yarr::YarrGenerator::BacktrackDestination::clearDataLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::hasDestination): + (JSC::Yarr::YarrGenerator::BacktrackDestination::isStackOffset): + (JSC::Yarr::YarrGenerator::BacktrackDestination::isLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::isJumpList): + (JSC::Yarr::YarrGenerator::BacktrackDestination::hasDataLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::copyTarget): + (JSC::Yarr::YarrGenerator::BacktrackDestination::copyTo): + (JSC::Yarr::YarrGenerator::BacktrackDestination::addBacktrackJump): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setStackOffset): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setNextBacktrackLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::copyBacktrackToLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setBacktrackToLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setBacktrackJumpList): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setBacktrackSourceLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setDataLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::setSubDataLabelPtr): + (JSC::Yarr::YarrGenerator::BacktrackDestination::linkToNextBacktrack): + (JSC::Yarr::YarrGenerator::BacktrackDestination::getStackOffset): + (JSC::Yarr::YarrGenerator::BacktrackDestination::getLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::getBacktrackJumps): + (JSC::Yarr::YarrGenerator::BacktrackDestination::getDataLabel): + (JSC::Yarr::YarrGenerator::BacktrackDestination::jumpToBacktrack): + (JSC::Yarr::YarrGenerator::BacktrackDestination::linkDataLabelToHereIfExists): + (JSC::Yarr::YarrGenerator::BacktrackDestination::plantJumpToBacktrackIfExists): + (JSC::Yarr::YarrGenerator::BacktrackDestination::linkAlternativeBacktracks): + (JSC::Yarr::YarrGenerator::BacktrackDestination::linkAlternativeBacktracksTo): + (JSC::Yarr::YarrGenerator::TermGenerationState::TermGenerationState): + (JSC::Yarr::YarrGenerator::TermGenerationState::resetAlternative): + (JSC::Yarr::YarrGenerator::TermGenerationState::alternativeValid): + (JSC::Yarr::YarrGenerator::TermGenerationState::nextAlternative): + (JSC::Yarr::YarrGenerator::TermGenerationState::alternative): + (JSC::Yarr::YarrGenerator::TermGenerationState::isLastAlternative): + (JSC::Yarr::YarrGenerator::TermGenerationState::resetTerm): + (JSC::Yarr::YarrGenerator::TermGenerationState::termValid): + (JSC::Yarr::YarrGenerator::TermGenerationState::nextTerm): + (JSC::Yarr::YarrGenerator::TermGenerationState::term): + (JSC::Yarr::YarrGenerator::TermGenerationState::isLastTerm): + (JSC::Yarr::YarrGenerator::TermGenerationState::getSubParenNum): + (JSC::Yarr::YarrGenerator::TermGenerationState::isMainDisjunction): + (JSC::Yarr::YarrGenerator::TermGenerationState::setParenthesesTail): + (JSC::Yarr::YarrGenerator::TermGenerationState::getParenthesesTail): + (JSC::Yarr::YarrGenerator::TermGenerationState::lookaheadTerm): + (JSC::Yarr::YarrGenerator::TermGenerationState::isSinglePatternCharacterLookaheadTerm): + (JSC::Yarr::YarrGenerator::TermGenerationState::inputOffset): + (JSC::Yarr::YarrGenerator::TermGenerationState::clearBacktrack): + (JSC::Yarr::YarrGenerator::TermGenerationState::jumpToBacktrack): + (JSC::Yarr::YarrGenerator::TermGenerationState::plantJumpToBacktrackIfExists): + (JSC::Yarr::YarrGenerator::TermGenerationState::linkDataLabelToBacktrackIfExists): + (JSC::Yarr::YarrGenerator::TermGenerationState::addBacktrackJump): + (JSC::Yarr::YarrGenerator::TermGenerationState::setBacktrackDataLabel): + (JSC::Yarr::YarrGenerator::TermGenerationState::setBackTrackStackOffset): + (JSC::Yarr::YarrGenerator::TermGenerationState::setBacktrackLabel): + (JSC::Yarr::YarrGenerator::TermGenerationState::linkAlternativeBacktracks): + (JSC::Yarr::YarrGenerator::TermGenerationState::linkAlternativeBacktracksTo): + (JSC::Yarr::YarrGenerator::TermGenerationState::setBacktrackLink): + (JSC::Yarr::YarrGenerator::TermGenerationState::chainBacktracks): + (JSC::Yarr::YarrGenerator::TermGenerationState::chainBacktrackJumps): + (JSC::Yarr::YarrGenerator::TermGenerationState::getBacktrackDestination): + (JSC::Yarr::YarrGenerator::TermGenerationState::propagateBacktrackingFrom): + (JSC::Yarr::YarrGenerator::ParenthesesTail::ParenthesesTail): + (JSC::Yarr::YarrGenerator::ParenthesesTail::processBacktracks): + (JSC::Yarr::YarrGenerator::ParenthesesTail::setNextIteration): + (JSC::Yarr::YarrGenerator::ParenthesesTail::addAfterParenJump): + (JSC::Yarr::YarrGenerator::ParenthesesTail::generateCode): + (JSC::Yarr::YarrGenerator::generateAssertionBOL): + (JSC::Yarr::YarrGenerator::generateAssertionEOL): + (JSC::Yarr::YarrGenerator::matchAssertionWordchar): + (JSC::Yarr::YarrGenerator::generateAssertionWordBoundary): + (JSC::Yarr::YarrGenerator::generatePatternCharacterSingle): + (JSC::Yarr::YarrGenerator::generatePatternCharacterPair): + (JSC::Yarr::YarrGenerator::generatePatternCharacterFixed): + (JSC::Yarr::YarrGenerator::generatePatternCharacterGreedy): + (JSC::Yarr::YarrGenerator::generatePatternCharacterNonGreedy): + (JSC::Yarr::YarrGenerator::generateCharacterClassSingle): + (JSC::Yarr::YarrGenerator::generateCharacterClassFixed): + (JSC::Yarr::YarrGenerator::generateCharacterClassGreedy): + (JSC::Yarr::YarrGenerator::generateCharacterClassNonGreedy): + (JSC::Yarr::YarrGenerator::generateParenthesesDisjunction): + (JSC::Yarr::YarrGenerator::generateParenthesesSingle): + (JSC::Yarr::YarrGenerator::generateParenthesesGreedyNoBacktrack): + (JSC::Yarr::YarrGenerator::generateParentheticalAssertion): + (JSC::Yarr::YarrGenerator::generateTerm): + (JSC::Yarr::YarrGenerator::generateDisjunction): + (JSC::Yarr::YarrGenerator::generateEnter): + (JSC::Yarr::YarrGenerator::generateReturn): + (JSC::Yarr::YarrGenerator::YarrGenerator): + (JSC::Yarr::YarrGenerator::generate): + (JSC::Yarr::YarrGenerator::compile): + (JSC::Yarr::jitCompile): + * yarr/YarrJIT.h: Renamed from Source/JavaScriptCore/yarr/RegexJIT.h. + (JSC::Yarr::YarrCodeBlock::YarrCodeBlock): + (JSC::Yarr::YarrCodeBlock::~YarrCodeBlock): + (JSC::Yarr::YarrCodeBlock::setFallBack): + (JSC::Yarr::YarrCodeBlock::isFallBack): + (JSC::Yarr::YarrCodeBlock::set): + (JSC::Yarr::YarrCodeBlock::execute): + (JSC::Yarr::YarrCodeBlock::getAddr): + (JSC::Yarr::execute): + * yarr/YarrParser.h: Renamed from Source/JavaScriptCore/yarr/RegexParser.h. + (JSC::Yarr::Parser::CharacterClassParserDelegate::CharacterClassParserDelegate): + (JSC::Yarr::Parser::CharacterClassParserDelegate::begin): + (JSC::Yarr::Parser::CharacterClassParserDelegate::atomPatternCharacter): + (JSC::Yarr::Parser::CharacterClassParserDelegate::atomBuiltInCharacterClass): + (JSC::Yarr::Parser::CharacterClassParserDelegate::end): + (JSC::Yarr::Parser::CharacterClassParserDelegate::assertionWordBoundary): + (JSC::Yarr::Parser::CharacterClassParserDelegate::atomBackReference): + (JSC::Yarr::Parser::Parser): + (JSC::Yarr::Parser::parseEscape): + (JSC::Yarr::Parser::parseAtomEscape): + (JSC::Yarr::Parser::parseCharacterClassEscape): + (JSC::Yarr::Parser::parseCharacterClass): + (JSC::Yarr::Parser::parseParenthesesBegin): + (JSC::Yarr::Parser::parseParenthesesEnd): + (JSC::Yarr::Parser::parseQuantifier): + (JSC::Yarr::Parser::parseTokens): + (JSC::Yarr::Parser::parse): + (JSC::Yarr::Parser::saveState): + (JSC::Yarr::Parser::restoreState): + (JSC::Yarr::Parser::atEndOfPattern): + (JSC::Yarr::Parser::peek): + (JSC::Yarr::Parser::peekIsDigit): + (JSC::Yarr::Parser::peekDigit): + (JSC::Yarr::Parser::consume): + (JSC::Yarr::Parser::consumeDigit): + (JSC::Yarr::Parser::consumeNumber): + (JSC::Yarr::Parser::consumeOctal): + (JSC::Yarr::Parser::tryConsume): + (JSC::Yarr::Parser::tryConsumeHex): + (JSC::Yarr::parse): + * yarr/YarrPattern.cpp: Renamed from Source/JavaScriptCore/yarr/RegexPattern.cpp. + (JSC::Yarr::CharacterClassConstructor::CharacterClassConstructor): + (JSC::Yarr::CharacterClassConstructor::reset): + (JSC::Yarr::CharacterClassConstructor::append): + (JSC::Yarr::CharacterClassConstructor::putChar): + (JSC::Yarr::CharacterClassConstructor::isUnicodeUpper): + (JSC::Yarr::CharacterClassConstructor::isUnicodeLower): + (JSC::Yarr::CharacterClassConstructor::putRange): + (JSC::Yarr::CharacterClassConstructor::charClass): + (JSC::Yarr::CharacterClassConstructor::addSorted): + (JSC::Yarr::CharacterClassConstructor::addSortedRange): + (JSC::Yarr::BeginCharHelper::BeginCharHelper): + (JSC::Yarr::BeginCharHelper::addBeginChar): + (JSC::Yarr::BeginCharHelper::merge): + (JSC::Yarr::BeginCharHelper::addCharacter): + (JSC::Yarr::BeginCharHelper::linkHotTerms): + (JSC::Yarr::YarrPatternConstructor::YarrPatternConstructor): + (JSC::Yarr::YarrPatternConstructor::~YarrPatternConstructor): + (JSC::Yarr::YarrPatternConstructor::reset): + (JSC::Yarr::YarrPatternConstructor::assertionBOL): + (JSC::Yarr::YarrPatternConstructor::assertionEOL): + (JSC::Yarr::YarrPatternConstructor::assertionWordBoundary): + (JSC::Yarr::YarrPatternConstructor::atomPatternCharacter): + (JSC::Yarr::YarrPatternConstructor::atomBuiltInCharacterClass): + (JSC::Yarr::YarrPatternConstructor::atomCharacterClassBegin): + (JSC::Yarr::YarrPatternConstructor::atomCharacterClassAtom): + (JSC::Yarr::YarrPatternConstructor::atomCharacterClassRange): + (JSC::Yarr::YarrPatternConstructor::atomCharacterClassBuiltIn): + (JSC::Yarr::YarrPatternConstructor::atomCharacterClassEnd): + (JSC::Yarr::YarrPatternConstructor::atomParenthesesSubpatternBegin): + (JSC::Yarr::YarrPatternConstructor::atomParentheticalAssertionBegin): + (JSC::Yarr::YarrPatternConstructor::atomParenthesesEnd): + (JSC::Yarr::YarrPatternConstructor::atomBackReference): + (JSC::Yarr::YarrPatternConstructor::copyDisjunction): + (JSC::Yarr::YarrPatternConstructor::copyTerm): + (JSC::Yarr::YarrPatternConstructor::quantifyAtom): + (JSC::Yarr::YarrPatternConstructor::disjunction): + (JSC::Yarr::YarrPatternConstructor::regexBegin): + (JSC::Yarr::YarrPatternConstructor::regexEnd): + (JSC::Yarr::YarrPatternConstructor::regexError): + (JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets): + (JSC::Yarr::YarrPatternConstructor::setupDisjunctionOffsets): + (JSC::Yarr::YarrPatternConstructor::setupOffsets): + (JSC::Yarr::YarrPatternConstructor::checkForTerminalParentheses): + (JSC::Yarr::YarrPatternConstructor::optimizeBOL): + (JSC::Yarr::YarrPatternConstructor::addBeginTerm): + (JSC::Yarr::YarrPatternConstructor::setupDisjunctionBeginTerms): + (JSC::Yarr::YarrPatternConstructor::setupAlternativeBeginTerms): + (JSC::Yarr::YarrPatternConstructor::setupBeginChars): + (JSC::Yarr::compile): + (JSC::Yarr::YarrPattern::YarrPattern): + * yarr/YarrPattern.h: Renamed from Source/JavaScriptCore/yarr/RegexPattern.h. + (JSC::Yarr::CharacterRange::CharacterRange): + (JSC::Yarr::CharacterClassTable::create): + (JSC::Yarr::CharacterClassTable::CharacterClassTable): + (JSC::Yarr::CharacterClass::CharacterClass): + (JSC::Yarr::PatternTerm::PatternTerm): + (JSC::Yarr::PatternTerm::ForwardReference): + (JSC::Yarr::PatternTerm::BOL): + (JSC::Yarr::PatternTerm::EOL): + (JSC::Yarr::PatternTerm::WordBoundary): + (JSC::Yarr::PatternTerm::invert): + (JSC::Yarr::PatternTerm::capture): + (JSC::Yarr::PatternTerm::quantify): + (JSC::Yarr::PatternAlternative::PatternAlternative): + (JSC::Yarr::PatternAlternative::lastTerm): + (JSC::Yarr::PatternAlternative::removeLastTerm): + (JSC::Yarr::PatternAlternative::setOnceThrough): + (JSC::Yarr::PatternAlternative::onceThrough): + (JSC::Yarr::PatternDisjunction::PatternDisjunction): + (JSC::Yarr::PatternDisjunction::~PatternDisjunction): + (JSC::Yarr::PatternDisjunction::addNewAlternative): + (JSC::Yarr::TermChain::TermChain): + (JSC::Yarr::BeginChar::BeginChar): + (JSC::Yarr::YarrPattern::~YarrPattern): + (JSC::Yarr::YarrPattern::reset): + (JSC::Yarr::YarrPattern::containsIllegalBackReference): + (JSC::Yarr::YarrPattern::newlineCharacterClass): + (JSC::Yarr::YarrPattern::digitsCharacterClass): + (JSC::Yarr::YarrPattern::spacesCharacterClass): + (JSC::Yarr::YarrPattern::wordcharCharacterClass): + (JSC::Yarr::YarrPattern::nondigitsCharacterClass): + (JSC::Yarr::YarrPattern::nonspacesCharacterClass): + (JSC::Yarr::YarrPattern::nonwordcharCharacterClass): + +2011-01-10 Gavin Barraclough <barraclough@apple.com> + + Windows build fix. + + * parser/SyntaxChecker.h: + +2011-01-10 Dave Tapuska <dtapuska@rim.com> + + Reviewed by Gavin Barraclough. + + Add CTI ASM versions for RVCT ARM THUMB2 mode. + + https://bugs.webkit.org/show_bug.cgi?id=52154 + + * jit/JITStubs.cpp: + (JSC::ctiTrampoline): + (JSC::ctiVMThrowTrampoline): + (JSC::ctiOpThrowNotCaught): + +2011-01-10 Gavin Barraclough <barraclough@apple.com> + + Qt build fix. + + * JavaScriptCore.pro: + +2011-01-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 52079 - Syntax errors should be early errors. + + From chapter 16 the spec: + An implementation must report most errors at the time the relevant ECMAScript language construct is + evaluated. An early error is an error that can be detected and reported prior to the evaluation of + any construct in the Program containing the error. An implementation must report early errors in a + Program prior to the first evaluation of that Program. Early errors in eval code are reported at + the time eval is called but prior to evaluation of any construct within the eval code. All errors + that are not early errors are runtime errors. + + An implementation must treat any instance of the following kinds of errors as an early error: + * Any syntax error." + + * JavaScriptCore.xcodeproj/project.pbxproj: + Added new files. + * bytecode/CodeBlock.cpp: + Removed op_throw_syntax_error. + * bytecode/Opcode.h: + Removed op_throw_syntax_error. + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): + If m_expressionTooDeep then throw a runtime error. + (JSC::BytecodeGenerator::BytecodeGenerator): + Initialize m_expressionTooDeep. + (JSC::BytecodeGenerator::emitThrowExpressionTooDeepException): + Sets m_expressionTooDeep. + * bytecompiler/BytecodeGenerator.h: + Added m_expressionTooDeep, removed emitThrowSyntaxError. + * bytecompiler/NodesCodegen.cpp: + (JSC::RegExpNode::emitBytecode): + (JSC::ContinueNode::emitBytecode): + (JSC::BreakNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::LabelNode::emitBytecode): + Conditions that threw syntax error are now handled during parsing; + during bytecompilation these are now just ASSERTs. + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + * jit/JITOpcodes.cpp: + * jit/JITOpcodes32_64.cpp: + * jit/JITStubs.cpp: + * jit/JITStubs.h: + Removed op_throw_syntax_error. + * parser/ASTBuilder.h: + (JSC::ASTBuilder::createRegExp): + Renamed; added syntax check. + * parser/JSParser.cpp: + (JSC::JSParser::breakIsValid): + (JSC::JSParser::hasLabel): + (JSC::JSParser::Scope::Scope): + (JSC::JSParser::Scope::setIsFunction): + (JSC::JSParser::Scope::isFunctionBoundary): + (JSC::JSParser::ScopeRef::hasContainingScope): + (JSC::JSParser::ScopeRef::containingScope): + (JSC::JSParser::AutoPopScopeRef::AutoPopScopeRef): + (JSC::JSParser::AutoPopScopeRef::~AutoPopScopeRef): + (JSC::JSParser::AutoPopScopeRef::setPopped): + (JSC::JSParser::popScopeInternal): + (JSC::JSParser::popScope): + (JSC::jsParse): + (JSC::JSParser::JSParser): + (JSC::JSParser::parseProgram): + (JSC::JSParser::parseBreakStatement): + (JSC::JSParser::parseContinueStatement): + (JSC::JSParser::parseReturnStatement): + (JSC::JSParser::parseTryStatement): + (JSC::JSParser::parseFunctionInfo): + (JSC::JSParser::parseExpressionOrLabelStatement): + (JSC::JSParser::parsePrimaryExpression): + * parser/JSParser.h: + * parser/Nodes.h: + * parser/Parser.cpp: + (JSC::Parser::parse): + * parser/SyntaxChecker.h: + (JSC::SyntaxChecker::createRegExp): + Renamed; added syntax check. + * runtime/ExceptionHelpers.cpp: + (JSC::createOutOfMemoryError): + (JSC::throwOutOfMemoryError): + * runtime/ExceptionHelpers.h: + Broke out createOutOfMemoryError. + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + (JSC::ProgramExecutable::compileInternal): + (JSC::FunctionExecutable::compileForCallInternal): + (JSC::FunctionExecutable::compileForConstructInternal): + Add check for exception after bytecode generation. + * runtime/RegExpConstructor.cpp: + (JSC::constructRegExp): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncCompile): + RegExp error prefixes not included in error string. + * yarr/RegexParser.h: + (JSC::Yarr::Parser::parse): + Removed regexBegin/regexEnd/regexError. + * yarr/RegexPattern.cpp: + (JSC::Yarr::RegexPatternConstructor::regexBegin): + Removed regexEnd/regexError. + (JSC::Yarr::compileRegex): + Add call to regexBegin (no longer called from the parser). + * yarr/YarrSyntaxChecker.cpp: Added. + (JSC::Yarr::SyntaxChecker::assertionBOL): + (JSC::Yarr::SyntaxChecker::assertionEOL): + (JSC::Yarr::SyntaxChecker::assertionWordBoundary): + (JSC::Yarr::SyntaxChecker::atomPatternCharacter): + (JSC::Yarr::SyntaxChecker::atomBuiltInCharacterClass): + (JSC::Yarr::SyntaxChecker::atomCharacterClassBegin): + (JSC::Yarr::SyntaxChecker::atomCharacterClassAtom): + (JSC::Yarr::SyntaxChecker::atomCharacterClassRange): + (JSC::Yarr::SyntaxChecker::atomCharacterClassBuiltIn): + (JSC::Yarr::SyntaxChecker::atomCharacterClassEnd): + (JSC::Yarr::SyntaxChecker::atomParenthesesSubpatternBegin): + (JSC::Yarr::SyntaxChecker::atomParentheticalAssertionBegin): + (JSC::Yarr::SyntaxChecker::atomParenthesesEnd): + (JSC::Yarr::SyntaxChecker::atomBackReference): + (JSC::Yarr::SyntaxChecker::quantifyAtom): + (JSC::Yarr::SyntaxChecker::disjunction): + (JSC::Yarr::checkSyntax): + * yarr/YarrSyntaxChecker.h: Added. + Check RegExp syntax. + +2011-01-10 Adam Roben <aroben@apple.com> + + Roll out r75289 + + It was causing assertion failures. See <http://webkit.org/b/52156>. + + * wtf/StackBounds.cpp: + (WTF::StackBounds::initialize): + +2011-01-08 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Darin Adler. + + Unify string table adding in AtomicString + https://bugs.webkit.org/show_bug.cgi?id=51927 + + Move code for adding a string into a separate function. + This removes multiple occurrence of the same logic. + + * wtf/text/AtomicString.cpp: + (WTF::addToStringTable): Added. + (WTF::AtomicString::add): Use addToStringTable(). + (WTF::AtomicString::fromUTF8): Ditto. + +2011-01-07 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Gavin Barraclough. + + Split machine stack marking functions into their own class (MachineStackMarker) + https://bugs.webkit.org/show_bug.cgi?id=52088 + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): Moved registerThread() + call behind an #ifdef because we shouldn't be registering threads at all + if we don't support usage on multiple threads. + + * Android.mk: + * CMakeLists.txt: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: Updated projects. + + * runtime/Collector.cpp: + (JSC::Heap::Heap): + (JSC::Heap::destroy): + (JSC::Heap::markRoots): + * runtime/Collector.h: + (JSC::Heap::machineStackMarker): Moved code to machineStackMarker. + + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::makeUsableFromMultipleThreads): Removed an unnecessary + level of indirection, to make Heap less of a God class. + + * runtime/MachineStackMarker.h: Copied from Source/JavaScriptCore/runtime/Collector.h. + * runtime/MachineStackMarker.cpp: Copied from Source/JavaScriptCore/runtime/Collector.cpp. + (JSC::MachineStackMarker::MachineStackMarker): + (JSC::MachineStackMarker::~MachineStackMarker): + (JSC::MachineStackMarker::makeUsableFromMultipleThreads): + (JSC::MachineStackMarker::registerThread): + (JSC::MachineStackMarker::unregisterThread): + (JSC::MachineStackMarker::markCurrentThreadConservativelyInternal): + (JSC::MachineStackMarker::markCurrentThreadConservatively): + (JSC::MachineStackMarker::markOtherThreadConservatively): + (JSC::MachineStackMarker::markMachineStackConservatively): Moved code from Heap. + 2011-01-07 Gavin Barraclough <barraclough@apple.com> Reviewed by Geoff Garen. diff --git a/Source/JavaScriptCore/Configurations/Base.xcconfig b/Source/JavaScriptCore/Configurations/Base.xcconfig index 09b6de1..a189159 100644 --- a/Source/JavaScriptCore/Configurations/Base.xcconfig +++ b/Source/JavaScriptCore/Configurations/Base.xcconfig @@ -1,4 +1,4 @@ -// Copyright (C) 2009, 2010 Apple Inc. All rights reserved. +// Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions @@ -40,7 +40,7 @@ GCC_MODEL_TUNING = $(GCC_MODEL_TUNING_$(REAL_PLATFORM_NAME)); GCC_MODEL_TUNING_macosx = G5; GCC_OBJC_CALL_CXX_CDTORS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; -GCC_PREPROCESSOR_DEFINITIONS = $(DEBUG_DEFINES) HAVE_DTRACE=$(HAVE_DTRACE) WEBKIT_VERSION_MIN_REQUIRED=WEBKIT_VERSION_LATEST $(GCC_PREPROCESSOR_DEFINITIONS); +GCC_PREPROCESSOR_DEFINITIONS = $(DEBUG_DEFINES) HAVE_DTRACE=$(HAVE_DTRACE) WEBKIT_VERSION_MIN_REQUIRED=WEBKIT_VERSION_LATEST HAVE_HEADER_DETECTION_H $(GCC_PREPROCESSOR_DEFINITIONS); GCC_STRICT_ALIASING = YES; GCC_THREADSAFE_STATICS = NO; GCC_TREAT_WARNINGS_AS_ERRORS = YES; diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make index 2e8adb4..4de4a88 100644 --- a/Source/JavaScriptCore/DerivedSources.make +++ b/Source/JavaScriptCore/DerivedSources.make @@ -1,4 +1,4 @@ -# Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. +# Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -37,20 +37,21 @@ VPATH = \ .PHONY : all all : \ ArrayPrototype.lut.h \ - chartables.c \ DatePrototype.lut.h \ + HeaderDetection.h \ JSONObject.lut.h \ + JavaScriptCore.JSVALUE32.exp \ + JavaScriptCore.JSVALUE32_64.exp \ + JavaScriptCore.JSVALUE64.exp \ Lexer.lut.h \ MathObject.lut.h \ NumberConstructor.lut.h \ RegExpConstructor.lut.h \ + RegExpJitTables.h \ RegExpObject.lut.h \ StringPrototype.lut.h \ + chartables.c \ docs/bytecode.html \ - RegExpJitTables.h \ - JavaScriptCore.JSVALUE32.exp \ - JavaScriptCore.JSVALUE32_64.exp \ - JavaScriptCore.JSVALUE64.exp \ # # lookup tables for classes @@ -68,10 +69,13 @@ chartables.c : dftables docs/bytecode.html: make-bytecode-docs.pl Interpreter.cpp perl $^ $@ -#character tables for Yarr +# character tables for Yarr + RegExpJitTables.h: create_regex_tables python $^ > $@ +# export files + JavaScriptCore.JSVALUE32.exp: JavaScriptCore.exp JavaScriptCore.JSVALUE32only.exp cat $^ > $@ @@ -80,3 +84,8 @@ JavaScriptCore.JSVALUE32_64.exp: JavaScriptCore.exp JavaScriptCore.JSVALUE32_64o JavaScriptCore.JSVALUE64.exp: JavaScriptCore.exp JavaScriptCore.JSVALUE64only.exp cat $^ > $@ + +# header detection + +HeaderDetection.h : DerivedSources.make + if [ -f $SDKROOT/System/Library/Frameworks/System.framework/PrivateHeaders/pthread_machdep.h ]; then echo "#define HAVE_PTHREAD_MACHDEP_H 1" > $@; else echo > $@; fi diff --git a/Source/JavaScriptCore/GNUmakefile.am b/Source/JavaScriptCore/GNUmakefile.am index 93f10ee..4c8d204 100644 --- a/Source/JavaScriptCore/GNUmakefile.am +++ b/Source/JavaScriptCore/GNUmakefile.am @@ -78,12 +78,15 @@ javascriptcore_sources += \ Source/JavaScriptCore/assembler/AbstractMacroAssembler.h \ Source/JavaScriptCore/assembler/ARMAssembler.cpp \ Source/JavaScriptCore/assembler/ARMAssembler.h \ + Source/JavaScriptCore/assembler/ARMv7Assembler.cpp \ + Source/JavaScriptCore/assembler/ARMv7Assembler.h \ Source/JavaScriptCore/assembler/AssemblerBuffer.h \ Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \ Source/JavaScriptCore/assembler/CodeLocation.h \ Source/JavaScriptCore/assembler/LinkBuffer.h \ Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp \ Source/JavaScriptCore/assembler/MacroAssemblerARM.h \ + Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h \ Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h \ Source/JavaScriptCore/assembler/MacroAssembler.h \ Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h \ @@ -236,8 +239,10 @@ javascriptcore_sources += \ Source/JavaScriptCore/runtime/CallData.cpp \ Source/JavaScriptCore/runtime/CallData.h \ Source/JavaScriptCore/runtime/ClassInfo.h \ - Source/JavaScriptCore/runtime/Collector.cpp \ - Source/JavaScriptCore/runtime/Collector.h \ + Source/JavaScriptCore/runtime/MarkedSpace.cpp \ + Source/JavaScriptCore/runtime/MarkedSpace.h \ + Source/JavaScriptCore/runtime/Heap.cpp \ + Source/JavaScriptCore/runtime/Heap.h \ Source/JavaScriptCore/runtime/CollectorHeapIterator.h \ Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \ Source/JavaScriptCore/runtime/CommonIdentifiers.h \ @@ -336,6 +341,8 @@ javascriptcore_sources += \ Source/JavaScriptCore/runtime/LiteralParser.h \ Source/JavaScriptCore/runtime/Lookup.cpp \ Source/JavaScriptCore/runtime/Lookup.h \ + Source/JavaScriptCore/runtime/MachineStackMarker.cpp \ + Source/JavaScriptCore/runtime/MachineStackMarker.h \ Source/JavaScriptCore/runtime/MarkStack.cpp \ Source/JavaScriptCore/runtime/MarkStack.h \ Source/JavaScriptCore/runtime/MathObject.cpp \ @@ -550,13 +557,16 @@ javascriptcore_sources += \ Source/JavaScriptCore/wtf/VMTags.h \ Source/JavaScriptCore/wtf/WTFThreadData.cpp \ Source/JavaScriptCore/wtf/WTFThreadData.h \ - Source/JavaScriptCore/yarr/RegexInterpreter.cpp \ - Source/JavaScriptCore/yarr/RegexInterpreter.h \ - Source/JavaScriptCore/yarr/RegexJIT.cpp \ - Source/JavaScriptCore/yarr/RegexJIT.h \ - Source/JavaScriptCore/yarr/RegexParser.h \ - Source/JavaScriptCore/yarr/RegexPattern.cpp \ - Source/JavaScriptCore/yarr/RegexPattern.h + Source/JavaScriptCore/yarr/Yarr.h \ + Source/JavaScriptCore/yarr/YarrInterpreter.cpp \ + Source/JavaScriptCore/yarr/YarrInterpreter.h \ + Source/JavaScriptCore/yarr/YarrJIT.cpp \ + Source/JavaScriptCore/yarr/YarrJIT.h \ + Source/JavaScriptCore/yarr/YarrParser.h \ + Source/JavaScriptCore/yarr/YarrPattern.cpp \ + Source/JavaScriptCore/yarr/YarrPattern.h \ + Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp \ + Source/JavaScriptCore/yarr/YarrSyntaxChecker.h if TARGET_WIN32 javascriptcore_sources += \ diff --git a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp index d24b083..56304fa 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp +++ b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp @@ -32,7 +32,7 @@ 'includes': [ # FIXME: Sense whether upstream or downstream build, and # include the right features.gypi - '../../../WebKit/chromium/features.gypi', + '../../../Source/WebKit/chromium/features.gypi', '../JavaScriptCore.gypi', ], 'variables': { @@ -40,7 +40,7 @@ 'conditions': [ ['inside_chromium_build==0', { # Webkit is being built outside of the full chromium project. - 'chromium_src_dir': '../../../WebKit/chromium', + 'chromium_src_dir': '../../../Source/WebKit/chromium', },{ # WebKit is checked out in src/chromium/third_party/WebKit 'chromium_src_dir': '../../../../..', diff --git a/Source/JavaScriptCore/JavaScriptCore.gypi b/Source/JavaScriptCore/JavaScriptCore.gypi index e60969e..a08b439 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gypi +++ b/Source/JavaScriptCore/JavaScriptCore.gypi @@ -182,8 +182,10 @@ 'runtime/CallData.cpp', 'runtime/CallData.h', 'runtime/ClassInfo.h', - 'runtime/Collector.cpp', - 'runtime/Collector.h', + 'runtime/MarkedSpace.cpp', + 'runtime/MarkedSpace.h', + 'runtime/Heap.cpp', + 'runtime/Heap.h', 'runtime/CollectorHeapIterator.h', 'runtime/CommonIdentifiers.cpp', 'runtime/CommonIdentifiers.h', @@ -276,6 +278,8 @@ 'runtime/LiteralParser.h', 'runtime/Lookup.cpp', 'runtime/Lookup.h', + 'runtime/MachineStackMarker.cpp', + 'runtime/MachineStackMarker.h', 'runtime/MarkStack.cpp', 'runtime/MarkStack.h', 'runtime/MarkStackWin.cpp', @@ -492,13 +496,16 @@ 'wtf/win/MainThreadWin.cpp', 'wtf/win/OwnPtrWin.cpp', 'wtf/wx/MainThreadWx.cpp', - 'yarr/RegexInterpreter.cpp', - 'yarr/RegexInterpreter.h', - 'yarr/RegexJIT.cpp', - 'yarr/RegexJIT.h', - 'yarr/RegexParser.h', - 'yarr/RegexPattern.cpp', - 'yarr/RegexPattern.h', + 'yarr/Yarr.h' + 'yarr/YarrInterpreter.cpp', + 'yarr/YarrInterpreter.h', + 'yarr/YarrJIT.cpp', + 'yarr/YarrJIT.h', + 'yarr/YarrParser.h', + 'yarr/YarrPattern.cpp', + 'yarr/YarrPattern.h', + 'yarr/YarrSyntaxChecker.cpp', + 'yarr/YarrSyntaxChecker.h', ] } } diff --git a/Source/JavaScriptCore/JavaScriptCore.pro b/Source/JavaScriptCore/JavaScriptCore.pro index 86b1b9a..ca420d2 100644 --- a/Source/JavaScriptCore/JavaScriptCore.pro +++ b/Source/JavaScriptCore/JavaScriptCore.pro @@ -127,7 +127,8 @@ SOURCES += \ runtime/BooleanObject.cpp \ runtime/BooleanPrototype.cpp \ runtime/CallData.cpp \ - runtime/Collector.cpp \ + runtime/MarkedSpace.cpp \ + runtime/Heap.cpp \ runtime/CommonIdentifiers.cpp \ runtime/Completion.cpp \ runtime/ConstructData.cpp \ @@ -174,6 +175,7 @@ SOURCES += \ runtime/JSWrapperObject.cpp \ runtime/LiteralParser.cpp \ runtime/Lookup.cpp \ + runtime/MachineStackMarker.cpp \ runtime/MarkStackPosix.cpp \ runtime/MarkStackSymbian.cpp \ runtime/MarkStackWin.cpp \ @@ -207,9 +209,10 @@ SOURCES += \ runtime/Structure.cpp \ runtime/TimeoutChecker.cpp \ runtime/UString.cpp \ - yarr/RegexPattern.cpp \ - yarr/RegexInterpreter.cpp \ - yarr/RegexJIT.cpp + yarr/YarrPattern.cpp \ + yarr/YarrInterpreter.cpp \ + yarr/YarrJIT.cpp \ + yarr/YarrSyntaxChecker.cpp # Generated files, simply list them for JavaScriptCore diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 7284362..1ddc251 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -586,11 +586,19 @@ > </File> <File - RelativePath="..\..\runtime\Collector.cpp" + RelativePath="..\..\runtime\Heap.cpp" > </File> <File - RelativePath="..\..\runtime\Collector.h" + RelativePath="..\..\runtime\Heap.h" + > + </File> + <File + RelativePath="..\..\runtime\MarkedSpace.cpp" + > + </File> + <File + RelativePath="..\..\runtime\MarkedSpace.h" > </File> <File @@ -986,6 +994,14 @@ > </File> <File + RelativePath="..\..\runtime\MachineStackMarker.cpp" + > + </File> + <File + RelativePath="..\..\runtime\MachineStackMarker.h" + > + </File> + <File RelativePath="..\..\runtime\MarkStack.cpp" > </File> @@ -1650,31 +1666,43 @@ Name="yarr" > <File - RelativePath="..\..\yarr\RegexInterpreter.cpp" + RelativePath="..\..\yarr\Yarr.h" + > + </File> + <File + RelativePath="..\..\yarr\YarrInterpreter.cpp" + > + </File> + <File + RelativePath="..\..\yarr\YarrInterpreter.h" + > + </File> + <File + RelativePath="..\..\yarr\YarrJIT.cpp" > </File> <File - RelativePath="..\..\yarr\RegexInterpreter.h" + RelativePath="..\..\yarr\YarrJIT.h" > </File> <File - RelativePath="..\..\yarr\RegexJIT.cpp" + RelativePath="..\..\yarr\YarrParser.h" > </File> <File - RelativePath="..\..\yarr\RegexJIT.h" + RelativePath="..\..\yarr\YarrPattern.cpp" > </File> <File - RelativePath="..\..\yarr\RegexParser.h" + RelativePath="..\..\yarr\YarrPattern.h" > </File> <File - RelativePath="..\..\yarr\RegexPattern.cpp" + RelativePath="..\..\yarr\YarrSyntaxChecker.cpp" > </File> <File - RelativePath="..\..\yarr\RegexPattern.h" + RelativePath="..\..\yarr\YarrSyntaxChecker.h" > </File> </Filter> diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 414f8b1..0f9b4ab 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -55,6 +55,10 @@ 140566D1107EC267005DBC8D /* JSStaticScopeObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */; }; 140566D6107EC271005DBC8D /* JSFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85E0255597D01FF60F7 /* JSFunction.cpp */; }; 140B7D1D0DC69AF7009C42B8 /* JSActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14DA818F0D99FD2000B0A4FB /* JSActivation.cpp */; }; + 140CDC7C12DC09BF0013CFC5 /* MarkedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 140CDC7612DBEA330013CFC5 /* MarkedSpace.cpp */; }; + 140CDE7012DE97A00013CFC5 /* Heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 140CDE6C12DE977E0013CFC5 /* Heap.cpp */; }; + 140CDE7112DE97B10013CFC5 /* Heap.h in Headers */ = {isa = PBXBuildFile; fileRef = 140CDE6D12DE977E0013CFC5 /* Heap.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 140CDF0C12DECE5C0013CFC5 /* MarkedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = 140CDC7712DBEA330013CFC5 /* MarkedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; }; 140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 141211310A48794D00480255 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; }; 141211340A48795800480255 /* minidom.c in Sources */ = {isa = PBXBuildFile; fileRef = 141211020A48780900480255 /* minidom.c */; }; @@ -163,6 +167,8 @@ 14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */; }; 14B3EF0512BC24DD00D29EFF /* PageBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B3EF0312BC24DD00D29EFF /* PageBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14B3EF0612BC24DD00D29EFF /* PageBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */; }; + 14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */; }; + 14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14B8EC720A5652090062BE54 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; }; 14BD59C50A3E8F9F00BAF59C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; }; 14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */; }; @@ -173,7 +179,6 @@ 14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */; settings = {ATTRIBUTES = (); }; }; 14F8BA3E107EC886009892DC /* FastMalloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */; }; 14F8BA43107EC88C009892DC /* TCSystemAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6541BD7008E80A17002CBEE7 /* TCSystemAlloc.cpp */; }; - 14F8BA4F107EC899009892DC /* Collector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8520255597D01FF60F7 /* Collector.cpp */; }; 14FFF98C12BFFF7500795BB8 /* PageAllocationAligned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14FFF98A12BFFF7500795BB8 /* PageAllocationAligned.cpp */; }; 14FFF98D12BFFF7500795BB8 /* PageAllocationAligned.h in Headers */ = {isa = PBXBuildFile; fileRef = 14FFF98B12BFFF7500795BB8 /* PageAllocationAligned.h */; settings = {ATTRIBUTES = (Private, ); }; }; 180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 180B9AF00F16C569009BDBC5 /* CurrentTime.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -187,6 +192,7 @@ 41359CF70FDD89CB00206180 /* DateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 41359CF50FDD89CB00206180 /* DateMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4409D8470FAF80A200523B87 /* OwnPtrCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 440B7AED0FAF7FCB0073323E /* OwnPtrCommon.h */; settings = {ATTRIBUTES = (Private, ); }; }; 44DD48530FAEA85000D6B4EB /* PassOwnPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 44DD48520FAEA85000D6B4EB /* PassOwnPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 451539B912DC994500EF7AC4 /* Yarr.h in Headers */ = {isa = PBXBuildFile; fileRef = 451539B812DC994500EF7AC4 /* Yarr.h */; }; 511FC4C9117EE28700425272 /* MD5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511FC4C7117EE23D00425272 /* MD5.cpp */; }; 511FC4CB117EE2A800425272 /* MD5.h in Headers */ = {isa = PBXBuildFile; fileRef = 511FC4CA117EE2A800425272 /* MD5.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5135FAF212D26ACE003C083B /* Decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5135FAD512D26856003C083B /* Decoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -219,6 +225,15 @@ 86565743115BE3DA00291F40 /* CString.h in Headers */ = {isa = PBXBuildFile; fileRef = 86565741115BE3DA00291F40 /* CString.h */; settings = {ATTRIBUTES = (Private, ); }; }; 865F408810E7D56300947361 /* APIShims.h in Headers */ = {isa = PBXBuildFile; fileRef = 865F408710E7D56300947361 /* APIShims.h */; }; 86676D5211FED9BC004B6863 /* BumpPointerAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 86676D4D11FED55D004B6863 /* BumpPointerAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */; }; + 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */; }; + 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */; }; + 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */; }; + 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */; }; + 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8012DBA33700A9FE7B /* YarrJIT.h */; }; + 86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8112DBA33700A9FE7B /* YarrParser.h */; }; + 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B8212DBA33700A9FE7B /* YarrPattern.cpp */; }; + 86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8312DBA33700A9FE7B /* YarrPattern.h */; }; 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA00117CEFD100B908B1 /* AtomicString.cpp */; }; 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA01117CEFD100B908B1 /* AtomicString.h */; settings = {ATTRIBUTES = (Private, ); }; }; 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA02117CEFD100B908B1 /* AtomicStringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -228,7 +243,6 @@ 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA15117CF19900B908B1 /* WTFString.cpp */; }; 868BFA18117CF19900B908B1 /* WTFString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA16117CF19900B908B1 /* WTFString.h */; settings = {ATTRIBUTES = (Private, ); }; }; 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA5F117D048200B908B1 /* StaticConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 868D81A212C428CE0093DC84 /* RegexPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868D81A112C428CE0093DC84 /* RegexPattern.cpp */; }; 8690231512092D5C00630AF9 /* PageReservation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8690231412092D5C00630AF9 /* PageReservation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -262,12 +276,6 @@ 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; }; 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; }; - 86EAC4970F93E8D1008EC948 /* RegexInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */; }; - 86EAC4980F93E8D1008EC948 /* RegexInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EAC4900F93E8D1008EC948 /* RegexInterpreter.h */; }; - 86EAC4990F93E8D1008EC948 /* RegexJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EAC4910F93E8D1008EC948 /* RegexJIT.cpp */; }; - 86EAC49A0F93E8D1008EC948 /* RegexJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EAC4920F93E8D1008EC948 /* RegexJIT.h */; }; - 86EAC49B0F93E8D1008EC948 /* RegexParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EAC4930F93E8D1008EC948 /* RegexParser.h */; }; - 86EAC49C0F93E8D1008EC948 /* RegexPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EAC4940F93E8D1008EC948 /* RegexPattern.h */; }; 86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F38858121130CA007A7CE3 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; }; 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; }; 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -389,7 +397,6 @@ BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 704FD35305697E6D003DBED9 /* BooleanObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */ = {isa = PBXBuildFile; fileRef = 145C507F0D9DF63B0088F6B9 /* CallData.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F00E16F5CD00B34460 /* Collator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A862AA0D7EBB7D001EC6AA /* Collator.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3F10E16F5CD00B34460 /* Collector.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8530255597D01FF60F7 /* Collector.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */ = {isa = PBXBuildFile; fileRef = 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BB2BC5030F772101FCFE1D /* Completion.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F50E16F5CD00B34460 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F68EBB8C0255D4C601FF60F7 /* config.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -660,6 +667,10 @@ 1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; }; 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; }; 14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCPtr.h; sourceTree = "<group>"; }; + 140CDC7612DBEA330013CFC5 /* MarkedSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkedSpace.cpp; sourceTree = "<group>"; }; + 140CDC7712DBEA330013CFC5 /* MarkedSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedSpace.h; sourceTree = "<group>"; }; + 140CDE6C12DE977E0013CFC5 /* Heap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Heap.cpp; sourceTree = "<group>"; }; + 140CDE6D12DE977E0013CFC5 /* Heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Heap.h; sourceTree = "<group>"; }; 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasePrivate.h; sourceTree = "<group>"; }; 141211020A48780900480255 /* minidom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = minidom.c; path = tests/minidom.c; sourceTree = "<group>"; }; 1412110D0A48788700480255 /* minidom.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = minidom.js; path = tests/minidom.js; sourceTree = "<group>"; }; @@ -725,6 +736,8 @@ 14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCallbackObject.cpp; sourceTree = "<group>"; }; 14B3EF0312BC24DD00D29EFF /* PageBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageBlock.h; sourceTree = "<group>"; }; 14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageBlock.cpp; sourceTree = "<group>"; }; + 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachineStackMarker.cpp; sourceTree = "<group>"; }; + 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineStackMarker.h; sourceTree = "<group>"; }; 14B8ECA60A5653980062BE54 /* JavaScriptCore.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.exp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; 14BD59BF0A3E8F9000BAF59C /* testapi */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testapi; sourceTree = BUILT_PRODUCTS_DIR; }; 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSContextRef.cpp; sourceTree = "<group>"; }; @@ -758,6 +771,7 @@ 440B7AED0FAF7FCB0073323E /* OwnPtrCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtrCommon.h; sourceTree = "<group>"; }; 449097EE0F8F81B50076A327 /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = "<group>"; }; 44DD48520FAEA85000D6B4EB /* PassOwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassOwnPtr.h; sourceTree = "<group>"; }; + 451539B812DC994500EF7AC4 /* Yarr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Yarr.h; path = yarr/Yarr.h; sourceTree = "<group>"; }; 45E12D8806A49B0F00E9DF84 /* jsc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsc.cpp; sourceTree = "<group>"; tabWidth = 4; }; 511FC4C7117EE23D00425272 /* MD5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD5.cpp; sourceTree = "<group>"; }; 511FC4CA117EE2A800425272 /* MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD5.h; sourceTree = "<group>"; }; @@ -837,6 +851,15 @@ 86565741115BE3DA00291F40 /* CString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CString.h; path = text/CString.h; sourceTree = "<group>"; }; 865F408710E7D56300947361 /* APIShims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIShims.h; sourceTree = "<group>"; }; 86676D4D11FED55D004B6863 /* BumpPointerAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BumpPointerAllocator.h; sourceTree = "<group>"; }; + 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrSyntaxChecker.cpp; path = yarr/YarrSyntaxChecker.cpp; sourceTree = "<group>"; }; + 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrSyntaxChecker.h; path = yarr/YarrSyntaxChecker.h; sourceTree = "<group>"; }; + 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrInterpreter.cpp; path = yarr/YarrInterpreter.cpp; sourceTree = "<group>"; }; + 86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrInterpreter.h; path = yarr/YarrInterpreter.h; sourceTree = "<group>"; }; + 86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrJIT.cpp; path = yarr/YarrJIT.cpp; sourceTree = "<group>"; }; + 86704B8012DBA33700A9FE7B /* YarrJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrJIT.h; path = yarr/YarrJIT.h; sourceTree = "<group>"; }; + 86704B8112DBA33700A9FE7B /* YarrParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrParser.h; path = yarr/YarrParser.h; sourceTree = "<group>"; }; + 86704B8212DBA33700A9FE7B /* YarrPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrPattern.cpp; path = yarr/YarrPattern.cpp; sourceTree = "<group>"; }; + 86704B8312DBA33700A9FE7B /* YarrPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrPattern.h; path = yarr/YarrPattern.h; sourceTree = "<group>"; }; 867FC35F11B763950025105E /* JavaScriptCore.JSVALUE32_64only.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.JSVALUE32_64only.exp; sourceTree = "<group>"; }; 867FC36011B763950025105E /* JavaScriptCore.JSVALUE32only.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.JSVALUE32only.exp; sourceTree = "<group>"; }; 867FC36111B763950025105E /* JavaScriptCore.JSVALUE64only.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.JSVALUE64only.exp; sourceTree = "<group>"; }; @@ -849,7 +872,6 @@ 868BFA15117CF19900B908B1 /* WTFString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WTFString.cpp; path = text/WTFString.cpp; sourceTree = "<group>"; }; 868BFA16117CF19900B908B1 /* WTFString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WTFString.h; path = text/WTFString.h; sourceTree = "<group>"; }; 868BFA5F117D048200B908B1 /* StaticConstructors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticConstructors.h; sourceTree = "<group>"; }; - 868D81A112C428CE0093DC84 /* RegexPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegexPattern.cpp; path = yarr/RegexPattern.cpp; sourceTree = "<group>"; }; 8690231412092D5C00630AF9 /* PageReservation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageReservation.h; sourceTree = "<group>"; }; 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedTranscendentalFunction.h; sourceTree = "<group>"; }; 869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; }; @@ -883,12 +905,6 @@ 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; sourceTree = "<group>"; }; 86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = "<group>"; }; 86E85538111B9968001AF51E /* JSStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringBuilder.h; sourceTree = "<group>"; }; - 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegexInterpreter.cpp; path = yarr/RegexInterpreter.cpp; sourceTree = "<group>"; }; - 86EAC4900F93E8D1008EC948 /* RegexInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexInterpreter.h; path = yarr/RegexInterpreter.h; sourceTree = "<group>"; }; - 86EAC4910F93E8D1008EC948 /* RegexJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegexJIT.cpp; path = yarr/RegexJIT.cpp; sourceTree = "<group>"; }; - 86EAC4920F93E8D1008EC948 /* RegexJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexJIT.h; path = yarr/RegexJIT.h; sourceTree = "<group>"; }; - 86EAC4930F93E8D1008EC948 /* RegexParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexParser.h; path = yarr/RegexParser.h; sourceTree = "<group>"; }; - 86EAC4940F93E8D1008EC948 /* RegexPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexPattern.h; path = yarr/RegexPattern.h; sourceTree = "<group>"; }; 86F38858121130CA007A7CE3 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicStringHash.h; path = text/AtomicStringHash.h; sourceTree = "<group>"; }; 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStatistics.cpp; sourceTree = "<group>"; }; 90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; }; @@ -1168,8 +1184,6 @@ F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayPrototype.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A84E0255597D01FF60F7 /* ArrayPrototype.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ArrayPrototype.h; sourceTree = "<group>"; tabWidth = 8; }; F692A8500255597D01FF60F7 /* BooleanObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BooleanObject.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8520255597D01FF60F7 /* Collector.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Collector.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8530255597D01FF60F7 /* Collector.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Collector.h; sourceTree = "<group>"; tabWidth = 8; }; F692A8540255597D01FF60F7 /* create_hash_table */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = text.script.perl; path = create_hash_table; sourceTree = "<group>"; tabWidth = 8; }; F692A8580255597D01FF60F7 /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Debugger.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A8590255597D01FF60F7 /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Debugger.h; sourceTree = "<group>"; tabWidth = 8; }; @@ -1667,8 +1681,6 @@ 7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = { isa = PBXGroup; children = ( - DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */, - DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */, BCF605110E203EF800B9A64D /* ArgList.cpp */, BCF605120E203EF800B9A64D /* ArgList.h */, BC257DE50E1F51C50016B6C9 /* Arguments.cpp */, @@ -1688,8 +1700,6 @@ BCA62DFE0E2826230004F30D /* CallData.cpp */, 145C507F0D9DF63B0088F6B9 /* CallData.h */, BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */, - F692A8520255597D01FF60F7 /* Collector.cpp */, - F692A8530255597D01FF60F7 /* Collector.h */, 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */, 65EA73620BAE35D1001BB560 /* CommonIdentifiers.cpp */, 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */, @@ -1722,12 +1732,16 @@ BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */, F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */, F692A85D0255597D01FF60F7 /* FunctionPrototype.h */, + DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */, + DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */, DDE82AD11209D955005C1756 /* GCHandle.cpp */, DDE82AD21209D955005C1756 /* GCHandle.h */, BC02E9B80E184545000F9297 /* GetterSetter.cpp */, BC337BDE0E1AF0B80076918A /* GetterSetter.h */, BC257DED0E1F52ED0016B6C9 /* GlobalEvalFunction.cpp */, BC257DEE0E1F52ED0016B6C9 /* GlobalEvalFunction.h */, + 140CDE6C12DE977E0013CFC5 /* Heap.cpp */, + 140CDE6D12DE977E0013CFC5 /* Heap.h */, 933A349D038AE80F008635CE /* Identifier.cpp */, 933A349A038AE7C6008635CE /* Identifier.h */, E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */, @@ -1785,6 +1799,10 @@ A7E2EA690FB460CF00601F06 /* LiteralParser.h */, F692A8680255597D01FF60F7 /* Lookup.cpp */, F692A8690255597D01FF60F7 /* Lookup.h */, + 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */, + 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */, + 140CDC7612DBEA330013CFC5 /* MarkedSpace.cpp */, + 140CDC7712DBEA330013CFC5 /* MarkedSpace.h */, A74B3498102A5F8E0032AB98 /* MarkStack.cpp */, A779558F101A74D500114E55 /* MarkStack.h */, A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */, @@ -1840,6 +1858,8 @@ 7E2C6C980D31C6B6002D44E2 /* ScopeChainMark.h */, 93303FE80E6A72B500786E6A /* SmallStrings.cpp */, 93303FEA0E6A72C000786E6A /* SmallStrings.h */, + A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */, + A730B6101250068F009D25B1 /* StrictEvalActivation.h */, BC18C3C00E16EE3300B34460 /* StringConstructor.cpp */, BC18C3C10E16EE3300B34460 /* StringConstructor.h */, BC18C3C20E16EE3300B34460 /* StringObject.cpp */, @@ -1865,8 +1885,6 @@ 14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */, 14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */, 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */, - A730B6101250068F009D25B1 /* StrictEvalActivation.h */, - A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */, ); path = runtime; sourceTree = "<group>"; @@ -1899,13 +1917,16 @@ 86EAC48C0F93E8B9008EC948 /* yarr */ = { isa = PBXGroup; children = ( - 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */, - 86EAC4900F93E8D1008EC948 /* RegexInterpreter.h */, - 86EAC4910F93E8D1008EC948 /* RegexJIT.cpp */, - 86EAC4920F93E8D1008EC948 /* RegexJIT.h */, - 86EAC4930F93E8D1008EC948 /* RegexParser.h */, - 86EAC4940F93E8D1008EC948 /* RegexPattern.h */, - 868D81A112C428CE0093DC84 /* RegexPattern.cpp */, + 451539B812DC994500EF7AC4 /* Yarr.h */, + 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */, + 86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */, + 86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */, + 86704B8012DBA33700A9FE7B /* YarrJIT.h */, + 86704B8112DBA33700A9FE7B /* YarrParser.h */, + 86704B8212DBA33700A9FE7B /* YarrPattern.cpp */, + 86704B8312DBA33700A9FE7B /* YarrPattern.h */, + 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */, + 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */, ); name = yarr; sourceTree = "<group>"; @@ -2083,6 +2104,7 @@ A784A26111D16622005776AC /* ASTBuilder.h in Headers */, BC5F7BBE11823B590052C02C /* Atomics.h in Headers */, 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */, + 86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */, 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */, BC18C3EB0E16F5CD00B34460 /* AVLTree.h in Headers */, 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */, @@ -2091,7 +2113,6 @@ 86676D5211FED9BC004B6863 /* BumpPointerAllocator.h in Headers */, A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */, 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */, - FDA15C1E12B0305C003A583A /* Complex.h in Headers */, 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */, BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */, 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */, @@ -2100,13 +2121,12 @@ 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */, 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */, BC18C3F00E16F5CD00B34460 /* Collator.h in Headers */, - BC18C3F10E16F5CD00B34460 /* Collector.h in Headers */, 14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */, BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */, BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */, + FDA15C1E12B0305C003A583A /* Complex.h in Headers */, BC18C3F50E16F5CD00B34460 /* config.h in Headers */, BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */, - 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */, 0BDFFAE00FC6192900D69EF4 /* CrossThreadRefCounted.h in Headers */, 86565743115BE3DA00291F40 /* CString.h in Headers */, 180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */, @@ -2120,9 +2140,12 @@ BC18C3FA0E16F5CD00B34460 /* Debugger.h in Headers */, BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */, BC18C3FB0E16F5CD00B34460 /* DebuggerCallFrame.h in Headers */, + 862AF4B612239C7B0024E5B8 /* DecimalNumber.h in Headers */, + 5135FAF212D26ACE003C083B /* Decoder.h in Headers */, BC18C3FC0E16F5CD00B34460 /* Deque.h in Headers */, BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */, BC18C3FE0E16F5CD00B34460 /* dtoa.h in Headers */, + 5135FAF312D26AD1003C083B /* Encoder.h in Headers */, BC3046070E1F497F003232CF /* Error.h in Headers */, BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */, BC02E98D0E183E38000F9297 /* ErrorInstance.h in Headers */, @@ -2137,6 +2160,8 @@ BC18C4030E16F5CD00B34460 /* Forward.h in Headers */, BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */, BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */, + DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */, + DDE82AD81209D955005C1756 /* GCHandle.h in Headers */, BC18C4060E16F5CD00B34460 /* GetPtr.h in Headers */, BC257DF00E1F52ED0016B6C9 /* GlobalEvalFunction.h in Headers */, BC18C4080E16F5CD00B34460 /* HashCountedSet.h in Headers */, @@ -2146,6 +2171,7 @@ BC18C40C0E16F5CD00B34460 /* HashSet.h in Headers */, BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */, BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */, + 140CDE7112DE97B10013CFC5 /* Heap.h in Headers */, BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */, BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */, 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */, @@ -2214,6 +2240,7 @@ A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */, BC18C4360E16F5CD00B34460 /* Locker.h in Headers */, BC18C4370E16F5CD00B34460 /* Lookup.h in Headers */, + 14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */, 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */, 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */, 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */, @@ -2224,11 +2251,13 @@ 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */, BC18C4390E16F5CD00B34460 /* MainThread.h in Headers */, BC18C43A0E16F5CD00B34460 /* MallocZoneSupport.h in Headers */, + 140CDF0C12DECE5C0013CFC5 /* MarkedSpace.h in Headers */, A7795590101A74D500114E55 /* MarkStack.h in Headers */, BC18C43B0E16F5CD00B34460 /* MathExtras.h in Headers */, BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */, BC18C52A0E16FCC200B34460 /* MathObject.lut.h in Headers */, 511FC4CB117EE2A800425272 /* MD5.h in Headers */, + 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */, BC18C43E0E16F5CD00B34460 /* MessageQueue.h in Headers */, 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */, BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */, @@ -2236,9 +2265,10 @@ A76EE6590FAE59D5003F069A /* NativeFunctionWrapper.h in Headers */, 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */, BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */, - 65E1A3DF122B894500B26097 /* NonCopyingSort.h in Headers */, BC18C4400E16F5CD00B34460 /* Noncopyable.h in Headers */, + 65E1A3DF122B894500B26097 /* NonCopyingSort.h in Headers */, C0A272630E50A06300E96E15 /* NotFound.h in Headers */, + 933F5CDC1269229B0049191E /* NullPtr.h in Headers */, BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */, BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */, BC18C4430E16F5CD00B34460 /* NumberObject.h in Headers */, @@ -2249,14 +2279,20 @@ E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */, 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */, BC18C4480E16F5CD00B34460 /* Operations.h in Headers */, + 1400067712A6F7830064D123 /* OSAllocator.h in Headers */, BC18C4490E16F5CD00B34460 /* OwnArrayPtr.h in Headers */, + BCFBE698122561D200309E9D /* OwnArrayPtrCommon.h in Headers */, 0BDFFAE10FC6193100D69EF4 /* OwnFastMallocPtr.h in Headers */, BC18C44A0E16F5CD00B34460 /* OwnPtr.h in Headers */, 4409D8470FAF80A200523B87 /* OwnPtrCommon.h in Headers */, 8627E5EC11F1281900A313B5 /* PageAllocation.h in Headers */, + 14FFF98D12BFFF7500795BB8 /* PageAllocationAligned.h in Headers */, + 14B3EF0512BC24DD00D29EFF /* PageBlock.h in Headers */, 8690231512092D5C00630AF9 /* PageReservation.h in Headers */, + 9714AF5F122F32070092D9F5 /* ParsedURL.h in Headers */, BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */, 93052C350FB792190048FDC3 /* ParserArena.h in Headers */, + BCFBE696122560E800309E9D /* PassOwnArrayPtr.h in Headers */, 44DD48530FAEA85000D6B4EB /* PassOwnPtr.h in Headers */, BC18C44C0E16F5CD00B34460 /* PassRefPtr.h in Headers */, BC18C44D0E16F5CD00B34460 /* pcre.h in Headers */, @@ -2277,15 +2313,12 @@ 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */, 088FA5BC0EF76D4300578E6F /* RandomNumber.h in Headers */, 08E279E90EF83B10007DB523 /* RandomNumberSeed.h in Headers */, + 9714AF4B122F289A0092D9F5 /* RawURLBuffer.h in Headers */, BC18C4570E16F5CD00B34460 /* RefCounted.h in Headers */, 90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */, BC18C4580E16F5CD00B34460 /* RefPtr.h in Headers */, BC18C4590E16F5CD00B34460 /* RefPtrHashMap.h in Headers */, - 86EAC4980F93E8D1008EC948 /* RegexInterpreter.h in Headers */, - 86EAC49A0F93E8D1008EC948 /* RegexJIT.h in Headers */, BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */, - 86EAC49B0F93E8D1008EC948 /* RegexParser.h in Headers */, - 86EAC49C0F93E8D1008EC948 /* RegexPattern.h in Headers */, A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */, BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */, BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */, @@ -2310,6 +2343,7 @@ 86D87DDB12BCAF94008E73A1 /* StackBounds.h in Headers */, 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */, FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */, + A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */, 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */, 081469491264378500DFF935 /* StringBuilder.h in Headers */, 08CABBA61265AB3900B206CE /* StringConcatenate.h in Headers */, @@ -2334,6 +2368,7 @@ BC18C46E0E16F5CD00B34460 /* TCSpinLock.h in Headers */, BC18C46F0E16F5CD00B34460 /* TCSystemAlloc.h in Headers */, 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */, + F3BD31ED126735770065467F /* TextPosition.h in Headers */, 18BAB55410DAE066000D945B /* ThreadIdentifierDataPthreads.h in Headers */, BC18C4700E16F5CD00B34460 /* Threading.h in Headers */, BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */, @@ -2347,6 +2382,11 @@ BC18C4730E16F5CD00B34460 /* Unicode.h in Headers */, BC18C4740E16F5CD00B34460 /* UnicodeIcu.h in Headers */, BC18C4750E16F5CD00B34460 /* UnusedParam.h in Headers */, + 9714AF4C122F289A0092D9F5 /* URLBuffer.h in Headers */, + 9714AF4D122F289A0092D9F5 /* URLComponent.h in Headers */, + 9714AF4E122F289A0092D9F5 /* URLParser.h in Headers */, + 9714AF4F122F289A0092D9F5 /* URLSegments.h in Headers */, + 9714AF60122F32070092D9F5 /* URLString.h in Headers */, BC18C4760E16F5CD00B34460 /* UString.h in Headers */, 08DDA5C11264631700751732 /* UStringBuilder.h in Headers */, BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */, @@ -2361,28 +2401,13 @@ 868BFA18117CF19900B908B1 /* WTFString.h in Headers */, 86D08D5411793613006E5ED0 /* WTFThreadData.h in Headers */, 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, - DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */, - DDE82AD81209D955005C1756 /* GCHandle.h in Headers */, - 86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */, - 862AF4B612239C7B0024E5B8 /* DecimalNumber.h in Headers */, - BCFBE696122560E800309E9D /* PassOwnArrayPtr.h in Headers */, - BCFBE698122561D200309E9D /* OwnArrayPtrCommon.h in Headers */, - 9714AF4B122F289A0092D9F5 /* RawURLBuffer.h in Headers */, - 9714AF4C122F289A0092D9F5 /* URLBuffer.h in Headers */, - 9714AF4D122F289A0092D9F5 /* URLComponent.h in Headers */, - 9714AF4E122F289A0092D9F5 /* URLParser.h in Headers */, - 9714AF4F122F289A0092D9F5 /* URLSegments.h in Headers */, - 9714AF5F122F32070092D9F5 /* ParsedURL.h in Headers */, - 9714AF60122F32070092D9F5 /* URLString.h in Headers */, - 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */, - A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */, - 933F5CDC1269229B0049191E /* NullPtr.h in Headers */, - F3BD31ED126735770065467F /* TextPosition.h in Headers */, - 1400067712A6F7830064D123 /* OSAllocator.h in Headers */, - 14B3EF0512BC24DD00D29EFF /* PageBlock.h in Headers */, - 14FFF98D12BFFF7500795BB8 /* PageAllocationAligned.h in Headers */, - 5135FAF212D26ACE003C083B /* Decoder.h in Headers */, - 5135FAF312D26AD1003C083B /* Encoder.h in Headers */, + 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */, + 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */, + 86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */, + 86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */, + 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */, + 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */, + 451539B912DC994500EF7AC4 /* Yarr.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2679,7 +2704,6 @@ 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */, E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */, E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */, - 14F8BA4F107EC899009892DC /* Collector.cpp in Sources */, 147F39C1107EC37600427A48 /* CommonIdentifiers.cpp in Sources */, 147F39C2107EC37600427A48 /* Completion.cpp in Sources */, 1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */, @@ -2711,6 +2735,7 @@ 14280855107EC0E70013E7B2 /* GetterSetter.cpp in Sources */, 147F39CD107EC37600427A48 /* GlobalEvalFunction.cpp in Sources */, 65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */, + 140CDE7012DE97A00013CFC5 /* Heap.cpp in Sources */, 147F39CE107EC37600427A48 /* Identifier.cpp in Sources */, E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */, 147F39CF107EC37600427A48 /* InternalFunction.cpp in Sources */, @@ -2765,9 +2790,11 @@ 148F21B0107EC5410042EC2C /* Lexer.cpp in Sources */, A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */, 14469DDE107EC7E700650446 /* Lookup.cpp in Sources */, + 14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */, 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */, 06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */, 06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */, + 140CDC7C12DC09BF0013CFC5 /* MarkedSpace.cpp in Sources */, A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */, A7C530E4102A3813005BC741 /* MarkStackPosix.cpp in Sources */, 14469DDF107EC7E700650446 /* MathObject.cpp in Sources */, @@ -2777,6 +2804,7 @@ 14469DE1107EC7E700650446 /* NativeErrorPrototype.cpp in Sources */, 148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */, 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */, + 93854A9A12C93D3B00DAAF77 /* NullPtr.cpp in Sources */, 14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */, 14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */, 14469DE4107EC7E700650446 /* NumberPrototype.cpp in Sources */, @@ -2807,13 +2835,10 @@ 14469DE9107EC7E700650446 /* PrototypeFunction.cpp in Sources */, 088FA5BB0EF76D4300578E6F /* RandomNumber.cpp in Sources */, 905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */, - 86EAC4970F93E8D1008EC948 /* RegexInterpreter.cpp in Sources */, - 86EAC4990F93E8D1008EC948 /* RegexJIT.cpp in Sources */, 14280841107EC0930013E7B2 /* RegExp.cpp in Sources */, A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */, 14280842107EC0930013E7B2 /* RegExpConstructor.cpp in Sources */, 14280843107EC0930013E7B2 /* RegExpObject.cpp in Sources */, - 868D81A212C428CE0093DC84 /* RegexPattern.cpp in Sources */, 14280844107EC0930013E7B2 /* RegExpPrototype.cpp in Sources */, 1428083A107EC0750013E7B2 /* RegisterFile.cpp in Sources */, 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */, @@ -2821,9 +2846,9 @@ 14469DEA107EC7E700650446 /* ScopeChain.cpp in Sources */, 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */, 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */, + 86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */, A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */, 86438FC41265503E00E0DFCA /* StringBuilder.cpp in Sources */, - 86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */, 14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */, 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */, 14469DEC107EC7E700650446 /* StringObject.cpp in Sources */, @@ -2844,7 +2869,10 @@ E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */, 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */, 86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */, - 93854A9A12C93D3B00DAAF77 /* NullPtr.cpp in Sources */, + 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */, + 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */, + 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */, + 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index cbae990..f3f5f27 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -1197,11 +1197,6 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printf("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data()); break; } - case op_throw_syntax_error: { - int k0 = (++it)->u.operand; - printf("[%4d] throw_syntax_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data()); - break; - } case op_jsr: { int retAddrDst = (++it)->u.operand; int offset = (++it)->u.operand; diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h index 6c1c6b2..8082ae0 100644 --- a/Source/JavaScriptCore/bytecode/Opcode.h +++ b/Source/JavaScriptCore/bytecode/Opcode.h @@ -185,7 +185,6 @@ namespace JSC { macro(op_catch, 2) \ macro(op_throw, 2) \ macro(op_throw_reference_error, 2) \ - macro(op_throw_syntax_error, 2) \ \ macro(op_jsr, 3) \ macro(op_sret, 2) \ diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 3a99957..34afb52 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -137,7 +137,7 @@ bool BytecodeGenerator::dumpsGeneratedCode() #endif } -void BytecodeGenerator::generate() +JSObject* BytecodeGenerator::generate() { m_codeBlock->setThisRegister(m_thisRegister.index()); @@ -154,6 +154,10 @@ void BytecodeGenerator::generate() symbolTable().clear(); m_codeBlock->shrinkToFit(); + + if (m_expressionTooDeep) + return createOutOfMemoryError(m_scopeChain->globalObject()); + return 0; } bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0) @@ -222,6 +226,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const ScopeChain& , m_usesExceptions(false) , m_regeneratingForExceptionInfo(false) , m_codeBlockBeingRegeneratedFrom(0) + , m_expressionTooDeep(false) { if (m_shouldEmitDebugHooks) m_codeBlock->setNeedsFullScopeChain(true); @@ -316,6 +321,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Scope , m_usesExceptions(false) , m_regeneratingForExceptionInfo(false) , m_codeBlockBeingRegeneratedFrom(0) + , m_expressionTooDeep(false) { if (m_shouldEmitDebugHooks) m_codeBlock->setNeedsFullScopeChain(true); @@ -481,6 +487,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const ScopeChain& scope , m_usesExceptions(false) , m_regeneratingForExceptionInfo(false) , m_codeBlockBeingRegeneratedFrom(0) + , m_expressionTooDeep(false) { if (m_shouldEmitDebugHooks || m_baseScopeDepth) m_codeBlock->setNeedsFullScopeChain(true); @@ -2053,12 +2060,6 @@ void BytecodeGenerator::emitThrowReferenceError(const UString& message) instructions().append(addConstantValue(jsString(globalData(), message))->index()); } -void BytecodeGenerator::emitThrowSyntaxError(const UString& message) -{ - emitOpcode(op_throw_syntax_error); - instructions().append(addConstantValue(jsString(globalData(), message))->index()); -} - PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally) { size_t begin = instructions().size(); @@ -2210,8 +2211,7 @@ RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException() // And we could make the caller pass the node pointer in, if there was some way of getting // that from an arbitrary node. However, calling emitExpressionInfo without any useful data // is still good enough to get us an accurate line number. - emitExpressionInfo(0, 0, 0); - emitThrowSyntaxError("Expression too deep"); + m_expressionTooDeep = true; return newTemporary(); } diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 37756fa..8b0cc40 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -102,7 +102,7 @@ namespace JSC { bool isConstructor() { return m_codeBlock->m_isConstructor; } - void generate(); + JSObject* generate(); // Returns the register corresponding to a local variable, or 0 if no // such register exists. Registers returned by registerFor do not @@ -364,7 +364,6 @@ namespace JSC { } void emitThrowReferenceError(const UString& message); - void emitThrowSyntaxError(const UString& message); void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value); @@ -581,6 +580,7 @@ namespace JSC { bool m_usesExceptions; bool m_regeneratingForExceptionInfo; CodeBlock* m_codeBlockBeingRegeneratedFrom; + bool m_expressionTooDeep; }; } diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp index a850c96..2875434 100644 --- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -83,13 +83,6 @@ RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& return generator.newTemporary(); } -RegisterID* ThrowableExpressionData::emitThrowSyntaxError(BytecodeGenerator& generator, const UString& message) -{ - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitThrowSyntaxError(message); - return generator.newTemporary(); -} - // ------------------------------ NullNode ------------------------------------- RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) @@ -130,11 +123,10 @@ RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegExp> regExp = generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), m_flags.ustring()); - if (!regExp->isValid()) - return emitThrowSyntaxError(generator, makeUString("Invalid regular expression: ", regExp->errorMessage())); if (dst == generator.ignoredResult()) return 0; + RefPtr<RegExp> regExp = generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), m_flags.ustring()); + ASSERT(regExp->isValid()); return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); } @@ -1641,12 +1633,7 @@ RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); LabelScope* scope = generator.continueTarget(m_ident); - - if (!scope) { - if (m_ident.isEmpty()) - return emitThrowSyntaxError(generator, "Invalid continue statement."); - return emitThrowSyntaxError(generator, makeUString("Undefined label: '", m_ident.ustring(), "'.")); - } + ASSERT(scope); generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth()); return dst; @@ -1660,12 +1647,7 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); LabelScope* scope = generator.breakTarget(m_ident); - - if (!scope) { - if (m_ident.isEmpty()) - return emitThrowSyntaxError(generator, "Invalid break statement."); - return emitThrowSyntaxError(generator, makeUString("Undefined label: '", m_ident.ustring(), "'.")); - } + ASSERT(scope); generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth()); return dst; @@ -1676,8 +1658,7 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - if (generator.codeType() != FunctionCode) - return emitThrowSyntaxError(generator, "Invalid return statement."); + ASSERT(generator.codeType() == FunctionCode); if (dst == generator.ignoredResult()) dst = 0; @@ -1882,8 +1863,7 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - if (generator.breakTarget(m_name)) - return emitThrowSyntaxError(generator, makeUString("Duplicate label: ", m_name.ustring(), ".")); + ASSERT(!generator.breakTarget(m_name)); RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); RegisterID* r0 = generator.emitNode(dst, m_statement); diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 57c068a..cf9f8a1 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -35,7 +35,7 @@ #include "CallFrame.h" #include "CallFrameClosure.h" #include "CodeBlock.h" -#include "Collector.h" +#include "Heap.h" #include "Debugger.h" #include "DebuggerCallFrame.h" #include "ErrorInstance.h" @@ -4632,17 +4632,6 @@ skip_id_custom_self: exceptionValue = JSValue(createReferenceError(callFrame, message)); goto vm_throw; } - DEFINE_OPCODE(op_throw_syntax_error) { - /* op_throw_syntax_error message(k) - - Constructs a new syntax Error instance using the - original constructor, using constant message as the - message string. The result is thrown. - */ - UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame); - exceptionValue = JSValue(createSyntaxError(callFrame, message)); - goto vm_throw; - } DEFINE_OPCODE(op_end) { /* end result(r) diff --git a/Source/JavaScriptCore/interpreter/RegisterFile.h b/Source/JavaScriptCore/interpreter/RegisterFile.h index 51a5bdf..f2e6553 100644 --- a/Source/JavaScriptCore/interpreter/RegisterFile.h +++ b/Source/JavaScriptCore/interpreter/RegisterFile.h @@ -29,7 +29,7 @@ #ifndef RegisterFile_h #define RegisterFile_h -#include "Collector.h" +#include "Heap.h" #include "ExecutableAllocator.h" #include "Register.h" #include "WeakGCPtr.h" diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.h b/Source/JavaScriptCore/jit/ExecutableAllocator.h index d45f294..3233412 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocator.h +++ b/Source/JavaScriptCore/jit/ExecutableAllocator.h @@ -231,8 +231,8 @@ public: #elif CPU(MIPS) static void cacheFlush(void* code, size_t size) { -#if COMPILER(GCC) && GCC_VERSION_AT_LEAST(4,3,0) -#if WTF_MIPS_ISA_REV(2) && !GCC_VERSION_AT_LEAST(4,4,3) +#if GCC_VERSION_AT_LEAST(4, 3, 0) +#if WTF_MIPS_ISA_REV(2) && !GCC_VERSION_AT_LEAST(4, 4, 3) int lineSize; asm("rdhwr %0, $1" : "=r" (lineSize)); // diff --git a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index e280b2d..9fc889e 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -38,14 +38,34 @@ #include <wtf/PageReservation.h> #include <wtf/VMTags.h> -#if CPU(X86_64) - // These limits suitable on 64-bit platforms (particularly x86-64, where we require all jumps to have a 2Gb max range). - #define VM_POOL_SIZE (2u * 1024u * 1024u * 1024u) // 2Gb - #define COALESCE_LIMIT (16u * 1024u * 1024u) // 16Mb +#if OS(LINUX) +#include <stdio.h> +#endif + +static const unsigned vmPoolSizeOvercommit = 2u * 1024u * 1024u * 1024u; // 2Gb +static const unsigned coalesceLimitOvercommit = 16u * 1024u * 1024u; // 16Mb + +static const unsigned vmPoolSizeNoOvercommit = 32u * 1024u * 1024u; // 32Mb +static const unsigned coalesceLimitNoOvercommit = 4u * 1024u * 1024u; // 4Mb + +static const unsigned vmPoolSizeEmbedded = 16u * 1024u * 1024u; // 16Mb +static const unsigned coalesceLimitEmbedded = 4u * 1024u * 1024u; // 4Mb + +#if CPU(X86_64) && !OS(LINUX) +// These limits suitable on 64-bit platforms (particularly x86-64, +// where we require all jumps to have a 2Gb max range). We don't +// enable this by default on Linux, since it needs overcommit and +// distros commonly disable that feature. We'll check the value +// for the overcommit feature at runtime and re-assign the Generic +// values if it's enabled. +static unsigned vmPoolSize = vmPoolSizeOvercommit; +static unsigned coalesceLimit = coalesceLimitOvercommit; +#elif CPU(ARM) +static unsigned vmPoolSize = vmPoolSizeEmbedded; +static unsigned coalesceLimit = coalesceLimitEmbedded; #else - // These limits are hopefully sensible on embedded platforms. - #define VM_POOL_SIZE (32u * 1024u * 1024u) // 32Mb - #define COALESCE_LIMIT (4u * 1024u * 1024u) // 4Mb +static unsigned vmPoolSize = vmPoolSizeNoOvercommit; +static unsigned coalesceLimit = coalesceLimitNoOvercommit; #endif using namespace WTF; @@ -315,7 +335,7 @@ public: // 16MB of allocations have been freed, sweep m_freeList // coalescing any neighboring fragments. m_countFreedSinceLastCoalesce += size; - if (m_countFreedSinceLastCoalesce >= COALESCE_LIMIT) { + if (m_countFreedSinceLastCoalesce >= coalesceLimit) { m_countFreedSinceLastCoalesce = 0; coalesceFreeSpace(); } @@ -433,11 +453,34 @@ void ExecutableAllocator::intializePageSize() static FixedVMPoolAllocator* allocator = 0; static size_t allocatedCount = 0; +#if OS(LINUX) +static void maybeModifyVMPoolSize() +{ + FILE* fp = fopen("/proc/sys/vm/overcommit_memory", "r"); + if (!fp) + return; + + unsigned overcommit = 0; + if (fscanf(fp, "%u", &overcommit) == 1) { + if (overcommit == 1) { + vmPoolSize = vmPoolSizeOvercommit; + coalesceLimit = coalesceLimitOvercommit; + } + } + + fclose(fp); +} +#endif + bool ExecutableAllocator::isValid() const { SpinLockHolder lock_holder(&spinlock); - if (!allocator) - allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, VM_POOL_SIZE); + if (!allocator) { +#if OS(LINUX) + maybeModifyVMPoolSize(); +#endif + allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, vmPoolSize); + } return allocator->isValid(); } @@ -445,7 +488,7 @@ bool ExecutableAllocator::underMemoryPressure() { // Technically we should take the spin lock here, but we don't care if we get stale data. // This is only really a heuristic anyway. - return allocatedCount > (VM_POOL_SIZE / 2); + return allocatedCount > (vmPoolSize / 2); } ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size) diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp index 01401a7..89b1e30 100644 --- a/Source/JavaScriptCore/jit/JIT.cpp +++ b/Source/JavaScriptCore/jit/JIT.cpp @@ -318,7 +318,6 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_tear_off_arguments) DEFINE_OP(op_throw) DEFINE_OP(op_throw_reference_error) - DEFINE_OP(op_throw_syntax_error) DEFINE_OP(op_to_jsnumber) DEFINE_OP(op_to_primitive) @@ -490,7 +489,6 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) privateCompileSlowCases(); Label arityCheck; - Call callArityCheck; if (m_codeBlock->codeType() == FunctionCode) { registerFileCheck.link(this); m_bytecodeOffset = 0; @@ -505,8 +503,9 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); branch32(Equal, regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this); restoreArgumentReference(); - callArityCheck = call(); - move(regT0, callFrameRegister); + + JITStubCall(this, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck).call(callFrameRegister); + jump(beginLabel); } @@ -586,10 +585,8 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation; } - if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck) { - patchBuffer.link(callArityCheck, FunctionPtr(m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck)); + if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck) *functionEntryArityCheck = patchBuffer.locationOf(arityCheck); - } return patchBuffer.finalizeCode(); } diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h index 907a774..45ed436 100644 --- a/Source/JavaScriptCore/jit/JIT.h +++ b/Source/JavaScriptCore/jit/JIT.h @@ -829,7 +829,6 @@ namespace JSC { void emit_op_tear_off_arguments(Instruction*); void emit_op_throw(Instruction*); void emit_op_throw_reference_error(Instruction*); - void emit_op_throw_syntax_error(Instruction*); void emit_op_to_jsnumber(Instruction*); void emit_op_to_primitive(Instruction*); void emit_op_unexpected_load(Instruction*); diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index 972b879..98cb2f3 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -1147,13 +1147,6 @@ void JIT::emit_op_throw_reference_error(Instruction* currentInstruction) stubCall.call(); } -void JIT::emit_op_throw_syntax_error(Instruction* currentInstruction) -{ - JITStubCall stubCall(this, cti_op_throw_syntax_error); - stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand)))); - stubCall.call(); -} - void JIT::emit_op_debug(Instruction* currentInstruction) { #if ENABLE(DEBUG_WITH_BREAKPOINT) diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index 5a0aae5..dda74c8 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -1494,15 +1494,6 @@ void JIT::emit_op_throw_reference_error(Instruction* currentInstruction) stubCall.call(); } -void JIT::emit_op_throw_syntax_error(Instruction* currentInstruction) -{ - unsigned message = currentInstruction[1].u.operand; - - JITStubCall stubCall(this, cti_op_throw_syntax_error); - stubCall.addArgument(m_codeBlock->getConstant(message)); - stubCall.call(); -} - void JIT::emit_op_debug(Instruction* currentInstruction) { #if ENABLE(DEBUG_WITH_BREAKPOINT) diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index 0959a6e..ded3428 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> - * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,7 +36,7 @@ #include "Arguments.h" #include "CallFrame.h" #include "CodeBlock.h" -#include "Collector.h" +#include "Heap.h" #include "Debugger.h" #include "ExceptionHelpers.h" #include "GetterSetter.h" @@ -737,6 +737,54 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "mov pc, lr" "\n" ); +#elif COMPILER(RVCT) && CPU(ARM_THUMB2) + +__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*) +{ + PRESERVE8 + sub sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET + str lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] + str r4, [sp, # PRESERVED_R4_OFFSET ] + str r5, [sp, # PRESERVED_R5_OFFSET ] + str r6, [sp, # PRESERVED_R6_OFFSET ] + str r1, [sp, # REGISTER_FILE_OFFSET ] + str r2, [sp, # CALLFRAME_OFFSET ] + str r3, [sp, # EXCEPTION_OFFSET ] + cpy r5, r2 + mov r6, #512 + blx r0 + ldr r6, [sp, # PRESERVED_R6_OFFSET ] + ldr r5, [sp, # PRESERVED_R5_OFFSET ] + ldr r4, [sp, # PRESERVED_R4_OFFSET ] + ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] + add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET + bx lr +} + +__asm void ctiVMThrowTrampoline() +{ + PRESERVE8 + cpy r0, sp + bl cti_vm_throw + ldr r6, [sp, # PRESERVED_R6_OFFSET ] + ldr r5, [sp, # PRESERVED_R5_OFFSET ] + ldr r4, [sp, # PRESERVED_R4_OFFSET ] + ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] + add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET + bx lr +} + +__asm void ctiOpThrowNotCaught() +{ + PRESERVE8 + ldr r6, [sp, # PRESERVED_R6_OFFSET ] + ldr r5, [sp, # PRESERVED_R5_OFFSET ] + ldr r4, [sp, # PRESERVED_R4_OFFSET ] + ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] + add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET + bx lr +} + #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL) __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*) @@ -1383,7 +1431,7 @@ DEFINE_STUB_FUNCTION(void*, register_file_check) // Rewind to the previous call frame because op_call already optimistically // moved the call frame forward. CallFrame* oldCallFrame = callFrame->callerFrame(); - ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(oldCallFrame->returnPC())); + ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(callFrame->returnPC())); STUB_SET_RETURN_ADDRESS(handler.catchRoutine); callFrame = handler.callFrame; } @@ -3567,16 +3615,6 @@ DEFINE_STUB_FUNCTION(void, op_throw_reference_error) VM_THROW_EXCEPTION_AT_END(); } -DEFINE_STUB_FUNCTION(void, op_throw_syntax_error) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - CallFrame* callFrame = stackFrame.callFrame; - UString message = stackFrame.args[0].jsValue().toString(callFrame); - stackFrame.globalData->exception = createSyntaxError(callFrame, message); - VM_THROW_EXCEPTION_AT_END(); -} - DEFINE_STUB_FUNCTION(void, op_debug) { STUB_INIT_STACK_FRAME(stackFrame); diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h index 937134b..66edf45 100644 --- a/Source/JavaScriptCore/jit/JITStubs.h +++ b/Source/JavaScriptCore/jit/JITStubs.h @@ -394,7 +394,6 @@ extern "C" { void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION); - void JIT_STUB cti_op_throw_syntax_error(STUB_ARGS_DECLARATION); void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION); void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION); void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION); diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h index 04cf272..337c87e 100644 --- a/Source/JavaScriptCore/parser/ASTBuilder.h +++ b/Source/JavaScriptCore/parser/ASTBuilder.h @@ -80,6 +80,13 @@ public: { m_scopes.append(Scope(globalData)); } + + struct BinaryExprContext { + BinaryExprContext(ASTBuilder&) {} + }; + struct UnaryExprContext { + UnaryExprContext(ASTBuilder&) {} + }; typedef SyntaxChecker FunctionBodyBuilder; @@ -208,8 +215,10 @@ public: return node; } - ExpressionNode* createRegex(const Identifier& pattern, const Identifier& flags, int start) + ExpressionNode* createRegExp(const Identifier& pattern, const Identifier& flags, int start) { + if (Yarr::checkSyntax(pattern.ustring())) + return 0; RegExpNode* node = new (m_globalData) RegExpNode(m_globalData, pattern, flags); int size = pattern.length() + 2; // + 2 for the two /'s setExceptionLocation(node, start, start + size, start + size); diff --git a/Source/JavaScriptCore/parser/JSParser.cpp b/Source/JavaScriptCore/parser/JSParser.cpp index 4201555..37b7f90 100644 --- a/Source/JavaScriptCore/parser/JSParser.cpp +++ b/Source/JavaScriptCore/parser/JSParser.cpp @@ -68,7 +68,7 @@ COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); class JSParser { public: JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*); - bool parseProgram(); + const char* parseProgram(); private: struct AllowInOverride { AllowInOverride(JSParser* parser) @@ -84,6 +84,16 @@ private: JSParser* m_parser; bool m_oldAllowsIn; }; + + struct ScopeLabelInfo { + ScopeLabelInfo(StringImpl* ident, bool isLoop) + : m_ident(ident) + , m_isLoop(isLoop) + { + } + StringImpl* m_ident; + bool m_isLoop; + }; void next(Lexer::LexType lexType = Lexer::IdentifyReservedWords) { @@ -91,7 +101,11 @@ private: m_lastTokenEnd = m_token.m_info.endOffset; m_lexer->setLastLineNumber(m_lastLine); m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType, strictMode()); - m_tokenCount++; + } + + bool nextTokenIsColon() + { + return m_lexer->nextTokenIsColon(); } bool consume(JSTokenType expected) @@ -130,10 +144,39 @@ private: bool strictMode() { return currentScope()->strictMode(); } bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } - bool breakIsValid() { return currentScope()->breakIsValid(); } - void pushLabel(const Identifier* label) { currentScope()->pushLabel(label); } + bool breakIsValid() + { + ScopeRef current = currentScope(); + while (!current->breakIsValid()) { + if (!current.hasContainingScope()) + return false; + current = current.containingScope(); + } + return true; + } + bool continueIsValid() + { + ScopeRef current = currentScope(); + while (!current->continueIsValid()) { + if (!current.hasContainingScope()) + return false; + current = current.containingScope(); + } + return true; + } + void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); } void popLabel() { currentScope()->popLabel(); } - bool hasLabel(const Identifier* label) { return currentScope()->hasLabel(label); } + ScopeLabelInfo* getLabel(const Identifier* label) + { + ScopeRef current = currentScope(); + ScopeLabelInfo* result = 0; + while (!(result = current->getLabel(label))) { + if (!current.hasContainingScope()) + return 0; + current = current.containingScope(); + } + return result; + } enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&); @@ -202,10 +245,10 @@ private: Lexer* m_lexer; StackBounds m_stack; bool m_error; + const char* m_errorMessage; JSGlobalData* m_globalData; JSToken m_token; bool m_allowsIn; - int m_tokenCount; int m_lastLine; int m_lastTokenEnd; int m_assignmentCount; @@ -231,7 +274,7 @@ private: int m_originalDepth; int* m_depth; }; - + struct Scope { Scope(JSGlobalData* globalData, bool isFunction, bool strictMode) : m_globalData(globalData) @@ -241,6 +284,7 @@ private: , m_allowsNewDecls(true) , m_strictMode(strictMode) , m_isFunction(isFunction) + , m_isFunctionBoundary(false) , m_isValidStrictMode(true) , m_loopDepth(0) , m_switchDepth(0) @@ -254,12 +298,13 @@ private: void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; } bool inLoop() { return !!m_loopDepth; } bool breakIsValid() { return m_loopDepth || m_switchDepth; } + bool continueIsValid() { return m_loopDepth; } - void pushLabel(const Identifier* label) + void pushLabel(const Identifier* label, bool isLoop) { if (!m_labels) m_labels = new LabelStack; - m_labels->append(label->impl()); + m_labels->append(ScopeLabelInfo(label->impl(), isLoop)); } void popLabel() @@ -269,19 +314,24 @@ private: m_labels->removeLast(); } - bool hasLabel(const Identifier* label) + ScopeLabelInfo* getLabel(const Identifier* label) { if (!m_labels) - return false; + return 0; for (int i = m_labels->size(); i > 0; i--) { - if (m_labels->at(i - 1) == label->impl()) - return true; + if (m_labels->at(i - 1).m_ident == label->impl()) + return &m_labels->at(i - 1); } - return false; + return 0; } - void setIsFunction() { m_isFunction = true; } + void setIsFunction() + { + m_isFunction = true; + m_isFunctionBoundary = true; + } bool isFunction() { return m_isFunction; } + bool isFunctionBoundary() { return m_isFunctionBoundary; } bool declareVariable(const Identifier* ident) { @@ -376,10 +426,12 @@ private: bool m_allowsNewDecls : 1; bool m_strictMode : 1; bool m_isFunction : 1; + bool m_isFunctionBoundary : 1; bool m_isValidStrictMode : 1; int m_loopDepth; int m_switchDepth; - typedef Vector<StringImpl*, 2> LabelStack; + + typedef Vector<ScopeLabelInfo, 2> LabelStack; LabelStack* m_labels; IdentifierSet m_declaredVariables; IdentifierSet m_usedVariables; @@ -397,11 +449,45 @@ private: } Scope* operator->() { return &m_scopeStack->at(m_index); } unsigned index() const { return m_index; } + + bool hasContainingScope() + { + return m_index && !m_scopeStack->at(m_index).isFunctionBoundary(); + } + + ScopeRef containingScope() + { + ASSERT(hasContainingScope()); + return ScopeRef(m_scopeStack, m_index - 1); + } + private: ScopeStack* m_scopeStack; unsigned m_index; }; - + + struct AutoPopScopeRef : public ScopeRef { + AutoPopScopeRef(JSParser* parser, ScopeRef scope) + : ScopeRef(scope) + , m_parser(parser) + { + } + + ~AutoPopScopeRef() + { + if (m_parser) + m_parser->popScope(*this, false); + } + + void setPopped() + { + m_parser = 0; + } + + private: + JSParser* m_parser; + }; + ScopeRef currentScope() { return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); @@ -419,7 +505,7 @@ private: return currentScope(); } - bool popScope(ScopeRef scope, bool shouldTrackClosedVariables) + bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables) { ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); ASSERT(m_scopeStack.size() > 1); @@ -427,7 +513,18 @@ private: m_scopeStack.removeLast(); return result; } - + + bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables) + { + return popScopeInternal(scope, shouldTrackClosedVariables); + } + + bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables) + { + scope.setPopped(); + return popScopeInternal(scope, shouldTrackClosedVariables); + } + bool declareVariable(const Identifier* ident) { unsigned i = m_scopeStack.size() - 1; @@ -448,7 +545,7 @@ private: ScopeStack m_scopeStack; }; -int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source) +const char* jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source) { JSParser parser(globalData->lexer, globalData, parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider()); return parser.parseProgram(); @@ -458,9 +555,9 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* p : m_lexer(lexer) , m_stack(globalData->stack()) , m_error(false) + , m_errorMessage("Parse error") , m_globalData(globalData) , m_allowsIn(true) - , m_tokenCount(0) , m_lastLine(0) , m_lastTokenEnd(0) , m_assignmentCount(0) @@ -483,7 +580,7 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* p m_lexer->setLastLineNumber(tokenLine()); } -bool JSParser::parseProgram() +const char* JSParser::parseProgram() { ASTBuilder context(m_globalData, m_lexer); if (m_lexer->isReparsing()) @@ -491,7 +588,7 @@ bool JSParser::parseProgram() ScopeRef scope = currentScope(); SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context); if (!sourceElements || !consume(EOFTOK)) - return true; + return m_errorMessage; IdentifierSet capturedVariables; scope->getCapturedVariables(capturedVariables); CodeFeatures features = context.features(); @@ -502,7 +599,7 @@ bool JSParser::parseProgram() m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, m_lastLine, context.numConstants(), capturedVariables); - return false; + return 0; } bool JSParser::allowAutomaticSemicolon() @@ -698,9 +795,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild fail(); // Remainder of a standard for loop is handled identically - if (declarations > 1 || match(SEMICOLON)) + if (match(SEMICOLON)) goto standardForLoop; + failIfFalse(declarations == 1); + // Handle for-in with var declaration int inLocation = tokenStart(); if (!consume(INTOKEN)) @@ -785,12 +884,12 @@ template <class TreeBuilder> TreeStatement JSParser::parseBreakStatement(TreeBui next(); if (autoSemiColon()) { - failIfFalseIfStrict(breakIsValid()); + failIfFalse(breakIsValid()); return context.createBreakStatement(startCol, endCol, startLine, endLine); } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; - failIfFalseIfStrict(hasLabel(ident)); + failIfFalse(getLabel(ident)); endCol = tokenEnd(); endLine = tokenLine(); next(); @@ -808,12 +907,14 @@ template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(Tree next(); if (autoSemiColon()) { - failIfFalseIfStrict(breakIsValid()); + failIfFalse(continueIsValid()); return context.createContinueStatement(startCol, endCol, startLine, endLine); } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; - failIfFalseIfStrict(hasLabel(ident)); + ScopeLabelInfo* label = getLabel(ident); + failIfFalse(label); + failIfFalse(label->m_isLoop); endCol = tokenEnd(); endLine = tokenLine(); next(); @@ -824,7 +925,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(Tree template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context) { ASSERT(match(RETURN)); - failIfFalseIfStrict(currentScope()->isFunction()); + failIfFalse(currentScope()->isFunction()); int startLine = tokenLine(); int endLine = startLine; int start = tokenStart(); @@ -974,7 +1075,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuild matchOrFail(IDENT); ident = m_token.m_data.ident; next(); - ScopeRef catchScope = pushScope(); + AutoPopScopeRef catchScope(this, pushScope()); failIfFalseIfStrict(catchScope->declareVariable(ident)); catchScope->preventNewDecls(); consumeOrFail(CLOSEPAREN); @@ -1118,7 +1219,7 @@ template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBu template <JSParser::FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine) { - ScopeRef functionScope = pushScope(); + AutoPopScopeRef functionScope(this, pushScope()); functionScope->setIsFunction(); if (match(IDENT)) { name = m_token.m_data.ident; @@ -1168,33 +1269,79 @@ template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(Tr return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } +struct LabelInfo { + LabelInfo(const Identifier* ident, int start, int end) + : m_ident(ident) + , m_start(start) + , m_end(end) + { + } + + const Identifier* m_ident; + int m_start; + int m_end; +}; + 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. + /* Expression and Label statements are ambiguous at LL(1), so we have a + * special case that looks for a colon as the next character in the input. */ - int start = tokenStart(); - int startLine = tokenLine(); - const Identifier* ident = m_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(COLON); + Vector<LabelInfo> labels; + + do { + int start = tokenStart(); + int startLine = tokenLine(); + if (!nextTokenIsColon()) { + // If we hit this path we're making a expression statement, which + // by definition can't make use of continue/break so we can just + // ignore any labels we might have accumulated. + TreeExpression expression = parseExpression(context); + failIfFalse(expression); + failIfFalse(autoSemiColon()); + return context.createExprStatement(expression, startLine, m_lastLine); + } + const Identifier* ident = m_token.m_data.ident; + int end = tokenEnd(); + next(); + consumeOrFail(COLON); + if (!m_syntaxAlreadyValidated) { + // This is O(N^2) over the current list of consecutive labels, but I + // have never seen more than one label in a row in the real world. + for (size_t i = 0; i < labels.size(); i++) + failIfTrue(ident->impl() == labels[i].m_ident->impl()); + failIfTrue(getLabel(ident)); + labels.append(LabelInfo(ident, start, end)); + } + } while (match(IDENT)); + bool isLoop = false; + switch (m_token.m_type) { + case FOR: + case WHILE: + case DO: + isLoop = true; + break; + + default: + break; + } const Identifier* unused = 0; - if (strictMode() && !m_syntaxAlreadyValidated) - pushLabel(ident); + if (!m_syntaxAlreadyValidated) { + for (size_t i = 0; i < labels.size(); i++) + pushLabel(labels[i].m_ident, isLoop); + } TreeStatement statement = parseStatement(context, unused); - if (strictMode() && !m_syntaxAlreadyValidated) - popLabel(); + if (!m_syntaxAlreadyValidated) { + for (size_t i = 0; i < labels.size(); i++) + popLabel(); + } failIfFalse(statement); - return context.createLabelStatement(ident, statement, start, end); + for (size_t i = 0; i < labels.size(); i++) { + const LabelInfo& info = labels[labels.size() - i - 1]; + statement = context.createLabelStatement(info.m_ident, statement, info.m_start, info.m_end); + } + return statement; } template <class TreeBuilder> TreeStatement JSParser::parseExpressionStatement(TreeBuilder& context) @@ -1345,6 +1492,7 @@ template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpressi next(); if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) { failIfTrueIfStrict(m_globalData->propertyNames->eval == *m_lastIdentifier); + failIfTrueIfStrict(m_globalData->propertyNames->arguments == *m_lastIdentifier); declareWrite(m_lastIdentifier); m_lastIdentifier = 0; } @@ -1400,6 +1548,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(Tree int operandStackDepth = 0; int operatorStackDepth = 0; + typename TreeBuilder::BinaryExprContext binaryExprContext(context); while (true) { int exprStart = tokenStart(); int initialAssignments = m_assignmentCount; @@ -1679,7 +1828,13 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre int start = tokenStart(); next(); - return context.createRegex(*pattern, *flags, start); + TreeExpression re = context.createRegExp(*pattern, *flags, start); + if (!re) { + m_errorMessage = Yarr::checkSyntax(pattern->ustring()); + ASSERT(m_errorMessage); + fail(); + } + return re; } default: fail(); @@ -1791,6 +1946,7 @@ endMemberExpression: template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeBuilder& context) { + typename TreeBuilder::UnaryExprContext unaryExprContext(context); AllowInOverride allowInOverride(this); int tokenStackDepth = 0; bool modifiesExpr = false; @@ -1826,9 +1982,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB bool isEvalOrArguments = false; if (strictMode() && !m_syntaxAlreadyValidated) { if (context.isResolve(expr)) { - isEvalOrArguments = m_globalData->propertyNames->eval == *m_lastIdentifier; - if (!isEvalOrArguments && currentScope()->isFunction()) - isEvalOrArguments = m_globalData->propertyNames->arguments == *m_lastIdentifier; + isEvalOrArguments = *m_lastIdentifier == m_globalData->propertyNames->eval || *m_lastIdentifier == m_globalData->propertyNames->arguments; } } failIfTrueIfStrict(isEvalOrArguments && modifiesExpr); diff --git a/Source/JavaScriptCore/parser/JSParser.h b/Source/JavaScriptCore/parser/JSParser.h index 0676b41..8bb7dbb 100644 --- a/Source/JavaScriptCore/parser/JSParser.h +++ b/Source/JavaScriptCore/parser/JSParser.h @@ -159,6 +159,6 @@ struct JSToken { enum JSParserStrictness { JSParseNormal, JSParseStrict }; enum JSParserMode { JSParseProgramCode, JSParseFunctionCode }; -int jsParse(JSGlobalData*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*); +const char* jsParse(JSGlobalData*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*); } #endif // JSParser_h diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp index ff7079f..35d0906 100644 --- a/Source/JavaScriptCore/parser/Lexer.cpp +++ b/Source/JavaScriptCore/parser/Lexer.cpp @@ -703,6 +703,15 @@ ALWAYS_INLINE bool Lexer::parseMultilineComment() } } +bool Lexer::nextTokenIsColon() +{ + const UChar* code = m_code; + while (code < m_codeEnd && (isWhiteSpace(*code) || isLineTerminator(*code))) + code++; + + return code < m_codeEnd && *code == ':'; +} + JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType lexType, bool strictMode) { ASSERT(!m_error); diff --git a/Source/JavaScriptCore/parser/Lexer.h b/Source/JavaScriptCore/parser/Lexer.h index 4d2513d..79987af 100644 --- a/Source/JavaScriptCore/parser/Lexer.h +++ b/Source/JavaScriptCore/parser/Lexer.h @@ -53,6 +53,7 @@ namespace JSC { // Functions for the parser itself. enum LexType { IdentifyReservedWords, IgnoreReservedWords }; JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType, bool strictMode); + bool nextTokenIsColon(); int lineNumber() const { return m_lineNumber; } void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; } int lastLineNumber() const { return m_lastLineNumber; } @@ -67,8 +68,11 @@ namespace JSC { int currentOffset() { return m_code - m_codeStart; } void setOffset(int offset) { + m_error = 0; m_code = m_codeStart + offset; m_current = *m_code; + m_buffer8.resize(0); + m_buffer16.resize(0); } private: diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h index b8e9cdf..54b7231 100644 --- a/Source/JavaScriptCore/parser/Nodes.h +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -273,7 +273,6 @@ namespace JSC { protected: RegisterID* emitThrowReferenceError(BytecodeGenerator&, const UString& message); - RegisterID* emitThrowSyntaxError(BytecodeGenerator&, const UString& message); private: uint32_t m_divot; diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index b203b21..dc15e4f 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -55,14 +55,14 @@ void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, JSP Lexer& lexer = *globalData->lexer; lexer.setCode(*m_source, m_arena); - int parseError = jsParse(globalData, parameters, strictness, mode, m_source); + const char* parseError = jsParse(globalData, parameters, strictness, mode, m_source); int lineNumber = lexer.lineNumber(); bool lexError = lexer.sawError(); lexer.clear(); if (parseError || lexError) { *errLine = lineNumber; - *errMsg = "Parse error"; + *errMsg = parseError ? parseError : "Parse error"; m_sourceElements = 0; } #ifdef ANDROID_INSTRUMENT diff --git a/Source/JavaScriptCore/parser/SourceCode.h b/Source/JavaScriptCore/parser/SourceCode.h index 9ba4da3..a3ce759 100644 --- a/Source/JavaScriptCore/parser/SourceCode.h +++ b/Source/JavaScriptCore/parser/SourceCode.h @@ -31,6 +31,7 @@ #include "SourceProvider.h" #include <wtf/RefPtr.h> +#include <wtf/text/TextPosition.h> namespace JSC { @@ -41,22 +42,34 @@ namespace JSC { , m_startChar(0) , m_endChar(0) , m_firstLine(0) + , m_firstColumn(0) { } - SourceCode(PassRefPtr<SourceProvider> provider, int firstLine = 1) + SourceCode(PassRefPtr<SourceProvider> provider, int firstLine = 1, int firstColumn = 1) : m_provider(provider) , m_startChar(0) , m_endChar(m_provider->length()) , m_firstLine(std::max(firstLine, 1)) + , m_firstColumn(std::max(firstColumn, 1)) { } - SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine) + SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine, int firstColumn = 1) : m_provider(provider) , m_startChar(start) , m_endChar(end) , m_firstLine(std::max(firstLine, 1)) + , m_firstColumn(std::max(firstColumn, 1)) + { + } + + SourceCode(PassRefPtr<SourceProvider> provider, const TextPosition1& startPosition) + : m_provider(provider) + , m_startChar(0) + , m_endChar(m_provider->length()) + , m_firstLine(startPosition.m_line.oneBasedInt()) + , m_firstColumn(startPosition.m_column.oneBasedInt()) { } @@ -70,6 +83,7 @@ namespace JSC { bool isNull() const { return !m_provider; } SourceProvider* provider() const { return m_provider.get(); } int firstLine() const { return m_firstLine; } + int firstColumn() const { return m_firstColumn; } int startOffset() const { return m_startChar; } int endOffset() const { return m_endChar; } const UChar* data() const { return m_provider->data() + m_startChar; } @@ -80,6 +94,7 @@ namespace JSC { int m_startChar; int m_endChar; int m_firstLine; + int m_firstColumn; }; inline SourceCode makeSource(const UString& source, const UString& url = UString(), int firstLine = 1) diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h index b00e710..1b5497a 100644 --- a/Source/JavaScriptCore/parser/SyntaxChecker.h +++ b/Source/JavaScriptCore/parser/SyntaxChecker.h @@ -26,11 +26,43 @@ #ifndef SyntaxChecker_h #define SyntaxChecker_h +#include <yarr/YarrSyntaxChecker.h> + namespace JSC { class SyntaxChecker { public: + struct BinaryExprContext { + BinaryExprContext(SyntaxChecker& context) + : m_context(&context) + { + m_context->m_topBinaryExprs.append(m_context->m_topBinaryExpr); + m_context->m_topBinaryExpr = 0; + } + ~BinaryExprContext() + { + m_context->m_topBinaryExpr = m_context->m_topBinaryExprs.last(); + m_context->m_topBinaryExprs.removeLast(); + } + private: + SyntaxChecker* m_context; + }; + struct UnaryExprContext { + UnaryExprContext(SyntaxChecker& context) + : m_context(&context) + { + m_context->m_topUnaryTokens.append(m_context->m_topUnaryToken); + m_context->m_topUnaryToken = 0; + } + ~UnaryExprContext() + { + m_context->m_topUnaryToken = m_context->m_topUnaryTokens.last(); + m_context->m_topUnaryTokens.removeLast(); + } + private: + SyntaxChecker* m_context; + }; + SyntaxChecker(JSGlobalData* , Lexer*) - : m_topBinaryExpr(0) { } @@ -107,7 +139,7 @@ public: ExpressionType createNull() { return NullExpr; } ExpressionType createBracketAccess(ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; } ExpressionType createDotAccess(ExpressionType, const Identifier&, int, int, int) { return DotExpr; } - ExpressionType createRegex(const Identifier&, const Identifier&, int) { return RegExpExpr; } + ExpressionType createRegExp(const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; } ExpressionType createNewExpr(ExpressionType, int, int, int, int) { return NewExpr; } ExpressionType createNewExpr(ExpressionType, int, int) { return NewExpr; } ExpressionType createConditionalExpr(ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; } @@ -210,6 +242,8 @@ public: private: int m_topBinaryExpr; int m_topUnaryToken; + Vector<int, 8> m_topBinaryExprs; + Vector<int, 8> m_topUnaryTokens; }; } diff --git a/Source/JavaScriptCore/runtime/Collector.cpp b/Source/JavaScriptCore/runtime/Collector.cpp deleted file mode 100644 index 38845ce..0000000 --- a/Source/JavaScriptCore/runtime/Collector.cpp +++ /dev/null @@ -1,1100 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "config.h" -#include "Collector.h" - -#include "ArgList.h" -#include "CallFrame.h" -#include "CodeBlock.h" -#include "CollectorHeapIterator.h" -#include "GCActivityCallback.h" -#include "Interpreter.h" -#include "JSArray.h" -#include "JSGlobalObject.h" -#include "JSLock.h" -#include "JSONObject.h" -#include "JSString.h" -#include "JSValue.h" -#include "JSZombie.h" -#include "MarkStack.h" -#include "Nodes.h" -#include "Tracing.h" -#include <algorithm> -#include <limits.h> -#include <setjmp.h> -#include <stdlib.h> -#include <wtf/FastMalloc.h> -#include <wtf/HashCountedSet.h> -#include <wtf/WTFThreadData.h> -#include <wtf/UnusedParam.h> -#include <wtf/VMTags.h> - -#if OS(DARWIN) - -#include <mach/mach_init.h> -#include <mach/mach_port.h> -#include <mach/task.h> -#include <mach/thread_act.h> -#include <mach/vm_map.h> - -#elif OS(WINDOWS) - -#include <windows.h> -#include <malloc.h> - -#elif OS(HAIKU) - -#include <OS.h> - -#elif OS(UNIX) - -#include <stdlib.h> -#if !OS(HAIKU) -#include <sys/mman.h> -#endif -#include <unistd.h> - -#if OS(SOLARIS) -#include <thread.h> -#else -#include <pthread.h> -#endif - -#if HAVE(PTHREAD_NP_H) -#include <pthread_np.h> -#endif - -#if OS(QNX) -#include <fcntl.h> -#include <sys/procfs.h> -#include <stdio.h> -#include <errno.h> -#endif - -#endif - -#define COLLECT_ON_EVERY_ALLOCATION 0 - -using std::max; - -namespace JSC { - -// tunable parameters - -const size_t GROWTH_FACTOR = 2; -const size_t LOW_WATER_FACTOR = 4; -const size_t ALLOCATIONS_PER_COLLECTION = 3600; -// This value has to be a macro to be used in max() without introducing -// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. -#define MIN_ARRAY_SIZE (static_cast<size_t>(14)) - -#if ENABLE(JSC_MULTIPLE_THREADS) - -#if OS(DARWIN) -typedef mach_port_t PlatformThread; -#elif OS(WINDOWS) -typedef HANDLE PlatformThread; -#endif - -class Heap::Thread { -public: - Thread(pthread_t pthread, const PlatformThread& platThread, void* base) - : posixThread(pthread) - , platformThread(platThread) - , stackBase(base) - { - } - - Thread* next; - pthread_t posixThread; - PlatformThread platformThread; - void* stackBase; -}; - -#endif - -Heap::Heap(JSGlobalData* globalData) - : m_markListSet(0) -#if ENABLE(JSC_MULTIPLE_THREADS) - , m_registeredThreads(0) - , m_currentThreadRegistrar(0) -#endif - , m_globalData(globalData) -{ - ASSERT(globalData); - memset(&m_heap, 0, sizeof(CollectorHeap)); - allocateBlock(); - m_activityCallback = DefaultGCActivityCallback::create(this); - (*m_activityCallback)(); -} - -Heap::~Heap() -{ - // The destroy function must already have been called, so assert this. - ASSERT(!m_globalData); -} - -void Heap::destroy() -{ - JSLock lock(SilenceAssertionsOnly); - - if (!m_globalData) - return; - - ASSERT(!m_globalData->dynamicGlobalObject); - ASSERT(!isBusy()); - - // The global object is not GC protected at this point, so sweeping may delete it - // (and thus the global data) before other objects that may use the global data. - RefPtr<JSGlobalData> protect(m_globalData); - - delete m_markListSet; - m_markListSet = 0; - - freeBlocks(); - -#if ENABLE(JSC_MULTIPLE_THREADS) - if (m_currentThreadRegistrar) { - int error = pthread_key_delete(m_currentThreadRegistrar); - ASSERT_UNUSED(error, !error); - } - - MutexLocker registeredThreadsLock(m_registeredThreadsMutex); - for (Heap::Thread* t = m_registeredThreads; t;) { - Heap::Thread* next = t->next; - delete t; - t = next; - } -#endif - m_globalData = 0; -} - -NEVER_INLINE CollectorBlock* Heap::allocateBlock() -{ - PageAllocationAligned allocation = PageAllocationAligned::allocate(BLOCK_SIZE, BLOCK_SIZE, OSAllocator::JSGCHeapPages); - CollectorBlock* block = static_cast<CollectorBlock*>(allocation.base()); - if (!block) - CRASH(); - - // Initialize block. - - block->heap = this; - clearMarkBits(block); - - Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get(); - for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i) - new (&block->cells[i]) JSCell(dummyMarkableCellStructure); - - // Add block to blocks vector. - - size_t numBlocks = m_heap.numBlocks; - if (m_heap.usedBlocks == numBlocks) { - static const size_t maxNumBlocks = ULONG_MAX / sizeof(PageAllocationAligned) / GROWTH_FACTOR; - if (numBlocks > maxNumBlocks) - CRASH(); - numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); - m_heap.numBlocks = numBlocks; - m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, numBlocks * sizeof(PageAllocationAligned))); - } - m_heap.blocks[m_heap.usedBlocks++] = allocation; - - return block; -} - -NEVER_INLINE void Heap::freeBlock(size_t block) -{ - m_heap.didShrink = true; - - ObjectIterator it(m_heap, block); - ObjectIterator end(m_heap, block + 1); - for ( ; it != end; ++it) - (*it)->~JSCell(); - m_heap.blocks[block].deallocate(); - - // swap with the last block so we compact as we go - m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1]; - m_heap.usedBlocks--; - - if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) { - m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; - m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(PageAllocationAligned))); - } -} - -void Heap::freeBlocks() -{ - ProtectCountSet protectedValuesCopy = m_protectedValues; - - clearMarkBits(); - ProtectCountSet::iterator protectedValuesEnd = protectedValuesCopy.end(); - for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) - markCell(it->first); - - m_heap.nextCell = 0; - m_heap.nextBlock = 0; - DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); - DeadObjectIterator end(m_heap, m_heap.usedBlocks); - for ( ; it != end; ++it) - (*it)->~JSCell(); - - ASSERT(!protectedObjectCount()); - - protectedValuesEnd = protectedValuesCopy.end(); - for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) - it->first->~JSCell(); - - for (size_t block = 0; block < m_heap.usedBlocks; ++block) - m_heap.blocks[block].deallocate(); - - fastFree(m_heap.blocks); - - memset(&m_heap, 0, sizeof(CollectorHeap)); -} - -void Heap::recordExtraCost(size_t cost) -{ - // Our frequency of garbage collection tries to balance memory use against speed - // by collecting based on the number of newly created values. However, for values - // that hold on to a great deal of memory that's not in the form of other JS values, - // that is not good enough - in some cases a lot of those objects can pile up and - // use crazy amounts of memory without a GC happening. So we track these extra - // memory costs. Only unusually large objects are noted, and we only keep track - // of this extra cost until the next GC. In garbage collected languages, most values - // are either very short lived temporaries, or have extremely long lifetimes. So - // if a large value survives one garbage collection, there is not much point to - // collecting more frequently as long as it stays alive. - - if (m_heap.extraCost > maxExtraCost && m_heap.extraCost > m_heap.usedBlocks * BLOCK_SIZE / 2) { - // If the last iteration through the heap deallocated blocks, we need - // to clean up remaining garbage before marking. Otherwise, the conservative - // marking mechanism might follow a pointer to unmapped memory. - if (m_heap.didShrink) - sweep(); - reset(); - } - m_heap.extraCost += cost; -} - -void* Heap::allocate(size_t s) -{ - ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); - typedef HeapConstants::Block Block; - typedef HeapConstants::Cell Cell; - - ASSERT(JSLock::lockCount() > 0); - ASSERT(JSLock::currentThreadIsHoldingLock()); - ASSERT_UNUSED(s, s <= HeapConstants::cellSize); - - ASSERT(m_heap.operationInProgress == NoOperation); - -#if COLLECT_ON_EVERY_ALLOCATION - collectAllGarbage(); - ASSERT(m_heap.operationInProgress == NoOperation); -#endif - -allocate: - - // Fast case: find the next garbage cell and recycle it. - - do { - ASSERT(m_heap.nextBlock < m_heap.usedBlocks); - Block* block = m_heap.collectorBlock(m_heap.nextBlock); - do { - ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock); - if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block - Cell* cell = &block->cells[m_heap.nextCell]; - - m_heap.operationInProgress = Allocation; - JSCell* imp = reinterpret_cast<JSCell*>(cell); - imp->~JSCell(); - m_heap.operationInProgress = NoOperation; - - ++m_heap.nextCell; - return cell; - } - block->marked.advanceToNextPossibleFreeCell(m_heap.nextCell); - } while (m_heap.nextCell != HeapConstants::cellsPerBlock); - m_heap.nextCell = 0; - } while (++m_heap.nextBlock != m_heap.usedBlocks); - - // Slow case: reached the end of the heap. Mark live objects and start over. - - reset(); - goto allocate; -} - -void Heap::resizeBlocks() -{ - m_heap.didShrink = false; - - size_t usedCellCount = markedCells(); - size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount); - size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; - - size_t maxCellCount = 1.25f * minCellCount; - size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; - - if (m_heap.usedBlocks < minBlockCount) - growBlocks(minBlockCount); - else if (m_heap.usedBlocks > maxBlockCount) - shrinkBlocks(maxBlockCount); -} - -void Heap::growBlocks(size_t neededBlocks) -{ - ASSERT(m_heap.usedBlocks < neededBlocks); - while (m_heap.usedBlocks < neededBlocks) - allocateBlock(); -} - -void Heap::shrinkBlocks(size_t neededBlocks) -{ - ASSERT(m_heap.usedBlocks > neededBlocks); - - // Clear the always-on last bit, so isEmpty() isn't fooled by it. - for (size_t i = 0; i < m_heap.usedBlocks; ++i) - m_heap.collectorBlock(i)->marked.clear(HeapConstants::cellsPerBlock - 1); - - for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) { - if (m_heap.collectorBlock(i)->marked.isEmpty()) { - freeBlock(i); - } else - ++i; - } - - // Reset the always-on last bit. - for (size_t i = 0; i < m_heap.usedBlocks; ++i) - m_heap.collectorBlock(i)->marked.set(HeapConstants::cellsPerBlock - 1); -} - -#if ENABLE(JSC_MULTIPLE_THREADS) - -static inline PlatformThread getCurrentPlatformThread() -{ -#if OS(DARWIN) - return pthread_mach_thread_np(pthread_self()); -#elif OS(WINDOWS) - return pthread_getw32threadhandle_np(pthread_self()); -#endif -} - -void Heap::makeUsableFromMultipleThreads() -{ - if (m_currentThreadRegistrar) - return; - - int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread); - if (error) - CRASH(); -} - -void Heap::registerThread() -{ - ASSERT(!m_globalData->exclusiveThread || m_globalData->exclusiveThread == currentThread()); - - if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar)) - return; - - pthread_setspecific(m_currentThreadRegistrar, this); - Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), m_globalData->stack().origin()); - - MutexLocker lock(m_registeredThreadsMutex); - - thread->next = m_registeredThreads; - m_registeredThreads = thread; -} - -void Heap::unregisterThread(void* p) -{ - if (p) - static_cast<Heap*>(p)->unregisterThread(); -} - -void Heap::unregisterThread() -{ - pthread_t currentPosixThread = pthread_self(); - - MutexLocker lock(m_registeredThreadsMutex); - - if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) { - Thread* t = m_registeredThreads; - m_registeredThreads = m_registeredThreads->next; - delete t; - } else { - Heap::Thread* last = m_registeredThreads; - Heap::Thread* t; - for (t = m_registeredThreads->next; t; t = t->next) { - if (pthread_equal(t->posixThread, currentPosixThread)) { - last->next = t->next; - break; - } - last = t; - } - ASSERT(t); // If t is NULL, we never found ourselves in the list. - delete t; - } -} - -#else // ENABLE(JSC_MULTIPLE_THREADS) - -void Heap::registerThread() -{ -} - -#endif - -inline bool isPointerAligned(void* p) -{ - return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0); -} - -// Cell size needs to be a power of two for isPossibleCell to be valid. -COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two); - -static inline bool isCellAligned(void *p) -{ - return (((intptr_t)(p) & CELL_MASK) == 0); -} - -static inline bool isPossibleCell(void* p) -{ - return isCellAligned(p) && p; -} - -void Heap::markConservatively(MarkStack& markStack, void* start, void* end) -{ -#if OS(WINCE) - if (start > end) { - void* tmp = start; - start = end; - end = tmp; - } -#else - ASSERT(start <= end); -#endif - - ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000); - ASSERT(isPointerAligned(start)); - ASSERT(isPointerAligned(end)); - - char** p = static_cast<char**>(start); - char** e = static_cast<char**>(end); - - while (p != e) { - char* x = *p++; - if (isPossibleCell(x)) { - size_t usedBlocks; - uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x); - xAsBits &= CELL_ALIGN_MASK; - - uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK; - const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1); - if (offset > lastCellOffset) - continue; - - CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset); - usedBlocks = m_heap.usedBlocks; - for (size_t block = 0; block < usedBlocks; block++) { - if (m_heap.collectorBlock(block) != blockAddr) - continue; - markStack.append(reinterpret_cast<JSCell*>(xAsBits)); - } - } - } -} - -void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack) -{ - markConservatively(markStack, m_globalData->stack().current(), m_globalData->stack().origin()); - markStack.drain(); -} - -#if COMPILER(GCC) -#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*)))) -#else -#define REGISTER_BUFFER_ALIGNMENT -#endif - -void Heap::markCurrentThreadConservatively(MarkStack& markStack) -{ - // setjmp forces volatile registers onto the stack - jmp_buf registers REGISTER_BUFFER_ALIGNMENT; -#if COMPILER(MSVC) -#pragma warning(push) -#pragma warning(disable: 4611) -#endif - setjmp(registers); -#if COMPILER(MSVC) -#pragma warning(pop) -#endif - - markCurrentThreadConservativelyInternal(markStack); -} - -#if ENABLE(JSC_MULTIPLE_THREADS) - -static inline void suspendThread(const PlatformThread& platformThread) -{ -#if OS(DARWIN) - thread_suspend(platformThread); -#elif OS(WINDOWS) - SuspendThread(platformThread); -#else -#error Need a way to suspend threads on this platform -#endif -} - -static inline void resumeThread(const PlatformThread& platformThread) -{ -#if OS(DARWIN) - thread_resume(platformThread); -#elif OS(WINDOWS) - ResumeThread(platformThread); -#else -#error Need a way to resume threads on this platform -#endif -} - -typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit - -#if OS(DARWIN) - -#if CPU(X86) -typedef i386_thread_state_t PlatformThreadRegisters; -#elif CPU(X86_64) -typedef x86_thread_state64_t PlatformThreadRegisters; -#elif CPU(PPC) -typedef ppc_thread_state_t PlatformThreadRegisters; -#elif CPU(PPC64) -typedef ppc_thread_state64_t PlatformThreadRegisters; -#elif CPU(ARM) -typedef arm_thread_state_t PlatformThreadRegisters; -#else -#error Unknown Architecture -#endif - -#elif OS(WINDOWS) && CPU(X86) -typedef CONTEXT PlatformThreadRegisters; -#else -#error Need a thread register struct for this platform -#endif - -static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) -{ -#if OS(DARWIN) - -#if CPU(X86) - unsigned user_count = sizeof(regs)/sizeof(int); - thread_state_flavor_t flavor = i386_THREAD_STATE; -#elif CPU(X86_64) - unsigned user_count = x86_THREAD_STATE64_COUNT; - thread_state_flavor_t flavor = x86_THREAD_STATE64; -#elif CPU(PPC) - unsigned user_count = PPC_THREAD_STATE_COUNT; - thread_state_flavor_t flavor = PPC_THREAD_STATE; -#elif CPU(PPC64) - unsigned user_count = PPC_THREAD_STATE64_COUNT; - thread_state_flavor_t flavor = PPC_THREAD_STATE64; -#elif CPU(ARM) - unsigned user_count = ARM_THREAD_STATE_COUNT; - thread_state_flavor_t flavor = ARM_THREAD_STATE; -#else -#error Unknown Architecture -#endif - - kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count); - if (result != KERN_SUCCESS) { - WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, - "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result); - CRASH(); - } - return user_count * sizeof(usword_t); -// end OS(DARWIN) - -#elif OS(WINDOWS) && CPU(X86) - regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS; - GetThreadContext(platformThread, ®s); - return sizeof(CONTEXT); -#else -#error Need a way to get thread registers on this platform -#endif -} - -static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) -{ -#if OS(DARWIN) - -#if __DARWIN_UNIX03 - -#if CPU(X86) - return reinterpret_cast<void*>(regs.__esp); -#elif CPU(X86_64) - return reinterpret_cast<void*>(regs.__rsp); -#elif CPU(PPC) || CPU(PPC64) - return reinterpret_cast<void*>(regs.__r1); -#elif CPU(ARM) - return reinterpret_cast<void*>(regs.__sp); -#else -#error Unknown Architecture -#endif - -#else // !__DARWIN_UNIX03 - -#if CPU(X86) - return reinterpret_cast<void*>(regs.esp); -#elif CPU(X86_64) - return reinterpret_cast<void*>(regs.rsp); -#elif CPU(PPC) || CPU(PPC64) - return reinterpret_cast<void*>(regs.r1); -#else -#error Unknown Architecture -#endif - -#endif // __DARWIN_UNIX03 - -// end OS(DARWIN) -#elif CPU(X86) && OS(WINDOWS) - return reinterpret_cast<void*>((uintptr_t) regs.Esp); -#else -#error Need a way to get the stack pointer for another thread on this platform -#endif -} - -void Heap::markOtherThreadConservatively(MarkStack& markStack, Thread* thread) -{ - suspendThread(thread->platformThread); - - PlatformThreadRegisters regs; - size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); - - // mark the thread's registers - markConservatively(markStack, static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); - markStack.drain(); - - void* stackPointer = otherThreadStackPointer(regs); - markConservatively(markStack, stackPointer, thread->stackBase); - markStack.drain(); - - resumeThread(thread->platformThread); -} - -#endif - -void Heap::markStackObjectsConservatively(MarkStack& markStack) -{ - markCurrentThreadConservatively(markStack); - -#if ENABLE(JSC_MULTIPLE_THREADS) - - if (m_currentThreadRegistrar) { - - MutexLocker lock(m_registeredThreadsMutex); - -#ifndef NDEBUG - // Forbid malloc during the mark phase. Marking a thread suspends it, so - // a malloc inside markChildren() would risk a deadlock with a thread that had been - // suspended while holding the malloc lock. - fastMallocForbid(); -#endif - // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held, - // and since this is a shared heap, they are real locks. - for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { - if (!pthread_equal(thread->posixThread, pthread_self())) - markOtherThreadConservatively(markStack, thread); - } -#ifndef NDEBUG - fastMallocAllow(); -#endif - } -#endif -} - -void Heap::updateWeakGCHandles() -{ - for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i) - weakGCHandlePool(i)->update(); -} - -void WeakGCHandlePool::update() -{ - for (unsigned i = 1; i < WeakGCHandlePool::numPoolEntries; ++i) { - if (m_entries[i].isValidPtr()) { - JSCell* cell = m_entries[i].get(); - if (!cell || !Heap::isCellMarked(cell)) - m_entries[i].invalidate(); - } - } -} - -WeakGCHandle* Heap::addWeakGCHandle(JSCell* ptr) -{ - for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i) - if (!weakGCHandlePool(i)->isFull()) - return weakGCHandlePool(i)->allocate(ptr); - - PageAllocationAligned allocation = PageAllocationAligned::allocate(WeakGCHandlePool::poolSize, WeakGCHandlePool::poolSize, OSAllocator::JSGCHeapPages); - m_weakGCHandlePools.append(allocation); - - WeakGCHandlePool* pool = new (allocation.base()) WeakGCHandlePool(); - return pool->allocate(ptr); -} - -void Heap::protect(JSValue k) -{ - ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); - - if (!k.isCell()) - return; - - m_protectedValues.add(k.asCell()); -} - -bool Heap::unprotect(JSValue k) -{ - ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); - - if (!k.isCell()) - return false; - - return m_protectedValues.remove(k.asCell()); -} - -void Heap::markProtectedObjects(MarkStack& markStack) -{ - ProtectCountSet::iterator end = m_protectedValues.end(); - for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) { - markStack.append(it->first); - markStack.drain(); - } -} - -void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) -{ - m_tempSortingVectors.append(tempVector); -} - -void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector) -{ - ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last()); - m_tempSortingVectors.removeLast(); -} - -void Heap::markTempSortVectors(MarkStack& markStack) -{ - typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors; - - VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end(); - for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) { - Vector<ValueStringPair>* tempSortingVector = *it; - - Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); - for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) - if (vectorIt->first) - markStack.append(vectorIt->first); - markStack.drain(); - } -} - -void Heap::clearMarkBits() -{ - for (size_t i = 0; i < m_heap.usedBlocks; ++i) - clearMarkBits(m_heap.collectorBlock(i)); -} - -void Heap::clearMarkBits(CollectorBlock* block) -{ - // allocate assumes that the last cell in every block is marked. - block->marked.clearAll(); - block->marked.set(HeapConstants::cellsPerBlock - 1); -} - -size_t Heap::markedCells(size_t startBlock, size_t startCell) const -{ - ASSERT(startBlock <= m_heap.usedBlocks); - ASSERT(startCell < HeapConstants::cellsPerBlock); - - if (startBlock >= m_heap.usedBlocks) - return 0; - - size_t result = 0; - result += m_heap.collectorBlock(startBlock)->marked.count(startCell); - for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i) - result += m_heap.collectorBlock(i)->marked.count(); - - return result; -} - -void Heap::sweep() -{ - ASSERT(m_heap.operationInProgress == NoOperation); - if (m_heap.operationInProgress != NoOperation) - CRASH(); - m_heap.operationInProgress = Collection; - -#if !ENABLE(JSC_ZOMBIES) - Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get(); -#endif - - DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); - DeadObjectIterator end(m_heap, m_heap.usedBlocks); - for ( ; it != end; ++it) { - JSCell* cell = *it; -#if ENABLE(JSC_ZOMBIES) - if (!cell->isZombie()) { - const ClassInfo* info = cell->classInfo(); - cell->~JSCell(); - new (cell) JSZombie(info, JSZombie::leakedZombieStructure()); - Heap::markCell(cell); - } -#else - cell->~JSCell(); - // Callers of sweep assume it's safe to mark any cell in the heap. - new (cell) JSCell(dummyMarkableCellStructure); -#endif - } - - m_heap.operationInProgress = NoOperation; -} - -void Heap::markRoots() -{ -#ifndef NDEBUG - if (m_globalData->isSharedInstance()) { - ASSERT(JSLock::lockCount() > 0); - ASSERT(JSLock::currentThreadIsHoldingLock()); - } -#endif - - ASSERT(m_heap.operationInProgress == NoOperation); - if (m_heap.operationInProgress != NoOperation) - CRASH(); - - m_heap.operationInProgress = Collection; - - MarkStack& markStack = m_globalData->markStack; - - // Reset mark bits. - clearMarkBits(); - - // Mark stack roots. - markStackObjectsConservatively(markStack); - m_globalData->interpreter->registerFile().markCallFrames(markStack, this); - - // Mark explicitly registered roots. - markProtectedObjects(markStack); - - // Mark temporary vector for Array sorting - markTempSortVectors(markStack); - - // Mark misc. other roots. - if (m_markListSet && m_markListSet->size()) - MarkedArgumentBuffer::markLists(markStack, *m_markListSet); - if (m_globalData->exception) - markStack.append(m_globalData->exception); - if (m_globalData->firstStringifierToMark) - JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); - - // Mark the small strings cache last, since it will clear itself if nothing - // else has marked it. - m_globalData->smallStrings.markChildren(markStack); - - markStack.drain(); - markStack.compact(); - - updateWeakGCHandles(); - - m_heap.operationInProgress = NoOperation; -} - -size_t Heap::objectCount() const -{ - return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks - + m_heap.nextCell // allocated cells in current block - + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap - - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel -} - -void Heap::addToStatistics(Heap::Statistics& statistics) const -{ - statistics.size += m_heap.usedBlocks * BLOCK_SIZE; - statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize); -} - -Heap::Statistics Heap::statistics() const -{ - Statistics statistics = { 0, 0 }; - addToStatistics(statistics); - return statistics; -} - -size_t Heap::size() const -{ - return m_heap.usedBlocks * BLOCK_SIZE; -} - -size_t Heap::globalObjectCount() -{ - size_t count = 0; - if (JSGlobalObject* head = m_globalData->head) { - JSGlobalObject* o = head; - do { - ++count; - o = o->next(); - } while (o != head); - } - return count; -} - -size_t Heap::protectedGlobalObjectCount() -{ - size_t count = 0; - if (JSGlobalObject* head = m_globalData->head) { - JSGlobalObject* o = head; - do { - if (m_protectedValues.contains(o)) - ++count; - o = o->next(); - } while (o != head); - } - - return count; -} - -size_t Heap::protectedObjectCount() -{ - return m_protectedValues.size(); -} - -static const char* typeName(JSCell* cell) -{ - if (cell->isString()) - return "string"; - if (cell->isGetterSetter()) - return "Getter-Setter"; - if (cell->isAPIValueWrapper()) - return "API wrapper"; - if (cell->isPropertyNameIterator()) - return "For-in iterator"; - if (!cell->isObject()) - return "[empty cell]"; - const ClassInfo* info = cell->classInfo(); - return info ? info->className : "Object"; -} - -HashCountedSet<const char*>* Heap::protectedObjectTypeCounts() -{ - HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; - - ProtectCountSet::iterator end = m_protectedValues.end(); - for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) - counts->add(typeName(it->first)); - - return counts; -} - -HashCountedSet<const char*>* Heap::objectTypeCounts() -{ - HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; - - LiveObjectIterator it = primaryHeapBegin(); - LiveObjectIterator heapEnd = primaryHeapEnd(); - for ( ; it != heapEnd; ++it) - counts->add(typeName(*it)); - - return counts; -} - -bool Heap::isBusy() -{ - return m_heap.operationInProgress != NoOperation; -} - -void Heap::reset() -{ - ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); - JAVASCRIPTCORE_GC_BEGIN(); - - markRoots(); - - JAVASCRIPTCORE_GC_MARKED(); - - m_heap.nextCell = 0; - m_heap.nextBlock = 0; - m_heap.nextNumber = 0; - m_heap.extraCost = 0; -#if ENABLE(JSC_ZOMBIES) - sweep(); -#endif - resizeBlocks(); - - JAVASCRIPTCORE_GC_END(); - - (*m_activityCallback)(); -} - -void Heap::collectAllGarbage() -{ - ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); - JAVASCRIPTCORE_GC_BEGIN(); - - // If the last iteration through the heap deallocated blocks, we need - // to clean up remaining garbage before marking. Otherwise, the conservative - // marking mechanism might follow a pointer to unmapped memory. - if (m_heap.didShrink) - sweep(); - - markRoots(); - - JAVASCRIPTCORE_GC_MARKED(); - - m_heap.nextCell = 0; - m_heap.nextBlock = 0; - m_heap.nextNumber = 0; - m_heap.extraCost = 0; - sweep(); - resizeBlocks(); - - JAVASCRIPTCORE_GC_END(); -} - -LiveObjectIterator Heap::primaryHeapBegin() -{ - return LiveObjectIterator(m_heap, 0); -} - -LiveObjectIterator Heap::primaryHeapEnd() -{ - return LiveObjectIterator(m_heap, m_heap.usedBlocks); -} - -void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback) -{ - m_activityCallback = activityCallback; -} - -GCActivityCallback* Heap::activityCallback() -{ - return m_activityCallback.get(); -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/CollectorHeapIterator.h b/Source/JavaScriptCore/runtime/CollectorHeapIterator.h index 9d107b7..7229d77 100644 --- a/Source/JavaScriptCore/runtime/CollectorHeapIterator.h +++ b/Source/JavaScriptCore/runtime/CollectorHeapIterator.h @@ -24,7 +24,7 @@ */ #include "config.h" -#include "Collector.h" +#include "Heap.h" #ifndef CollectorHeapIterator_h #define CollectorHeapIterator_h diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp index 1ef264c..4a58800 100644 --- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -130,11 +130,16 @@ JSObject* createNotAnObjectError(ExecState* exec, JSValue value) JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName) { return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'")); -} +} + +JSObject* createOutOfMemoryError(JSGlobalObject* globalObject) +{ + return createError(globalObject, "Out of memory"); +} JSObject* throwOutOfMemoryError(ExecState* exec) { - return throwError(exec, createError(exec, "Out of memory")); + return throwError(exec, createOutOfMemoryError(exec->lexicalGlobalObject())); } JSObject* throwStackOverflowError(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.h b/Source/JavaScriptCore/runtime/ExceptionHelpers.h index 7edffad..5f1ec6f 100644 --- a/Source/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.h @@ -47,6 +47,7 @@ namespace JSC { JSObject* createTerminatedExecutionException(JSGlobalData*); JSObject* createStackOverflowError(ExecState*); JSObject* createStackOverflowError(JSGlobalObject*); + JSObject* createOutOfMemoryError(JSGlobalObject*); JSObject* createUndefinedVariableError(ExecState*, const Identifier&); JSObject* createNotAnObjectError(ExecState*, JSValue); JSObject* createInvalidParamError(ExecState*, const char* op, JSValue); diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index c7262be..25c551b 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -109,8 +109,12 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope ASSERT(!m_evalCodeBlock); m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get()))); - generator->generate(); - + if ((exception = generator->generate())) { + m_evalCodeBlock.clear(); + evalNode->destroyData(); + return exception; + } + evalNode->destroyData(); #if ENABLE(JIT) @@ -157,7 +161,11 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider())); OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock.get()))); - generator->generate(); + if ((exception = generator->generate())) { + m_programCodeBlock.clear(); + programNode->destroyData(); + return exception; + } programNode->destroyData(); @@ -194,7 +202,12 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain ASSERT(!m_codeBlockForCall); m_codeBlockForCall = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), false)); OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall.get()))); - generator->generate(); + if ((exception = generator->generate())) { + m_codeBlockForCall.clear(); + body->destroyData(); + return exception; + } + m_numParametersForCall = m_codeBlockForCall->m_numParameters; ASSERT(m_numParametersForCall); m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars; @@ -235,7 +248,12 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope ASSERT(!m_codeBlockForConstruct); m_codeBlockForConstruct = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), true)); OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct.get()))); - generator->generate(); + if ((exception = generator->generate())) { + m_codeBlockForConstruct.clear(); + body->destroyData(); + return exception; + } + m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters; ASSERT(m_numParametersForConstruct); m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars; diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index 7168a05..414a0ad 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -30,7 +30,7 @@ #include "GCActivityCallback.h" #include "APIShims.h" -#include "Collector.h" +#include "Heap.h" #include "JSGlobalData.h" #include "JSLock.h" #include <wtf/RetainPtr.h> diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp new file mode 100644 index 0000000..a224ee0 --- /dev/null +++ b/Source/JavaScriptCore/runtime/Heap.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" +#include "Heap.h" + +#include "CollectorHeapIterator.h" +#include "GCActivityCallback.h" +#include "GCHandle.h" +#include "Interpreter.h" +#include "JSGlobalData.h" +#include "JSGlobalObject.h" +#include "JSLock.h" +#include "JSONObject.h" +#include "Tracing.h" + +#define COLLECT_ON_EVERY_ALLOCATION 0 + +namespace JSC { + +Heap::Heap(JSGlobalData* globalData) + : m_markedSpace(globalData) + , m_operationInProgress(NoOperation) + , m_markListSet(0) + , m_activityCallback(DefaultGCActivityCallback::create(this)) + , m_globalData(globalData) + , m_machineStackMarker(&globalData->heap) + , m_extraCost(0) +{ + (*m_activityCallback)(); +} + +Heap::~Heap() +{ + // The destroy function must already have been called, so assert this. + ASSERT(!m_globalData); +} + +void Heap::destroy() +{ + JSLock lock(SilenceAssertionsOnly); + + if (!m_globalData) + return; + + ASSERT(!m_globalData->dynamicGlobalObject); + ASSERT(m_operationInProgress == NoOperation); + + // The global object is not GC protected at this point, so sweeping may delete it + // (and thus the global data) before other objects that may use the global data. + RefPtr<JSGlobalData> protect(m_globalData); + + delete m_markListSet; + m_markListSet = 0; + + ProtectCountSet protectedValuesCopy = m_protectedValues; + m_markedSpace.destroy(protectedValuesCopy); + ASSERT(!protectedObjectCount()); + + m_globalData = 0; +} + +void Heap::recordExtraCost(size_t cost) +{ + // Our frequency of garbage collection tries to balance memory use against speed + // by collecting based on the number of newly created values. However, for values + // that hold on to a great deal of memory that's not in the form of other JS values, + // that is not good enough - in some cases a lot of those objects can pile up and + // use crazy amounts of memory without a GC happening. So we track these extra + // memory costs. Only unusually large objects are noted, and we only keep track + // of this extra cost until the next GC. In garbage collected languages, most values + // are either very short lived temporaries, or have extremely long lifetimes. So + // if a large value survives one garbage collection, there is not much point to + // collecting more frequently as long as it stays alive. + + if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.size() / 2) { + JAVASCRIPTCORE_GC_BEGIN(); + + // If the last iteration through the heap deallocated blocks, we need + // to clean up remaining garbage before marking. Otherwise, the conservative + // marking mechanism might follow a pointer to unmapped memory. + if (m_markedSpace.didShrink()) + m_markedSpace.sweep(); + + markRoots(); + + JAVASCRIPTCORE_GC_MARKED(); + + m_markedSpace.reset(); + m_extraCost = 0; + + JAVASCRIPTCORE_GC_END(); + + (*m_activityCallback)(); + } + m_extraCost += cost; +} + +void* Heap::allocate(size_t s) +{ + ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); + ASSERT(JSLock::lockCount() > 0); + ASSERT(JSLock::currentThreadIsHoldingLock()); + ASSERT_UNUSED(s, s <= HeapConstants::cellSize); + ASSERT(m_operationInProgress == NoOperation); + +#if COLLECT_ON_EVERY_ALLOCATION + collectAllGarbage(); + ASSERT(m_operationInProgress == NoOperation); +#endif + + m_operationInProgress = Allocation; + void* result = m_markedSpace.allocate(s); + m_operationInProgress = NoOperation; + + if (!result) { + JAVASCRIPTCORE_GC_BEGIN(); + + markRoots(); + + JAVASCRIPTCORE_GC_MARKED(); + + m_markedSpace.reset(); + m_extraCost = 0; + + JAVASCRIPTCORE_GC_END(); + + (*m_activityCallback)(); + + m_operationInProgress = Allocation; + result = m_markedSpace.allocate(s); + m_operationInProgress = NoOperation; + } + ASSERT(result); + return result; +} + +void Heap::markConservatively(MarkStack& markStack, void* start, void* end) +{ + m_markedSpace.markConservatively(markStack, start, end); +} + +void Heap::updateWeakGCHandles() +{ + for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i) + weakGCHandlePool(i)->update(); +} + +void WeakGCHandlePool::update() +{ + for (unsigned i = 1; i < WeakGCHandlePool::numPoolEntries; ++i) { + if (m_entries[i].isValidPtr()) { + JSCell* cell = m_entries[i].get(); + if (!cell || !Heap::isCellMarked(cell)) + m_entries[i].invalidate(); + } + } +} + +WeakGCHandle* Heap::addWeakGCHandle(JSCell* ptr) +{ + for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i) + if (!weakGCHandlePool(i)->isFull()) + return weakGCHandlePool(i)->allocate(ptr); + + PageAllocationAligned allocation = PageAllocationAligned::allocate(WeakGCHandlePool::poolSize, WeakGCHandlePool::poolSize, OSAllocator::JSGCHeapPages); + m_weakGCHandlePools.append(allocation); + + WeakGCHandlePool* pool = new (allocation.base()) WeakGCHandlePool(); + return pool->allocate(ptr); +} + +void Heap::protect(JSValue k) +{ + ASSERT(k); + ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); + + if (!k.isCell()) + return; + + m_protectedValues.add(k.asCell()); +} + +bool Heap::unprotect(JSValue k) +{ + ASSERT(k); + ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); + + if (!k.isCell()) + return false; + + return m_protectedValues.remove(k.asCell()); +} + +void Heap::markProtectedObjects(MarkStack& markStack) +{ + ProtectCountSet::iterator end = m_protectedValues.end(); + for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) { + markStack.append(it->first); + markStack.drain(); + } +} + +void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) +{ + m_tempSortingVectors.append(tempVector); +} + +void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector) +{ + ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last()); + m_tempSortingVectors.removeLast(); +} + +void Heap::markTempSortVectors(MarkStack& markStack) +{ + typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors; + + VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end(); + for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) { + Vector<ValueStringPair>* tempSortingVector = *it; + + Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); + for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) + if (vectorIt->first) + markStack.append(vectorIt->first); + markStack.drain(); + } +} + +void Heap::markRoots() +{ +#ifndef NDEBUG + if (m_globalData->isSharedInstance()) { + ASSERT(JSLock::lockCount() > 0); + ASSERT(JSLock::currentThreadIsHoldingLock()); + } +#endif + + ASSERT(m_operationInProgress == NoOperation); + if (m_operationInProgress != NoOperation) + CRASH(); + + m_operationInProgress = Collection; + + MarkStack& markStack = m_globalData->markStack; + + // Reset mark bits. + m_markedSpace.clearMarkBits(); + + // Mark stack roots. + m_machineStackMarker.markMachineStackConservatively(markStack); + m_globalData->interpreter->registerFile().markCallFrames(markStack, this); + + // Mark explicitly registered roots. + markProtectedObjects(markStack); + + // Mark temporary vector for Array sorting + markTempSortVectors(markStack); + + // Mark misc. other roots. + if (m_markListSet && m_markListSet->size()) + MarkedArgumentBuffer::markLists(markStack, *m_markListSet); + if (m_globalData->exception) + markStack.append(m_globalData->exception); + if (m_globalData->firstStringifierToMark) + JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); + + // Mark the small strings cache last, since it will clear itself if nothing + // else has marked it. + m_globalData->smallStrings.markChildren(markStack); + + markStack.drain(); + markStack.compact(); + + updateWeakGCHandles(); + + m_operationInProgress = NoOperation; +} + +size_t Heap::objectCount() const +{ + return m_markedSpace.objectCount(); +} + +MarkedSpace::Statistics Heap::statistics() const +{ + return m_markedSpace.statistics(); +} + +size_t Heap::size() const +{ + return m_markedSpace.size(); +} + +size_t Heap::globalObjectCount() +{ + size_t count = 0; + if (JSGlobalObject* head = m_globalData->head) { + JSGlobalObject* o = head; + do { + ++count; + o = o->next(); + } while (o != head); + } + return count; +} + +size_t Heap::protectedGlobalObjectCount() +{ + size_t count = 0; + if (JSGlobalObject* head = m_globalData->head) { + JSGlobalObject* o = head; + do { + if (m_protectedValues.contains(o)) + ++count; + o = o->next(); + } while (o != head); + } + + return count; +} + +size_t Heap::protectedObjectCount() +{ + return m_protectedValues.size(); +} + +static const char* typeName(JSCell* cell) +{ + if (cell->isString()) + return "string"; + if (cell->isGetterSetter()) + return "Getter-Setter"; + if (cell->isAPIValueWrapper()) + return "API wrapper"; + if (cell->isPropertyNameIterator()) + return "For-in iterator"; + if (!cell->isObject()) + return "[empty cell]"; + const ClassInfo* info = cell->classInfo(); + return info ? info->className : "Object"; +} + +HashCountedSet<const char*>* Heap::protectedObjectTypeCounts() +{ + HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; + + ProtectCountSet::iterator end = m_protectedValues.end(); + for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) + counts->add(typeName(it->first)); + + return counts; +} + +HashCountedSet<const char*>* Heap::objectTypeCounts() +{ + HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; + + LiveObjectIterator it = primaryHeapBegin(); + LiveObjectIterator heapEnd = primaryHeapEnd(); + for ( ; it != heapEnd; ++it) + counts->add(typeName(*it)); + + return counts; +} + +bool Heap::isBusy() +{ + return m_operationInProgress != NoOperation; +} + +void Heap::collectAllGarbage() +{ + ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); + JAVASCRIPTCORE_GC_BEGIN(); + + // If the last iteration through the heap deallocated blocks, we need + // to clean up remaining garbage before marking. Otherwise, the conservative + // marking mechanism might follow a pointer to unmapped memory. + if (m_markedSpace.didShrink()) + m_markedSpace.sweep(); + + markRoots(); + + JAVASCRIPTCORE_GC_MARKED(); + + m_markedSpace.reset(); + m_markedSpace.sweep(); + m_extraCost = 0; + + JAVASCRIPTCORE_GC_END(); + + (*m_activityCallback)(); +} + +LiveObjectIterator Heap::primaryHeapBegin() +{ + return m_markedSpace.primaryHeapBegin(); +} + +LiveObjectIterator Heap::primaryHeapEnd() +{ + return m_markedSpace.primaryHeapEnd(); +} + +void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback) +{ + m_activityCallback = activityCallback; +} + +GCActivityCallback* Heap::activityCallback() +{ + return m_activityCallback.get(); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h new file mode 100644 index 0000000..243bba3 --- /dev/null +++ b/Source/JavaScriptCore/runtime/Heap.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef Heap_h +#define Heap_h + +#include "MarkedSpace.h" +#include <wtf/Forward.h> +#include <wtf/HashSet.h> + +#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell) + +namespace JSC { + + class JSValue; + class UString; + class GCActivityCallback; + class JSCell; + class JSGlobalData; + class JSValue; + class LiveObjectIterator; + class MarkedArgumentBuffer; + class MarkStack; + class WeakGCHandlePool; + + typedef std::pair<JSValue, UString> ValueStringPair; + + enum OperationInProgress { NoOperation, Allocation, Collection }; + + class Heap : public Noncopyable { + public: + void destroy(); + + void* allocate(size_t); + + bool isBusy(); // true if an allocation or collection is in progress + void collectAllGarbage(); + + GCActivityCallback* activityCallback(); + void setActivityCallback(PassOwnPtr<GCActivityCallback>); + + static const size_t minExtraCost = 256; + static const size_t maxExtraCost = 1024 * 1024; + + void reportExtraMemoryCost(size_t cost); + + size_t objectCount() const; + MarkedSpace::Statistics statistics() const; + size_t size() const; + + void protect(JSValue); + // Returns true if the value is no longer protected by any protect pointers + // (though it may still be alive due to heap/stack references). + bool unprotect(JSValue); + + static Heap* heap(JSValue); // 0 for immediate values + static Heap* heap(JSCell*); + + size_t globalObjectCount(); + size_t protectedObjectCount(); + size_t protectedGlobalObjectCount(); + HashCountedSet<const char*>* protectedObjectTypeCounts(); + HashCountedSet<const char*>* objectTypeCounts(); + + static bool isCellMarked(const JSCell*); + static bool checkMarkCell(const JSCell*); + static void markCell(JSCell*); + + WeakGCHandle* addWeakGCHandle(JSCell*); + + void markConservatively(MarkStack&, void* start, void* end); + + void pushTempSortVector(WTF::Vector<ValueStringPair>*); + void popTempSortVector(WTF::Vector<ValueStringPair>*); + + HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } + + JSGlobalData* globalData() const { return m_globalData; } + + LiveObjectIterator primaryHeapBegin(); + LiveObjectIterator primaryHeapEnd(); + + MachineStackMarker& machineStackMarker() { return m_machineStackMarker; } + + MarkedSpace& markedSpace() { return m_markedSpace; } + + private: + friend class JSGlobalData; + Heap(JSGlobalData*); + ~Heap(); + + void recordExtraCost(size_t); + + void markRoots(); + void markProtectedObjects(MarkStack&); + void markTempSortVectors(MarkStack&); + + void updateWeakGCHandles(); + WeakGCHandlePool* weakGCHandlePool(size_t index); + + MarkedSpace m_markedSpace; + OperationInProgress m_operationInProgress; + + ProtectCountSet m_protectedValues; + WTF::Vector<PageAllocationAligned> m_weakGCHandlePools; + WTF::Vector<WTF::Vector<ValueStringPair>* > m_tempSortingVectors; + + HashSet<MarkedArgumentBuffer*>* m_markListSet; + + OwnPtr<GCActivityCallback> m_activityCallback; + + JSGlobalData* m_globalData; + + MachineStackMarker m_machineStackMarker; + + size_t m_extraCost; + }; + + inline bool Heap::isCellMarked(const JSCell* cell) + { + return MarkedSpace::isCellMarked(cell); + } + + inline bool Heap::checkMarkCell(const JSCell* cell) + { + return MarkedSpace::checkMarkCell(cell); + } + + inline void Heap::markCell(JSCell* cell) + { + MarkedSpace::markCell(cell); + } + + inline void Heap::reportExtraMemoryCost(size_t cost) + { + if (cost > minExtraCost) + recordExtraCost(cost); + } + + inline WeakGCHandlePool* Heap::weakGCHandlePool(size_t index) + { + return static_cast<WeakGCHandlePool*>(m_weakGCHandlePools[index].base()); + } + +} // namespace JSC + +#endif // Heap_h diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp index 08dddc1..27611b7 100644 --- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp @@ -29,7 +29,7 @@ #include "config.h" #include "InitializeThreading.h" -#include "Collector.h" +#include "Heap.h" #include "dtoa.h" #include "Identifier.h" #include "JSGlobalObject.h" diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 556a16e..556603b 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -952,8 +952,10 @@ void JSArray::sort(ExecState* exec) for (size_t i = 0; i < lengthNotIncludingUndefined; i++) values[i].second = values[i].first.toString(exec); - if (exec->hadException()) + if (exec->hadException()) { + Heap::heap(this)->popTempSortVector(&values); return; + } // FIXME: Since we sort by string value, a fast algorithm might be to use a radix sort. That would be O(N) rather // than O(N log N). diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 7d4929d..95f4efa 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -25,7 +25,7 @@ #include "CallData.h" #include "ConstructData.h" -#include "Collector.h" +#include "Heap.h" #include "JSImmediate.h" #include "JSValue.h" #include "MarkStack.h" @@ -63,6 +63,7 @@ namespace JSC { friend class JSAPIValueWrapper; friend class JSZombie; friend class JSGlobalData; + friend class MarkedSpace; private: explicit JSCell(Structure*); @@ -362,7 +363,7 @@ namespace JSC { inline Heap* Heap::heap(JSCell* c) { - return cellBlock(c)->heap; + return MarkedSpace::cellBlock(c)->heap; } #if ENABLE(JSC_ZOMBIES) diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index aca995a..f20a9a4 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -30,7 +30,7 @@ #include "JSGlobalData.h" #include "ArgList.h" -#include "Collector.h" +#include "Heap.h" #include "CollectorHeapIterator.h" #include "CommonIdentifiers.h" #include "FunctionConstructor.h" diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index 699f975..a24732a 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -30,7 +30,7 @@ #define JSGlobalData_h #include "CachedTranscendentalFunction.h" -#include "Collector.h" +#include "Heap.h" #include "DateInstanceCache.h" #include "ExecutableAllocator.h" #include "JITStubs.h" @@ -128,7 +128,7 @@ namespace JSC { #if ENABLE(JSC_MULTIPLE_THREADS) // Will start tracking threads that use the heap, which is resource-heavy. - void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); } + void makeUsableFromMultipleThreads() { heap.machineStackMarker().makeUsableFromMultipleThreads(); } #endif GlobalDataType globalDataType; @@ -229,8 +229,7 @@ namespace JSC { int maxReentryDepth; RegExpCache* m_regExpCache; - - BumpPointerAllocator m_regexAllocator; + BumpPointerAllocator m_regExpAllocator; #if ENABLE(REGEXP_TRACING) typedef ListHashSet<RefPtr<RegExp> > RTTraceList; diff --git a/Source/JavaScriptCore/runtime/JSLock.cpp b/Source/JavaScriptCore/runtime/JSLock.cpp index 10f4f3f..918141f 100644 --- a/Source/JavaScriptCore/runtime/JSLock.cpp +++ b/Source/JavaScriptCore/runtime/JSLock.cpp @@ -21,7 +21,7 @@ #include "config.h" #include "JSLock.h" -#include "Collector.h" +#include "Heap.h" #include "CallFrame.h" #if ENABLE(JSC_MULTIPLE_THREADS) diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.h b/Source/JavaScriptCore/runtime/JSNumberCell.h index 0040067..1ccdf50 100644 --- a/Source/JavaScriptCore/runtime/JSNumberCell.h +++ b/Source/JavaScriptCore/runtime/JSNumberCell.h @@ -26,7 +26,7 @@ #include "CallFrame.h" #include "JSCell.h" #include "JSImmediate.h" -#include "Collector.h" +#include "Heap.h" #include "UString.h" #include <stddef.h> // for size_t diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 30e40e4..6ecc73f 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -588,10 +588,28 @@ bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& property } } -static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue) +static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, const PropertyDescriptor& oldDescriptor) { if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) { - target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter)); + if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) { + GetterSetter* accessor = new (exec) GetterSetter(exec); + if (oldDescriptor.getter()) { + attributes |= Getter; + accessor->setGetter(asObject(oldDescriptor.getter())); + } + if (oldDescriptor.setter()) { + attributes |= Setter; + accessor->setSetter(asObject(oldDescriptor.setter())); + } + target->putWithAttributes(exec, propertyName, accessor, attributes); + return true; + } + JSValue newValue = jsUndefined(); + if (descriptor.value()) + newValue = descriptor.value(); + else if (oldDescriptor.value()) + newValue = oldDescriptor.value(); + target->putWithAttributes(exec, propertyName, newValue, attributes & ~(Getter | Setter)); return true; } attributes &= ~ReadOnly; @@ -608,8 +626,11 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName { // If we have a new property we can just put it on normally PropertyDescriptor current; - if (!getOwnPropertyDescriptor(exec, propertyName, current)) - return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined()); + if (!getOwnPropertyDescriptor(exec, propertyName, current)) { + PropertyDescriptor oldDescriptor; + oldDescriptor.setValue(jsUndefined()); + return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), oldDescriptor); + } if (descriptor.isEmpty()) return true; @@ -635,7 +656,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName if (descriptor.isGenericDescriptor()) { if (!current.attributesEqual(descriptor)) { deleteProperty(exec, propertyName); - putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value()); + putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current); } return true; } @@ -648,7 +669,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName return false; } deleteProperty(exec, propertyName); - return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined()); + return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current); } // Changing the value and attributes of an existing property @@ -676,7 +697,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName return true; } deleteProperty(exec, propertyName); - return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value()); + return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current); } // Changing the accessor functions of an existing accessor property diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index fefffde..6696404 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -314,11 +314,15 @@ namespace JSC { ~JSString() { ASSERT(vptr() == JSGlobalData::jsStringVPtr); - for (unsigned i = 0; i < m_fiberCount; ++i) - RopeImpl::deref(m_other.m_fibers[i]); - - if (!m_fiberCount && m_other.m_finalizerCallback) - m_other.m_finalizerCallback(this, m_other.m_finalizerContext); + if (!m_fiberCount) { + if (m_other.m_finalizerCallback) + m_other.m_finalizerCallback(this, m_other.m_finalizerContext); + } else { + unsigned i = 0; + do + RopeImpl::deref(m_other.m_fibers[i]); + while (++i < m_fiberCount); + } } const UString& value(ExecState* exec) const @@ -624,8 +628,7 @@ namespace JSC { inline UString JSValue::toPrimitiveString(ExecState* exec) const { - if (isString()) - return static_cast<JSString*>(asCell())->value(exec); + ASSERT(!isString()); if (isInt32()) return exec->globalData().numericStrings.add(asInt32()); if (isDouble()) diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index dc54f40..cad9662 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -763,8 +763,7 @@ namespace JSC { return asValue() == jsNull(); } #endif // USE(JSVALUE32_64) - - typedef std::pair<JSValue, UString> ValueStringPair; + } // namespace JSC #endif // JSValue_h diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp new file mode 100644 index 0000000..b4a1936 --- /dev/null +++ b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" +#include "MachineStackMarker.h" + +#include "Heap.h" +#include "JSArray.h" +#include "JSGlobalData.h" +#include <setjmp.h> +#include <stdlib.h> + +#if OS(DARWIN) + +#include <mach/mach_init.h> +#include <mach/mach_port.h> +#include <mach/task.h> +#include <mach/thread_act.h> +#include <mach/vm_map.h> + +#elif OS(WINDOWS) + +#include <windows.h> +#include <malloc.h> + +#elif OS(HAIKU) + +#include <OS.h> + +#elif OS(UNIX) + +#include <stdlib.h> +#if !OS(HAIKU) +#include <sys/mman.h> +#endif +#include <unistd.h> + +#if OS(SOLARIS) +#include <thread.h> +#else +#include <pthread.h> +#endif + +#if HAVE(PTHREAD_NP_H) +#include <pthread_np.h> +#endif + +#if OS(QNX) +#include <fcntl.h> +#include <sys/procfs.h> +#include <stdio.h> +#include <errno.h> +#endif + +#endif + +namespace JSC { + +#if ENABLE(JSC_MULTIPLE_THREADS) + +#if OS(DARWIN) +typedef mach_port_t PlatformThread; +#elif OS(WINDOWS) +typedef HANDLE PlatformThread; +#endif + +class MachineStackMarker::Thread { +public: + Thread(pthread_t pthread, const PlatformThread& platThread, void* base) + : posixThread(pthread) + , platformThread(platThread) + , stackBase(base) + { + } + + Thread* next; + pthread_t posixThread; + PlatformThread platformThread; + void* stackBase; +}; + +#endif + +MachineStackMarker::MachineStackMarker(Heap* heap) + : m_heap(heap) +#if ENABLE(JSC_MULTIPLE_THREADS) + , m_registeredThreads(0) + , m_currentThreadRegistrar(0) +#endif +{ +} + +MachineStackMarker::~MachineStackMarker() +{ +#if ENABLE(JSC_MULTIPLE_THREADS) + if (m_currentThreadRegistrar) { + int error = pthread_key_delete(m_currentThreadRegistrar); + ASSERT_UNUSED(error, !error); + } + + MutexLocker registeredThreadsLock(m_registeredThreadsMutex); + for (Thread* t = m_registeredThreads; t;) { + Thread* next = t->next; + delete t; + t = next; + } +#endif +} + +#if ENABLE(JSC_MULTIPLE_THREADS) + +static inline PlatformThread getCurrentPlatformThread() +{ +#if OS(DARWIN) + return pthread_mach_thread_np(pthread_self()); +#elif OS(WINDOWS) + return pthread_getw32threadhandle_np(pthread_self()); +#endif +} + +void MachineStackMarker::makeUsableFromMultipleThreads() +{ + if (m_currentThreadRegistrar) + return; + + int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread); + if (error) + CRASH(); +} + +void MachineStackMarker::registerThread() +{ + ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); + + if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar)) + return; + + pthread_setspecific(m_currentThreadRegistrar, this); + Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin()); + + MutexLocker lock(m_registeredThreadsMutex); + + thread->next = m_registeredThreads; + m_registeredThreads = thread; +} + +void MachineStackMarker::unregisterThread(void* p) +{ + if (p) + static_cast<MachineStackMarker*>(p)->unregisterThread(); +} + +void MachineStackMarker::unregisterThread() +{ + pthread_t currentPosixThread = pthread_self(); + + MutexLocker lock(m_registeredThreadsMutex); + + if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) { + Thread* t = m_registeredThreads; + m_registeredThreads = m_registeredThreads->next; + delete t; + } else { + Thread* last = m_registeredThreads; + Thread* t; + for (t = m_registeredThreads->next; t; t = t->next) { + if (pthread_equal(t->posixThread, currentPosixThread)) { + last->next = t->next; + break; + } + last = t; + } + ASSERT(t); // If t is NULL, we never found ourselves in the list. + delete t; + } +} + +#endif + +void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(MarkStack& markStack) +{ + m_heap->markConservatively(markStack, m_heap->globalData()->stack().current(), m_heap->globalData()->stack().origin()); + markStack.drain(); +} + +#if COMPILER(GCC) +#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*)))) +#else +#define REGISTER_BUFFER_ALIGNMENT +#endif + +void MachineStackMarker::markCurrentThreadConservatively(MarkStack& markStack) +{ + // setjmp forces volatile registers onto the stack + jmp_buf registers REGISTER_BUFFER_ALIGNMENT; +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4611) +#endif + setjmp(registers); +#if COMPILER(MSVC) +#pragma warning(pop) +#endif + + markCurrentThreadConservativelyInternal(markStack); +} + +#if ENABLE(JSC_MULTIPLE_THREADS) + +static inline void suspendThread(const PlatformThread& platformThread) +{ +#if OS(DARWIN) + thread_suspend(platformThread); +#elif OS(WINDOWS) + SuspendThread(platformThread); +#else +#error Need a way to suspend threads on this platform +#endif +} + +static inline void resumeThread(const PlatformThread& platformThread) +{ +#if OS(DARWIN) + thread_resume(platformThread); +#elif OS(WINDOWS) + ResumeThread(platformThread); +#else +#error Need a way to resume threads on this platform +#endif +} + +typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit + +#if OS(DARWIN) + +#if CPU(X86) +typedef i386_thread_state_t PlatformThreadRegisters; +#elif CPU(X86_64) +typedef x86_thread_state64_t PlatformThreadRegisters; +#elif CPU(PPC) +typedef ppc_thread_state_t PlatformThreadRegisters; +#elif CPU(PPC64) +typedef ppc_thread_state64_t PlatformThreadRegisters; +#elif CPU(ARM) +typedef arm_thread_state_t PlatformThreadRegisters; +#else +#error Unknown Architecture +#endif + +#elif OS(WINDOWS) && CPU(X86) +typedef CONTEXT PlatformThreadRegisters; +#else +#error Need a thread register struct for this platform +#endif + +static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) +{ +#if OS(DARWIN) + +#if CPU(X86) + unsigned user_count = sizeof(regs)/sizeof(int); + thread_state_flavor_t flavor = i386_THREAD_STATE; +#elif CPU(X86_64) + unsigned user_count = x86_THREAD_STATE64_COUNT; + thread_state_flavor_t flavor = x86_THREAD_STATE64; +#elif CPU(PPC) + unsigned user_count = PPC_THREAD_STATE_COUNT; + thread_state_flavor_t flavor = PPC_THREAD_STATE; +#elif CPU(PPC64) + unsigned user_count = PPC_THREAD_STATE64_COUNT; + thread_state_flavor_t flavor = PPC_THREAD_STATE64; +#elif CPU(ARM) + unsigned user_count = ARM_THREAD_STATE_COUNT; + thread_state_flavor_t flavor = ARM_THREAD_STATE; +#else +#error Unknown Architecture +#endif + + kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count); + if (result != KERN_SUCCESS) { + WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, + "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result); + CRASH(); + } + return user_count * sizeof(usword_t); +// end OS(DARWIN) + +#elif OS(WINDOWS) && CPU(X86) + regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS; + GetThreadContext(platformThread, ®s); + return sizeof(CONTEXT); +#else +#error Need a way to get thread registers on this platform +#endif +} + +static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) +{ +#if OS(DARWIN) + +#if __DARWIN_UNIX03 + +#if CPU(X86) + return reinterpret_cast<void*>(regs.__esp); +#elif CPU(X86_64) + return reinterpret_cast<void*>(regs.__rsp); +#elif CPU(PPC) || CPU(PPC64) + return reinterpret_cast<void*>(regs.__r1); +#elif CPU(ARM) + return reinterpret_cast<void*>(regs.__sp); +#else +#error Unknown Architecture +#endif + +#else // !__DARWIN_UNIX03 + +#if CPU(X86) + return reinterpret_cast<void*>(regs.esp); +#elif CPU(X86_64) + return reinterpret_cast<void*>(regs.rsp); +#elif CPU(PPC) || CPU(PPC64) + return reinterpret_cast<void*>(regs.r1); +#else +#error Unknown Architecture +#endif + +#endif // __DARWIN_UNIX03 + +// end OS(DARWIN) +#elif CPU(X86) && OS(WINDOWS) + return reinterpret_cast<void*>((uintptr_t) regs.Esp); +#else +#error Need a way to get the stack pointer for another thread on this platform +#endif +} + +void MachineStackMarker::markOtherThreadConservatively(MarkStack& markStack, Thread* thread) +{ + suspendThread(thread->platformThread); + + PlatformThreadRegisters regs; + size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); + + // mark the thread's registers + m_heap->markConservatively(markStack, static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); + markStack.drain(); + + void* stackPointer = otherThreadStackPointer(regs); + m_heap->markConservatively(markStack, stackPointer, thread->stackBase); + markStack.drain(); + + resumeThread(thread->platformThread); +} + +#endif + +void MachineStackMarker::markMachineStackConservatively(MarkStack& markStack) +{ + markCurrentThreadConservatively(markStack); + +#if ENABLE(JSC_MULTIPLE_THREADS) + + if (m_currentThreadRegistrar) { + + MutexLocker lock(m_registeredThreadsMutex); + +#ifndef NDEBUG + // Forbid malloc during the mark phase. Marking a thread suspends it, so + // a malloc inside markChildren() would risk a deadlock with a thread that had been + // suspended while holding the malloc lock. + fastMallocForbid(); +#endif + // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held, + // and since this is a shared heap, they are real locks. + for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { + if (!pthread_equal(thread->posixThread, pthread_self())) + markOtherThreadConservatively(markStack, thread); + } +#ifndef NDEBUG + fastMallocAllow(); +#endif + } +#endif +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.h b/Source/JavaScriptCore/runtime/MachineStackMarker.h new file mode 100644 index 0000000..e80fe05 --- /dev/null +++ b/Source/JavaScriptCore/runtime/MachineStackMarker.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef MachineStackMarker_h +#define MachineStackMarker_h + +#include <wtf/Noncopyable.h> +#include <wtf/ThreadingPrimitives.h> + +#if ENABLE(JSC_MULTIPLE_THREADS) +#include <pthread.h> +#endif + +namespace JSC { + + class Heap; + class MarkStack; + + class MachineStackMarker : public Noncopyable { + public: + MachineStackMarker(Heap*); + ~MachineStackMarker(); + + void markMachineStackConservatively(MarkStack&); + +#if ENABLE(JSC_MULTIPLE_THREADS) + void makeUsableFromMultipleThreads(); + void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads. +#endif + + private: + void markCurrentThreadConservatively(MarkStack&); + void markCurrentThreadConservativelyInternal(MarkStack&); + +#if ENABLE(JSC_MULTIPLE_THREADS) + class Thread; + + static void unregisterThread(void*); + + void unregisterThread(); + void markOtherThreadConservatively(MarkStack&, Thread*); +#endif + + Heap* m_heap; + +#if ENABLE(JSC_MULTIPLE_THREADS) + Mutex m_registeredThreadsMutex; + Thread* m_registeredThreads; + pthread_key_t m_currentThreadRegistrar; +#endif + }; + +} // namespace JSC + +#endif // MachineStackMarker_h diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp new file mode 100644 index 0000000..4bc3c18 --- /dev/null +++ b/Source/JavaScriptCore/runtime/MarkedSpace.cpp @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" +#include "MarkedSpace.h" + +#include "CollectorHeapIterator.h" +#include "JSCell.h" +#include "JSGlobalData.h" +#include "JSLock.h" + +using std::max; + +namespace JSC { + +class Structure; + +// tunable parameters + +const size_t GROWTH_FACTOR = 2; +const size_t LOW_WATER_FACTOR = 4; +const size_t ALLOCATIONS_PER_COLLECTION = 3600; +// This value has to be a macro to be used in max() without introducing +// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. +#define MIN_ARRAY_SIZE (static_cast<size_t>(14)) + +MarkedSpace::MarkedSpace(JSGlobalData* globalData) + : m_globalData(globalData) +{ + memset(&m_heap, 0, sizeof(CollectorHeap)); + allocateBlock(); +} + +void MarkedSpace::destroy(ProtectCountSet& protectedValuesCopy) +{ + clearMarkBits(); + ProtectCountSet::iterator protectedValuesEnd = protectedValuesCopy.end(); + for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) + markCell(it->first); + + m_heap.nextCell = 0; + m_heap.nextBlock = 0; + DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); + DeadObjectIterator end(m_heap, m_heap.usedBlocks); + for ( ; it != end; ++it) + (*it)->~JSCell(); + + protectedValuesEnd = protectedValuesCopy.end(); + for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) + it->first->~JSCell(); + + for (size_t block = 0; block < m_heap.usedBlocks; ++block) + m_heap.blocks[block].deallocate(); + + fastFree(m_heap.blocks); + + memset(&m_heap, 0, sizeof(CollectorHeap)); +} + +NEVER_INLINE CollectorBlock* MarkedSpace::allocateBlock() +{ + PageAllocationAligned allocation = PageAllocationAligned::allocate(BLOCK_SIZE, BLOCK_SIZE, OSAllocator::JSGCHeapPages); + CollectorBlock* block = static_cast<CollectorBlock*>(allocation.base()); + if (!block) + CRASH(); + + // Initialize block. + + block->heap = &globalData()->heap; + clearMarkBits(block); + + Structure* dummyMarkableCellStructure = globalData()->dummyMarkableCellStructure.get(); + for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i) + new (&block->cells[i]) JSCell(dummyMarkableCellStructure); + + // Add block to blocks vector. + + size_t numBlocks = m_heap.numBlocks; + if (m_heap.usedBlocks == numBlocks) { + static const size_t maxNumBlocks = ULONG_MAX / sizeof(PageAllocationAligned) / GROWTH_FACTOR; + if (numBlocks > maxNumBlocks) + CRASH(); + numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); + m_heap.numBlocks = numBlocks; + m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, numBlocks * sizeof(PageAllocationAligned))); + } + m_heap.blocks[m_heap.usedBlocks++] = allocation; + + return block; +} + +NEVER_INLINE void MarkedSpace::freeBlock(size_t block) +{ + m_heap.didShrink = true; + + ObjectIterator it(m_heap, block); + ObjectIterator end(m_heap, block + 1); + for ( ; it != end; ++it) + (*it)->~JSCell(); + m_heap.blocks[block].deallocate(); + + // swap with the last block so we compact as we go + m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1]; + m_heap.usedBlocks--; + + if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) { + m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; + m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(PageAllocationAligned))); + } +} + +void* MarkedSpace::allocate(size_t s) +{ + ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); + typedef HeapConstants::Block Block; + typedef HeapConstants::Cell Cell; + + ASSERT(JSLock::lockCount() > 0); + ASSERT(JSLock::currentThreadIsHoldingLock()); + ASSERT_UNUSED(s, s <= HeapConstants::cellSize); + + // Fast case: find the next garbage cell and recycle it. + + do { + ASSERT(m_heap.nextBlock < m_heap.usedBlocks); + Block* block = m_heap.collectorBlock(m_heap.nextBlock); + do { + ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock); + if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block + Cell* cell = &block->cells[m_heap.nextCell]; + + JSCell* imp = reinterpret_cast<JSCell*>(cell); + imp->~JSCell(); + + ++m_heap.nextCell; + return cell; + } + block->marked.advanceToNextPossibleFreeCell(m_heap.nextCell); + } while (m_heap.nextCell != HeapConstants::cellsPerBlock); + m_heap.nextCell = 0; + } while (++m_heap.nextBlock != m_heap.usedBlocks); + + return 0; +} + +void MarkedSpace::resizeBlocks() +{ + m_heap.didShrink = false; + + size_t usedCellCount = markedCells(); + size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount); + size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; + + size_t maxCellCount = 1.25f * minCellCount; + size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; + + if (m_heap.usedBlocks < minBlockCount) + growBlocks(minBlockCount); + else if (m_heap.usedBlocks > maxBlockCount) + shrinkBlocks(maxBlockCount); +} + +void MarkedSpace::growBlocks(size_t neededBlocks) +{ + ASSERT(m_heap.usedBlocks < neededBlocks); + while (m_heap.usedBlocks < neededBlocks) + allocateBlock(); +} + +void MarkedSpace::shrinkBlocks(size_t neededBlocks) +{ + ASSERT(m_heap.usedBlocks > neededBlocks); + + // Clear the always-on last bit, so isEmpty() isn't fooled by it. + for (size_t i = 0; i < m_heap.usedBlocks; ++i) + m_heap.collectorBlock(i)->marked.clear(HeapConstants::cellsPerBlock - 1); + + for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) { + if (m_heap.collectorBlock(i)->marked.isEmpty()) { + freeBlock(i); + } else + ++i; + } + + // Reset the always-on last bit. + for (size_t i = 0; i < m_heap.usedBlocks; ++i) + m_heap.collectorBlock(i)->marked.set(HeapConstants::cellsPerBlock - 1); +} + +inline bool isPointerAligned(void* p) +{ + return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0); +} + +// Cell size needs to be a power of two for isPossibleCell to be valid. +COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two); + +static inline bool isCellAligned(void *p) +{ + return (((intptr_t)(p) & CELL_MASK) == 0); +} + +static inline bool isPossibleCell(void* p) +{ + return isCellAligned(p) && p; +} + +void MarkedSpace::markConservatively(MarkStack& markStack, void* start, void* end) +{ +#if OS(WINCE) + if (start > end) { + void* tmp = start; + start = end; + end = tmp; + } +#else + ASSERT(start <= end); +#endif + + ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000); + ASSERT(isPointerAligned(start)); + ASSERT(isPointerAligned(end)); + + char** p = static_cast<char**>(start); + char** e = static_cast<char**>(end); + + while (p != e) { + char* x = *p++; + if (isPossibleCell(x)) { + size_t usedBlocks; + uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x); + xAsBits &= CELL_ALIGN_MASK; + + uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK; + const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1); + if (offset > lastCellOffset) + continue; + + CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset); + usedBlocks = m_heap.usedBlocks; + for (size_t block = 0; block < usedBlocks; block++) { + if (m_heap.collectorBlock(block) != blockAddr) + continue; + markStack.append(reinterpret_cast<JSCell*>(xAsBits)); + } + } + } +} + +void MarkedSpace::clearMarkBits() +{ + for (size_t i = 0; i < m_heap.usedBlocks; ++i) + clearMarkBits(m_heap.collectorBlock(i)); +} + +void MarkedSpace::clearMarkBits(CollectorBlock* block) +{ + // allocate assumes that the last cell in every block is marked. + block->marked.clearAll(); + block->marked.set(HeapConstants::cellsPerBlock - 1); +} + +size_t MarkedSpace::markedCells(size_t startBlock, size_t startCell) const +{ + ASSERT(startBlock <= m_heap.usedBlocks); + ASSERT(startCell < HeapConstants::cellsPerBlock); + + if (startBlock >= m_heap.usedBlocks) + return 0; + + size_t result = 0; + result += m_heap.collectorBlock(startBlock)->marked.count(startCell); + for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i) + result += m_heap.collectorBlock(i)->marked.count(); + + return result; +} + +void MarkedSpace::sweep() +{ +#if !ENABLE(JSC_ZOMBIES) + Structure* dummyMarkableCellStructure = globalData()->dummyMarkableCellStructure.get(); +#endif + + DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); + DeadObjectIterator end(m_heap, m_heap.usedBlocks); + for ( ; it != end; ++it) { + JSCell* cell = *it; +#if ENABLE(JSC_ZOMBIES) + if (!cell->isZombie()) { + const ClassInfo* info = cell->classInfo(); + cell->~JSCell(); + new (cell) JSZombie(info, JSZombie::leakedZombieStructure()); + Heap::markCell(cell); + } +#else + cell->~JSCell(); + // Callers of sweep assume it's safe to mark any cell in the heap. + new (cell) JSCell(dummyMarkableCellStructure); +#endif + } +} + +size_t MarkedSpace::objectCount() const +{ + return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks + + m_heap.nextCell // allocated cells in current block + + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap + - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel +} + +void MarkedSpace::addToStatistics(Statistics& statistics) const +{ + statistics.size += m_heap.usedBlocks * BLOCK_SIZE; + statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize); +} + +MarkedSpace::Statistics MarkedSpace::statistics() const +{ + Statistics statistics = { 0, 0 }; + addToStatistics(statistics); + return statistics; +} + +size_t MarkedSpace::size() const +{ + return m_heap.usedBlocks * BLOCK_SIZE; +} + +void MarkedSpace::reset() +{ + m_heap.nextCell = 0; + m_heap.nextBlock = 0; +#if ENABLE(JSC_ZOMBIES) + sweep(); +#endif + resizeBlocks(); +} + +LiveObjectIterator MarkedSpace::primaryHeapBegin() +{ + return LiveObjectIterator(m_heap, 0); +} + +LiveObjectIterator MarkedSpace::primaryHeapEnd() +{ + return LiveObjectIterator(m_heap, m_heap.usedBlocks); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Collector.h b/Source/JavaScriptCore/runtime/MarkedSpace.h index a4e2fe1..78f918c 100644 --- a/Source/JavaScriptCore/runtime/Collector.h +++ b/Source/JavaScriptCore/runtime/MarkedSpace.h @@ -19,44 +19,25 @@ * */ -#ifndef Collector_h -#define Collector_h - -#include "GCHandle.h" -#include "JSValue.h" -#include <stddef.h> -#include <string.h> -#include <wtf/Bitmap.h> +#ifndef MarkedSpace_h +#define MarkedSpace_h + +#include "MachineStackMarker.h" +#include "PageAllocationAligned.h" #include <wtf/FixedArray.h> #include <wtf/HashCountedSet.h> -#include <wtf/HashSet.h> #include <wtf/Noncopyable.h> -#include <wtf/OwnPtr.h> -#include <wtf/PageAllocation.h> -#include <wtf/PageAllocationAligned.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Threading.h> - -#if ENABLE(JSC_MULTIPLE_THREADS) -#include <pthread.h> -#endif - -#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell) +#include <wtf/Vector.h> namespace JSC { class CollectorBlock; - class GCActivityCallback; + class Heap; class JSCell; class JSGlobalData; - class JSValue; - class MarkedArgumentBuffer; - class MarkStack; - - enum OperationInProgress { NoOperation, Allocation, Collection }; - class LiveObjectIterator; + class MarkStack; + class WeakGCHandle; #if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP) const size_t BLOCK_SIZE = 64 * 1024; // 64k @@ -64,47 +45,31 @@ namespace JSC { const size_t BLOCK_SIZE = 256 * 1024; // 256k #endif + typedef HashCountedSet<JSCell*> ProtectCountSet; + struct CollectorHeap { size_t nextBlock; size_t nextCell; PageAllocationAligned* blocks; - void* nextNumber; - size_t numBlocks; size_t usedBlocks; - size_t extraCost; bool didShrink; - OperationInProgress operationInProgress; - CollectorBlock* collectorBlock(size_t index) const { return static_cast<CollectorBlock*>(blocks[index].base()); } }; - class Heap : public Noncopyable { + class MarkedSpace : public Noncopyable { public: - class Thread; + MarkedSpace(JSGlobalData*); + void destroy(ProtectCountSet&); - void destroy(); - - void* allocateNumber(size_t); void* allocate(size_t); - bool isBusy(); // true if an allocation or collection is in progress - void collectAllGarbage(); - - GCActivityCallback* activityCallback(); - void setActivityCallback(PassOwnPtr<GCActivityCallback>); - - static const size_t minExtraCost = 256; - static const size_t maxExtraCost = 1024 * 1024; - - void reportExtraMemoryCost(size_t cost); - size_t objectCount() const; struct Statistics { size_t size; @@ -113,22 +78,8 @@ namespace JSC { Statistics statistics() const; size_t size() const; - void protect(JSValue); - // Returns true if the value is no longer protected by any protect pointers - // (though it may still be alive due to heap/stack references). - bool unprotect(JSValue); - - static Heap* heap(JSValue); // 0 for immediate values static Heap* heap(JSCell*); - size_t globalObjectCount(); - size_t protectedObjectCount(); - size_t protectedGlobalObjectCount(); - HashCountedSet<const char*>* protectedObjectTypeCounts(); - HashCountedSet<const char*>* objectTypeCounts(); - - void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads. - static bool isCellMarked(const JSCell*); static bool checkMarkCell(const JSCell*); static void markCell(JSCell*); @@ -137,30 +88,21 @@ namespace JSC { void markConservatively(MarkStack&, void* start, void* end); - void pushTempSortVector(WTF::Vector<ValueStringPair>*); - void popTempSortVector(WTF::Vector<ValueStringPair>*); - - HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } - - JSGlobalData* globalData() const { return m_globalData; } static bool isNumber(JSCell*); LiveObjectIterator primaryHeapBegin(); LiveObjectIterator primaryHeapEnd(); - private: - void reset(); - void sweep(); + JSGlobalData* globalData() { return m_globalData; } + static CollectorBlock* cellBlock(const JSCell*); static size_t cellOffset(const JSCell*); - friend class JSGlobalData; - Heap(JSGlobalData*); - ~Heap(); + void reset(); + void sweep(); NEVER_INLINE CollectorBlock* allocateBlock(); NEVER_INLINE void freeBlock(size_t); - void freeBlocks(); void resizeBlocks(); void growBlocks(size_t neededBlocks); void shrinkBlocks(size_t neededBlocks); @@ -168,44 +110,14 @@ namespace JSC { void clearMarkBits(CollectorBlock*); size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const; - void recordExtraCost(size_t); - void addToStatistics(Statistics&) const; void markRoots(); - void markProtectedObjects(MarkStack&); - void markTempSortVectors(MarkStack&); - void markCurrentThreadConservatively(MarkStack&); - void markCurrentThreadConservativelyInternal(MarkStack&); - void markOtherThreadConservatively(MarkStack&, Thread*); - void markStackObjectsConservatively(MarkStack&); - - void updateWeakGCHandles(); - WeakGCHandlePool* weakGCHandlePool(size_t index); - - typedef HashCountedSet<JSCell*> ProtectCountSet; + bool didShrink() { return m_heap.didShrink; } + + private: CollectorHeap m_heap; - - ProtectCountSet m_protectedValues; - WTF::Vector<PageAllocationAligned> m_weakGCHandlePools; - WTF::Vector<WTF::Vector<ValueStringPair>* > m_tempSortingVectors; - - HashSet<MarkedArgumentBuffer*>* m_markListSet; - - OwnPtr<GCActivityCallback> m_activityCallback; - -#if ENABLE(JSC_MULTIPLE_THREADS) - void makeUsableFromMultipleThreads(); - - static void unregisterThread(void*); - void unregisterThread(); - - Mutex m_registeredThreadsMutex; - Thread* m_registeredThreads; - pthread_key_t m_currentThreadRegistrar; -#endif - JSGlobalData* m_globalData; }; @@ -219,7 +131,7 @@ namespace JSC { const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; const size_t CELL_MASK = CELL_SIZE - 1; const size_t CELL_ALIGN_MASK = ~CELL_MASK; - const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells. + const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(MarkedSpace*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells. const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); @@ -283,54 +195,31 @@ namespace JSC { typedef CollectorBlock Block; }; - inline CollectorBlock* Heap::cellBlock(const JSCell* cell) + inline CollectorBlock* MarkedSpace::cellBlock(const JSCell* cell) { return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); } - inline size_t Heap::cellOffset(const JSCell* cell) + inline size_t MarkedSpace::cellOffset(const JSCell* cell) { return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; } - inline bool Heap::isCellMarked(const JSCell* cell) + inline bool MarkedSpace::isCellMarked(const JSCell* cell) { return cellBlock(cell)->marked.get(cellOffset(cell)); } - inline bool Heap::checkMarkCell(const JSCell* cell) + inline bool MarkedSpace::checkMarkCell(const JSCell* cell) { return cellBlock(cell)->marked.getset(cellOffset(cell)); } - inline void Heap::markCell(JSCell* cell) + inline void MarkedSpace::markCell(JSCell* cell) { cellBlock(cell)->marked.set(cellOffset(cell)); } - inline void Heap::reportExtraMemoryCost(size_t cost) - { - if (cost > minExtraCost) - recordExtraCost(cost); - } - - inline void* Heap::allocateNumber(size_t s) - { - if (void* result = m_heap.nextNumber) { - m_heap.nextNumber = 0; - return result; - } - - void* result = allocate(s); - m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2); - return result; - } - - - inline WeakGCHandlePool* Heap::weakGCHandlePool(size_t index) - { - return static_cast<WeakGCHandlePool*>(m_weakGCHandlePools[index].base()); - } } // namespace JSC -#endif /* Collector_h */ +#endif // MarkedSpace_h diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.cpp b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp index 7fafa9c..06a319b 100644 --- a/Source/JavaScriptCore/runtime/MemoryStatistics.cpp +++ b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp @@ -32,7 +32,7 @@ namespace JSC { -Heap::Statistics heapStatistics(JSGlobalData* commonGlobalData) +MarkedSpace::Statistics heapStatistics(JSGlobalData* commonGlobalData) { return commonGlobalData->heap.statistics(); } diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.h b/Source/JavaScriptCore/runtime/MemoryStatistics.h index 1b92eb9..2659702 100644 --- a/Source/JavaScriptCore/runtime/MemoryStatistics.h +++ b/Source/JavaScriptCore/runtime/MemoryStatistics.h @@ -26,7 +26,7 @@ #ifndef MemoryStatistics_h #define MemoryStatistics_h -#include "Collector.h" +#include "Heap.h" class JSGlobalData; @@ -37,7 +37,7 @@ struct GlobalMemoryStatistics { size_t JITBytes; }; -Heap::Statistics heapStatistics(JSGlobalData* commonGlobalData); +MarkedSpace::Statistics heapStatistics(JSGlobalData* commonGlobalData); GlobalMemoryStatistics globalMemoryStatistics(); } diff --git a/Source/JavaScriptCore/runtime/Protect.h b/Source/JavaScriptCore/runtime/Protect.h index 06cf97f..0c1b5e8 100644 --- a/Source/JavaScriptCore/runtime/Protect.h +++ b/Source/JavaScriptCore/runtime/Protect.h @@ -22,7 +22,7 @@ #ifndef Protect_h #define Protect_h -#include "Collector.h" +#include "Heap.h" #include "JSValue.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp index 664a7fb..31a1abe 100644 --- a/Source/JavaScriptCore/runtime/RegExp.cpp +++ b/Source/JavaScriptCore/runtime/RegExp.cpp @@ -22,22 +22,20 @@ #include "config.h" #include "RegExp.h" + #include "Lexer.h" +#include "yarr/Yarr.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wtf/Assertions.h> #include <wtf/OwnArrayPtr.h> -#include "yarr/RegexJIT.h" -#include "yarr/RegexInterpreter.h" -#include "yarr/RegexPattern.h" - namespace JSC { struct RegExpRepresentation { #if ENABLE(YARR_JIT) - Yarr::RegexCodeBlock m_regExpJITCode; + Yarr::YarrCodeBlock m_regExpJITCode; #endif OwnPtr<Yarr::BytecodePattern> m_regExpBytecode; }; @@ -82,7 +80,7 @@ PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patte RegExp::RegExpState RegExp::compile(JSGlobalData* globalData) { - Yarr::RegexPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError); + Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError); if (m_constructionError) return ParseError; @@ -92,7 +90,7 @@ RegExp::RegExpState RegExp::compile(JSGlobalData* globalData) #if ENABLE(YARR_JIT) if (!pattern.m_containsBackreferences && globalData->canUseJIT()) { - Yarr::jitCompileRegex(pattern, globalData, m_representation->m_regExpJITCode); + Yarr::jitCompile(pattern, globalData, m_representation->m_regExpJITCode); #if ENABLE(YARR_JIT_DEBUG) if (!m_representation->m_regExpJITCode.isFallBack()) res = JITCode; @@ -105,7 +103,7 @@ RegExp::RegExpState RegExp::compile(JSGlobalData* globalData) } #endif - m_representation->m_regExpBytecode = Yarr::byteCompileRegex(pattern, &globalData->m_regexAllocator); + m_representation->m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator); return res; } @@ -144,13 +142,13 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) int result; #if ENABLE(YARR_JIT) if (m_state == JITCode) { - result = Yarr::executeRegex(m_representation->m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector); + result = Yarr::execute(m_representation->m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector); #if ENABLE(YARR_JIT_DEBUG) matchCompareWithInterpreter(s, startOffset, offsetVector, result); #endif } else #endif - result = Yarr::interpretRegex(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), offsetVector); + result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), offsetVector); ASSERT(result >= -1); #if ENABLE(REGEXP_TRACING) @@ -181,7 +179,7 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int* for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++) interpreterOffsetVector[j] = -1; - interpreterResult = Yarr::interpretRegex(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), interpreterOffsetVector); + interpreterResult = Yarr::interpret(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), interpreterOffsetVector); if (jitResult != interpreterResult) differences++; @@ -230,7 +228,7 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int* snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern); #if ENABLE(YARR_JIT) - Yarr::RegexCodeBlock& codeBlock = m_representation->m_regExpJITCode; + Yarr::YarrCodeBlock& codeBlock = m_representation->m_regExpJITCode; char jitAddr[20]; if (m_state == JITCode) diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 21ca170..30d3eab 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -307,7 +307,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args) RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); if (!regExp->isValid()) - return throwError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage()))); + return throwError(exec, createSyntaxError(exec, regExp->errorMessage())); return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); } diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 0a4c8bf..04bcc3b 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -95,7 +95,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) } if (!regExp->isValid()) - return throwVMError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage()))); + return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage())); asRegExpObject(thisValue)->setRegExp(regExp.release()); asRegExpObject(thisValue)->setLastIndex(0); diff --git a/Source/JavaScriptCore/runtime/UString.cpp b/Source/JavaScriptCore/runtime/UString.cpp index b3cd40c..b70d505 100644 --- a/Source/JavaScriptCore/runtime/UString.cpp +++ b/Source/JavaScriptCore/runtime/UString.cpp @@ -25,7 +25,7 @@ #include "UString.h" #include "JSGlobalObjectFunctions.h" -#include "Collector.h" +#include "Heap.h" #include "Identifier.h" #include "Operations.h" #include <ctype.h> diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h index 6b96a74..2d4e59d 100644 --- a/Source/JavaScriptCore/runtime/WeakGCMap.h +++ b/Source/JavaScriptCore/runtime/WeakGCMap.h @@ -26,7 +26,7 @@ #ifndef WeakGCMap_h #define WeakGCMap_h -#include "Collector.h" +#include "Heap.h" #include <wtf/HashMap.h> namespace JSC { diff --git a/Source/JavaScriptCore/runtime/WeakGCPtr.h b/Source/JavaScriptCore/runtime/WeakGCPtr.h index ac77cf3..6cc75a5 100644 --- a/Source/JavaScriptCore/runtime/WeakGCPtr.h +++ b/Source/JavaScriptCore/runtime/WeakGCPtr.h @@ -26,7 +26,7 @@ #ifndef WeakGCPtr_h #define WeakGCPtr_h -#include "Collector.h" +#include "Heap.h" #include "GCHandle.h" #include <wtf/Noncopyable.h> diff --git a/Source/JavaScriptCore/wtf/AlwaysInline.h b/Source/JavaScriptCore/wtf/AlwaysInline.h index 29c35a8..bacbdd0 100644 --- a/Source/JavaScriptCore/wtf/AlwaysInline.h +++ b/Source/JavaScriptCore/wtf/AlwaysInline.h @@ -41,7 +41,7 @@ #endif #ifndef UNLIKELY -#if defined(__GNUC__) +#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) #define UNLIKELY(x) __builtin_expect((x), 0) #else #define UNLIKELY(x) (x) @@ -49,7 +49,7 @@ #endif #ifndef LIKELY -#if defined(__GNUC__) +#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) #define LIKELY(x) __builtin_expect((x), 1) #else #define LIKELY(x) (x) diff --git a/Source/JavaScriptCore/wtf/FastMalloc.cpp b/Source/JavaScriptCore/wtf/FastMalloc.cpp index 62d7def..882f10d 100644 --- a/Source/JavaScriptCore/wtf/FastMalloc.cpp +++ b/Source/JavaScriptCore/wtf/FastMalloc.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2005, 2007, Google Inc. // All rights reserved. -// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. +// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011 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 @@ -442,10 +442,18 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #include <wtf/HashSet.h> #include <wtf/Vector.h> #endif + +#if HAVE(HEADER_DETECTION_H) +#include "HeaderDetection.h" +#endif + #if HAVE(DISPATCH_H) #include <dispatch/dispatch.h> #endif +#if HAVE(PTHREAD_MACHDEP_H) +#include <System/pthread_machdep.h> +#endif #ifndef PRIuS #define PRIuS "zu" @@ -455,7 +463,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0; // call to the function on Mac OS X, and it's used in performance-critical code. So we // use a function pointer. But that's not necessarily faster on other platforms, and we had // problems with this technique on Windows, so we'll do this only on Mac OS X. -#if OS(DARWIN) +#if OS(DARWIN) && !defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0) static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific; #define pthread_getspecific(key) pthread_getspecific_function_pointer(key) #endif @@ -1438,7 +1446,22 @@ class TCMalloc_PageHeap { void scavenge(); ALWAYS_INLINE bool shouldScavenge() const; -#if !HAVE(DISPATCH_H) +#if HAVE(DISPATCH_H) || OS(WINDOWS) + void periodicScavenge(); + ALWAYS_INLINE bool isScavengerSuspended(); + ALWAYS_INLINE void scheduleScavenger(); + ALWAYS_INLINE void rescheduleScavenger(); + ALWAYS_INLINE void suspendScavenger(); +#endif + +#if HAVE(DISPATCH_H) + dispatch_queue_t m_scavengeQueue; + dispatch_source_t m_scavengeTimer; + bool m_scavengingSuspended; +#elif OS(WINDOWS) + static void CALLBACK scavengerTimerFired(void*, BOOLEAN); + HANDLE m_scavengeQueueTimer; +#else static NO_RETURN_WITH_VALUE void* runScavengerThread(void*); NO_RETURN void scavengerThread(); @@ -1448,12 +1471,6 @@ class TCMalloc_PageHeap { pthread_mutex_t m_scavengeMutex; pthread_cond_t m_scavengeCondition; -#else // !HAVE(DISPATCH_H) - void periodicScavenge(); - - dispatch_queue_t m_scavengeQueue; - dispatch_source_t m_scavengeTimer; - bool m_scavengingScheduled; #endif #endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY @@ -1489,7 +1506,85 @@ void TCMalloc_PageHeap::init() #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -#if !HAVE(DISPATCH_H) +#if HAVE(DISPATCH_H) + +void TCMalloc_PageHeap::initializeScavenger() +{ + m_scavengeQueue = dispatch_queue_create("com.apple.JavaScriptCore.FastMallocSavenger", NULL); + m_scavengeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_scavengeQueue); + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeDelayInSeconds * NSEC_PER_SEC); + dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeDelayInSeconds * NSEC_PER_SEC, 1000 * NSEC_PER_USEC); + dispatch_source_set_event_handler(m_scavengeTimer, ^{ periodicScavenge(); }); + m_scavengingSuspended = true; +} + +ALWAYS_INLINE bool TCMalloc_PageHeap::isScavengerSuspended() +{ + ASSERT(IsHeld(pageheap_lock)); + return m_scavengingSuspended; +} + +ALWAYS_INLINE void TCMalloc_PageHeap::scheduleScavenger() +{ + ASSERT(IsHeld(pageheap_lock)); + m_scavengingSuspended = false; + dispatch_resume(m_scavengeTimer); +} + +ALWAYS_INLINE void TCMalloc_PageHeap::rescheduleScavenger() +{ + // Nothing to do here for libdispatch. +} + +ALWAYS_INLINE void TCMalloc_PageHeap::suspendScavenger() +{ + ASSERT(IsHeld(pageheap_lock)); + m_scavengingSuspended = true; + dispatch_suspend(m_scavengeTimer); +} + +#elif OS(WINDOWS) + +void TCMalloc_PageHeap::scavengerTimerFired(void* context, BOOLEAN) +{ + static_cast<TCMalloc_PageHeap*>(context)->periodicScavenge(); +} + +void TCMalloc_PageHeap::initializeScavenger() +{ + m_scavengeQueueTimer = 0; +} + +ALWAYS_INLINE bool TCMalloc_PageHeap::isScavengerSuspended() +{ + ASSERT(IsHeld(pageheap_lock)); + return !m_scavengeQueueTimer; +} + +ALWAYS_INLINE void TCMalloc_PageHeap::scheduleScavenger() +{ + // We need to use WT_EXECUTEONLYONCE here and reschedule the timer, because + // Windows will fire the timer event even when the function is already running. + ASSERT(IsHeld(pageheap_lock)); + CreateTimerQueueTimer(&m_scavengeQueueTimer, 0, scavengerTimerFired, this, kScavengeDelayInSeconds * 1000, 0, WT_EXECUTEONLYONCE); +} + +ALWAYS_INLINE void TCMalloc_PageHeap::rescheduleScavenger() +{ + // We must delete the timer and create it again, because it is not possible to retrigger a timer on Windows. + suspendScavenger(); + scheduleScavenger(); +} + +ALWAYS_INLINE void TCMalloc_PageHeap::suspendScavenger() +{ + ASSERT(IsHeld(pageheap_lock)); + HANDLE scavengeQueueTimer = m_scavengeQueueTimer; + m_scavengeQueueTimer = 0; + DeleteTimerQueueTimer(0, scavengeQueueTimer, 0); +} + +#else void TCMalloc_PageHeap::initializeScavenger() { @@ -1529,27 +1624,6 @@ ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() pthread_cond_signal(&m_scavengeCondition); } -#else // !HAVE(DISPATCH_H) - -void TCMalloc_PageHeap::initializeScavenger() -{ - m_scavengeQueue = dispatch_queue_create("com.apple.JavaScriptCore.FastMallocSavenger", NULL); - m_scavengeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_scavengeQueue); - dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeDelayInSeconds * NSEC_PER_SEC); - dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeDelayInSeconds * NSEC_PER_SEC, 1000 * NSEC_PER_USEC); - dispatch_source_set_event_handler(m_scavengeTimer, ^{ periodicScavenge(); }); - m_scavengingScheduled = false; -} - -ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() -{ - ASSERT(IsHeld(pageheap_lock)); - if (!m_scavengingScheduled && shouldScavenge()) { - m_scavengingScheduled = true; - dispatch_resume(m_scavengeTimer); - } -} - #endif void TCMalloc_PageHeap::scavenge() @@ -2378,13 +2452,29 @@ static inline TCMalloc_PageHeap* getPageHeap() #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -#if !HAVE(DISPATCH_H) -#if OS(WINDOWS) -static void sleep(unsigned seconds) +#if HAVE(DISPATCH_H) || OS(WINDOWS) + +void TCMalloc_PageHeap::periodicScavenge() { - ::Sleep(seconds * 1000); + SpinLockHolder h(&pageheap_lock); + pageheap->scavenge(); + + if (shouldScavenge()) { + rescheduleScavenger(); + return; + } + + suspendScavenger(); } -#endif + +ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() +{ + ASSERT(IsHeld(pageheap_lock)); + if (isScavengerSuspended() && shouldScavenge()) + scheduleScavenger(); +} + +#else void TCMalloc_PageHeap::scavengerThread() { @@ -2409,19 +2499,7 @@ void TCMalloc_PageHeap::scavengerThread() } } -#else - -void TCMalloc_PageHeap::periodicScavenge() -{ - SpinLockHolder h(&pageheap_lock); - pageheap->scavenge(); - - if (!shouldScavenge()) { - m_scavengingScheduled = false; - dispatch_suspend(m_scavengeTimer); - } -} -#endif // HAVE(DISPATCH_H) +#endif #endif @@ -2448,11 +2526,18 @@ DWORD tlsIndex = TLS_OUT_OF_INDEXES; static ALWAYS_INLINE void setThreadHeap(TCMalloc_ThreadCache* heap) { - // still do pthread_setspecific when using MSVC fast TLS to - // benefit from the delete callback. + // Still do pthread_setspecific even if there's an alternate form + // of thread-local storage in use, to benefit from the delete callback. pthread_setspecific(heap_key, heap); + #if OS(WINDOWS) TlsSetValue(tlsIndex, heap); +#elif defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0) + // Can't have two libraries both doing this in the same process, + // so check and make this crash right away. + if (_pthread_getspecific_direct(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0)) + CRASH(); + _pthread_setspecific_direct(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0, heap); #endif } @@ -2964,6 +3049,8 @@ inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetThreadHeap() { return threadlocal_heap; #elif OS(WINDOWS) return static_cast<TCMalloc_ThreadCache*>(TlsGetValue(tlsIndex)); +#elif defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0) + return static_cast<TCMalloc_ThreadCache*>(_pthread_getspecific_direct(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0)); #else return static_cast<TCMalloc_ThreadCache*>(pthread_getspecific(heap_key)); #endif diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h index e6175c4..e3fec74 100644 --- a/Source/JavaScriptCore/wtf/Platform.h +++ b/Source/JavaScriptCore/wtf/Platform.h @@ -74,9 +74,10 @@ /* COMPILER(RVCT4_OR_GREATER) - ARM RealView Compilation Tools 4.0 or greater */ #if defined(__CC_ARM) || defined(__ARMCC__) #define WTF_COMPILER_RVCT 1 -#if __ARMCC_VERSION >= 400000 -#define WTF_COMPILER_RVCT4_OR_GREATER 1 -#endif +#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) (__ARMCC_VERSION >= (major * 100000 + minor * 10000 + patch * 1000 + build)) +#else +/* Define this for !RVCT compilers, just so we can write things like RVCT_VERSION_AT_LEAST(3, 0, 0, 0). */ +#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) 0 #endif /* COMPILER(GCC) - GNU Compiler Collection */ @@ -86,7 +87,7 @@ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #define GCC_VERSION_AT_LEAST(major, minor, patch) (GCC_VERSION >= (major * 10000 + minor * 100 + patch)) #else -/* define this for !GCC compilers, just so we can write things like COMPILER(GCC) && GCC_VERSION_AT_LEAST(4,1,0) */ +/* Define this for !GCC compilers, just so we can write things like GCC_VERSION_AT_LEAST(4, 1, 0). */ #define GCC_VERSION_AT_LEAST(major, minor, patch) 0 #endif @@ -971,8 +972,8 @@ #define ENABLE_REPAINT_THROTTLING 0 #endif -/* Disable the JIT on versiond of GCC prior to 4.1 */ -#if !defined(ENABLE_JIT) && COMPILER(GCC) && !GCC_VERSION_AT_LEAST(4,1,0) +/* Disable the JIT on versions of GCC prior to 4.1 */ +#if !defined(ENABLE_JIT) && COMPILER(GCC) && !GCC_VERSION_AT_LEAST(4, 1, 0) #define ENABLE_JIT 0 #endif @@ -984,7 +985,7 @@ /* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */ #if !defined(ENABLE_JIT) \ && (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \ - && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4,1,0)) \ + && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \ && !OS(WINCE) #define ENABLE_JIT 1 #endif @@ -1028,7 +1029,7 @@ #endif /* Configure the interpreter */ -#if COMPILER(GCC) || (COMPILER(RVCT4_OR_GREATER) && defined(__GNUC__)) +#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__)) #define HAVE_COMPUTED_GOTO 1 #endif #if HAVE(COMPUTED_GOTO) && ENABLE(INTERPRETER) diff --git a/Source/JavaScriptCore/wtf/RefPtrHashMap.h b/Source/JavaScriptCore/wtf/RefPtrHashMap.h index 7f6ebfe..b9e7eea 100644 --- a/Source/JavaScriptCore/wtf/RefPtrHashMap.h +++ b/Source/JavaScriptCore/wtf/RefPtrHashMap.h @@ -18,6 +18,9 @@ * */ +#ifndef RefPtrHashMap_h +#define RefPtrHashMap_h + namespace WTF { // This specialization is a direct copy of HashMap, with overloaded functions @@ -334,3 +337,5 @@ namespace WTF { } } // namespace WTF + +#endif // RefPtrHashMap_h diff --git a/Source/JavaScriptCore/wtf/StackBounds.cpp b/Source/JavaScriptCore/wtf/StackBounds.cpp index f83695e..be8ce84 100644 --- a/Source/JavaScriptCore/wtf/StackBounds.cpp +++ b/Source/JavaScriptCore/wtf/StackBounds.cpp @@ -60,12 +60,12 @@ namespace WTF { // Bug 26276 - Need a mechanism to determine stack extent // // These platforms should now be working correctly: -// DARWIN, WINDOWS-CPU(X86), QNX, UNIX, WINCE +// DARWIN, QNX, UNIX // These platforms are not: -// WINDOWS-CPU(X86_64), SOLARIS, OPENBSD, SYMBIAN, HAIKU +// WINDOWS, SOLARIS, OPENBSD, SYMBIAN, HAIKU, WINCE // // FIXME: remove this! - this code unsafely guesses at stack sizes! -#if (OS(WINDOWS) && CPU(X86_64)) || OS(SOLARIS) || OS(OPENBSD) || OS(SYMBIAN) || OS(HAIKU) +#if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD) || OS(SYMBIAN) || OS(HAIKU) // Based on the current limit used by the JSC parser, guess the stack size. static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024; // This method assumes the stack is growing downwards. @@ -247,37 +247,39 @@ void StackBounds::initialize() m_bound = isGrowingDownward ? lowerStackBound : upperStackBound; } -#elif OS(WINDOWS) && (CPU(X86) || CPU(X86_64)) +#elif OS(WINDOWS) void StackBounds::initialize() { -#if CPU(X86) - // Offset 0x18 from the FS segment register gives a pointer to - // the thread information block for the current thread. +#if CPU(X86) && COMPILER(MSVC) + // offset 0x18 from the FS segment register gives a pointer to + // the thread information block for the current thread NT_TIB* pTib; -#if COMPILER(MSVC) __asm { MOV EAX, FS:[18h] MOV pTib, EAX } -#else + m_origin = static_cast<void*>(pTib->StackBase); +#elif CPU(X86) && COMPILER(GCC) + // offset 0x18 from the FS segment register gives a pointer to + // the thread information block for the current thread + NT_TIB* pTib; asm ( "movl %%fs:0x18, %0\n" : "=r" (pTib) ); -#endif - // See http://en.wikipedia.org/wiki/Win32_Thread_Information_Block for more information! - void* pDeallocationStack = reinterpret_cast<char*>(pTib) + 0xE0C; m_origin = static_cast<void*>(pTib->StackBase); - m_bound = *static_cast<void**>(pDeallocationStack); #elif CPU(X86_64) PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); m_origin = reinterpret_cast<void*>(pTib->StackBase); - m_bound = estimateStackBound(m_origin); +#else +#error Need a way to get the stack bounds on this platform (Windows) #endif + // Looks like we should be able to get pTib->StackLimit + m_bound = estimateStackBound(m_origin); } #else -#error Need a way to get the stack bounds on this platform. +#error Need a way to get the stack bounds on this platform #endif } // namespace WTF diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.cpp b/Source/JavaScriptCore/wtf/text/AtomicString.cpp index 93ad21d..dd8d66c 100644 --- a/Source/JavaScriptCore/wtf/text/AtomicString.cpp +++ b/Source/JavaScriptCore/wtf/text/AtomicString.cpp @@ -74,6 +74,16 @@ static inline HashSet<StringImpl*>& stringTable() return table->table(); } +template<typename T, typename HashTranslator> +static inline PassRefPtr<StringImpl> addToStringTable(const T& value) +{ + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<T, HashTranslator>(value); + + // If the string is newly-translated, then we need to adopt it. + // The boolean in the pair tells us if that is so. + return addResult.second ? adoptRef(*addResult.first) : *addResult.first; +} + struct CStringTranslator { static unsigned hash(const char* c) { @@ -115,11 +125,9 @@ PassRefPtr<StringImpl> AtomicString::add(const char* c) if (!c) return 0; if (!*c) - return StringImpl::empty(); - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c); - if (!addResult.second) - return *addResult.first; - return adoptRef(*addResult.first); + return StringImpl::empty(); + + return addToStringTable<const char*, CStringTranslator>(c); } struct UCharBuffer { @@ -265,12 +273,8 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length) if (!length) return StringImpl::empty(); - UCharBuffer buf = { s, length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); - - // If the string is newly-translated, then we need to adopt it. - // The boolean in the pair tells us if that is so. - return addResult.second ? adoptRef(*addResult.first) : *addResult.first; + UCharBuffer buffer = { s, length }; + return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer); } PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsigned existingHash) @@ -280,12 +284,9 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsign if (!length) return StringImpl::empty(); - - HashAndCharacters buffer = { existingHash, s, length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); - if (!addResult.second) - return *addResult.first; - return adoptRef(*addResult.first); + + HashAndCharacters buffer = { existingHash, s, length }; + return addToStringTable<HashAndCharacters, HashAndCharactersTranslator>(buffer); } PassRefPtr<StringImpl> AtomicString::add(const UChar* s) @@ -300,12 +301,8 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s) if (!length) return StringImpl::empty(); - UCharBuffer buf = {s, length}; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); - - // If the string is newly-translated, then we need to adopt it. - // The boolean in the pair tells us if that is so. - return addResult.second ? adoptRef(*addResult.first) : *addResult.first; + UCharBuffer buffer = { s, length }; + return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer); } PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r) @@ -370,12 +367,8 @@ AtomicString AtomicString::fromUTF8(const char* characters, size_t length) if (!buffer.hash) return AtomicString(); - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndUTF8Characters, HashAndUTF8CharactersTranslator>(buffer); - - // If the string is newly-translated, then we need to adopt it. - // The boolean in the pair tells us if that is so. AtomicString atomicString; - atomicString.m_string = addResult.second ? adoptRef(*addResult.first) : *addResult.first; + atomicString.m_string = addToStringTable<HashAndUTF8Characters, HashAndUTF8CharactersTranslator>(buffer); return atomicString; } diff --git a/Source/JavaScriptCore/yarr/Yarr.h b/Source/JavaScriptCore/yarr/Yarr.h new file mode 100644 index 0000000..57176bc --- /dev/null +++ b/Source/JavaScriptCore/yarr/Yarr.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged + * 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. + */ + +#ifndef Yarr_h +#define Yarr_h + +#include "YarrInterpreter.h" +#include "YarrJIT.h" +#include "YarrPattern.h" + +namespace JSC { namespace Yarr { + +#define YarrStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers. +#define YarrStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers. +#define YarrStackSpaceForBackTrackInfoBackReference 2 +#define YarrStackSpaceForBackTrackInfoAlternative 1 // One per alternative. +#define YarrStackSpaceForBackTrackInfoParentheticalAssertion 1 +#define YarrStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers. +#define YarrStackSpaceForBackTrackInfoParenthesesTerminal 1 +#define YarrStackSpaceForBackTrackInfoParentheses 2 + +static const unsigned quantifyInfinite = UINT_MAX; + +// The below limit restricts the number of "recursive" match calls in order to +// avoid spending exponential time on complex regular expressions. +static const unsigned matchLimit = 1000000; + +enum JSRegExpResult { + JSRegExpMatch = 1, + JSRegExpNoMatch = 0, + JSRegExpErrorNoMatch = -1, + JSRegExpErrorHitLimit = -2, + JSRegExpErrorNoMemory = -3, + JSRegExpErrorInternal = -4 +}; + +PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*); +int interpret(BytecodePattern*, const UChar* input, unsigned start, unsigned length, int* output); + +#if ENABLE(YARR_JIT) +void jitCompile(YarrPattern&, JSGlobalData*, YarrCodeBlock& jitObject); +int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output); +#endif + +} } // namespace JSC::Yarr + +#endif // Yarr_h + diff --git a/Source/JavaScriptCore/yarr/RegexInterpreter.cpp b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp index 7769922..d2dbf23 100644 --- a/Source/JavaScriptCore/yarr/RegexInterpreter.cpp +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp @@ -25,9 +25,9 @@ */ #include "config.h" -#include "RegexInterpreter.h" +#include "YarrInterpreter.h" -#include "RegexPattern.h" +#include "Yarr.h" #include <wtf/BumpPointerAllocator.h> #ifndef NDEBUG @@ -1433,7 +1433,7 @@ class ByteCompiler { }; public: - ByteCompiler(RegexPattern& pattern) + ByteCompiler(YarrPattern& pattern) : m_pattern(pattern) { m_currentAlternativeIndex = 0; @@ -1825,14 +1825,14 @@ public: if (term.quantityType == QuantifierFixedCount) disjunctionAlreadyCheckedCount = term.parentheses.disjunction->m_minimumSize; else - alternativeFrameLocation += RegexStackSpaceForBackTrackInfoParenthesesOnce; + alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce; unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked; atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, alternativeFrameLocation); emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount); atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType); } else if (term.parentheses.isTerminal) { unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked; - atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + RegexStackSpaceForBackTrackInfoParenthesesOnce); + atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesOnce); emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount); atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType); } else { @@ -1845,7 +1845,7 @@ public: } case PatternTerm::TypeParentheticalAssertion: { - unsigned alternativeFrameLocation = term.frameLocation + RegexStackSpaceForBackTrackInfoParentheticalAssertion; + unsigned alternativeFrameLocation = term.frameLocation + YarrStackSpaceForBackTrackInfoParentheticalAssertion; ASSERT(currentCountAlreadyChecked >= (unsigned)term.inputPosition); int positiveInputOffset = currentCountAlreadyChecked - term.inputPosition; @@ -1861,31 +1861,30 @@ public: } private: - RegexPattern& m_pattern; + YarrPattern& m_pattern; OwnPtr<ByteDisjunction> m_bodyDisjunction; unsigned m_currentAlternativeIndex; Vector<ParenthesesStackEntry> m_parenthesesStack; Vector<ByteDisjunction*> m_allParenthesesInfo; }; -PassOwnPtr<BytecodePattern> byteCompileRegex(RegexPattern& pattern, BumpPointerAllocator* allocator) +PassOwnPtr<BytecodePattern> byteCompile(YarrPattern& pattern, BumpPointerAllocator* allocator) { return ByteCompiler(pattern).compile(allocator); } -int interpretRegex(BytecodePattern* regex, const UChar* input, unsigned start, unsigned length, int* output) +int interpret(BytecodePattern* bytecode, const UChar* input, unsigned start, unsigned length, int* output) { - return Interpreter(regex, output, input, start, length).interpret(); + return Interpreter(bytecode, output, input, start, length).interpret(); } - -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoPatternCharacter) == (RegexStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoPatternCharacter); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoCharacterClass) == (RegexStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoCharacterClass); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoBackReference) == (RegexStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoBackReference); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoAlternative) == (RegexStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoAlternative); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheticalAssertion) == (RegexStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParentheticalAssertion); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParenthesesOnce) == (RegexStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParenthesesOnce); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheses) == (RegexStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParentheses); +COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoPatternCharacter) == (YarrStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoPatternCharacter); +COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoCharacterClass) == (YarrStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoCharacterClass); +COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoBackReference) == (YarrStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoBackReference); +COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoAlternative) == (YarrStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoAlternative); +COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheticalAssertion) == (YarrStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheticalAssertion); +COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParenthesesOnce) == (YarrStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParenthesesOnce); +COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheses) == (YarrStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheses); } } diff --git a/Source/JavaScriptCore/yarr/RegexInterpreter.h b/Source/JavaScriptCore/yarr/YarrInterpreter.h index 0fd8a57..be703a9 100644 --- a/Source/JavaScriptCore/yarr/RegexInterpreter.h +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.h @@ -23,11 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RegexInterpreter_h -#define RegexInterpreter_h +#ifndef YarrInterpreter_h +#define YarrInterpreter_h -#include "RegexParser.h" -#include "RegexPattern.h" +#include "YarrPattern.h" #include <wtf/PassOwnPtr.h> #include <wtf/unicode/Unicode.h> @@ -38,21 +37,6 @@ using WTF::BumpPointerAllocator; namespace JSC { namespace Yarr { -// TODO move the matchLimit constant and the JSRegExpResult enum to the JSRegExp.h when pcre is removed. - -// The below limit restricts the number of "recursive" match calls in order to -// avoid spending exponential time on complex regular expressions. -static const unsigned matchLimit = 1000000; - -enum JSRegExpResult { - JSRegExpMatch = 1, - JSRegExpNoMatch = 0, - JSRegExpErrorNoMatch = -1, - JSRegExpErrorHitLimit = -2, - JSRegExpErrorNoMemory = -3, - JSRegExpErrorInternal = -4 -}; - class ByteDisjunction; struct ByteTerm { @@ -329,7 +313,7 @@ public: }; struct BytecodePattern : FastAllocBase { - BytecodePattern(PassOwnPtr<ByteDisjunction> body, Vector<ByteDisjunction*> allParenthesesInfo, RegexPattern& pattern, BumpPointerAllocator* allocator) + BytecodePattern(PassOwnPtr<ByteDisjunction> body, Vector<ByteDisjunction*> allParenthesesInfo, YarrPattern& pattern, BumpPointerAllocator* allocator) : m_body(body) , m_ignoreCase(pattern.m_ignoreCase) , m_multiline(pattern.m_multiline) @@ -341,7 +325,7 @@ struct BytecodePattern : FastAllocBase { m_allParenthesesInfo.append(allParenthesesInfo); m_userCharacterClasses.append(pattern.m_userCharacterClasses); - // 'Steal' the RegexPattern's CharacterClasses! We clear its + // 'Steal' the YarrPattern's CharacterClasses! We clear its // array, so that it won't delete them on destruction. We'll // take responsibility for that. pattern.m_userCharacterClasses.clear(); @@ -360,7 +344,7 @@ struct BytecodePattern : FastAllocBase { bool m_multiline; bool m_containsBeginChars; // Each BytecodePattern is associated with a RegExp, each RegExp is associated - // with a JSGlobalData. Cache a pointer to out JSGlobalData's m_regexAllocator. + // with a JSGlobalData. Cache a pointer to out JSGlobalData's m_regExpAllocator. BumpPointerAllocator* m_allocator; CharacterClass* newlineCharacterClass; @@ -373,9 +357,6 @@ private: Vector<CharacterClass*> m_userCharacterClasses; }; -PassOwnPtr<BytecodePattern> byteCompileRegex(RegexPattern& pattern, BumpPointerAllocator*); -int interpretRegex(BytecodePattern* v_regex, const UChar* input, unsigned start, unsigned length, int* output); - } } // namespace JSC::Yarr -#endif // RegexInterpreter_h +#endif // YarrInterpreter_h diff --git a/Source/JavaScriptCore/yarr/RegexJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp index 50fe6db..ae59cba 100644 --- a/Source/JavaScriptCore/yarr/RegexJIT.cpp +++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp @@ -24,13 +24,13 @@ */ #include "config.h" -#include "RegexJIT.h" +#include "YarrJIT.h" #include "ASCIICType.h" #include "JSGlobalData.h" #include "LinkBuffer.h" #include "MacroAssembler.h" -#include "RegexParser.h" +#include "Yarr.h" #if ENABLE(YARR_JIT) @@ -38,8 +38,8 @@ using namespace WTF; namespace JSC { namespace Yarr { -class RegexGenerator : private MacroAssembler { - friend void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline); +class YarrGenerator : private MacroAssembler { + friend void jitCompile(JSGlobalData*, YarrCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline); #if CPU(ARM) static const RegisterID input = ARMRegisters::r0; @@ -299,13 +299,25 @@ class RegexGenerator : private MacroAssembler { addJump(jump); } + IndirectJumpEntry(int32_t stackOffset, DataLabelPtr dataLabel) + : m_stackOffset(stackOffset) + { + addDataLabel(dataLabel); + } + void addJump(Jump jump) { m_relJumps.append(jump); } + + void addDataLabel(DataLabelPtr dataLabel) + { + m_dataLabelPtrVector.append(dataLabel); + } int32_t m_stackOffset; JumpList m_relJumps; + Vector<DataLabelPtr, 16> m_dataLabelPtrVector; }; struct AlternativeBacktrackRecord { @@ -354,10 +366,31 @@ class RegexGenerator : private MacroAssembler { jumps.empty(); } + void addIndirectJumpEntry(int32_t stackOffset, DataLabelPtr dataLabel) + { + IndirectJumpHashMap::iterator result = m_indirectJumpMap.find(stackOffset); + + ASSERT(stackOffset >= 0); + + uint32_t offset = static_cast<uint32_t>(stackOffset); + + if (result == m_indirectJumpMap.end()) + m_indirectJumpMap.add(offset, new IndirectJumpEntry(stackOffset, dataLabel)); + else + result->second->addDataLabel(dataLabel); + } + void emitIndirectJumpTable(MacroAssembler* masm) { for (IndirectJumpHashMap::iterator iter = m_indirectJumpMap.begin(); iter != m_indirectJumpMap.end(); ++iter) { IndirectJumpEntry* indJumpEntry = iter->second; + size_t size = indJumpEntry->m_dataLabelPtrVector.size(); + if (size) { + // Link any associated DataLabelPtr's with indirect jump via label + Label hereLabel = masm->label(); + for (size_t i = 0; i < size; ++i) + m_backtrackRecords.append(AlternativeBacktrackRecord(indJumpEntry->m_dataLabelPtrVector[i], hereLabel)); + } indJumpEntry->m_relJumps.link(masm); masm->jump(Address(stackPointerRegister, indJumpEntry->m_stackOffset)); delete indJumpEntry; @@ -383,7 +416,7 @@ class RegexGenerator : private MacroAssembler { return parenthesesTail; } - void emitParenthesesTail(RegexGenerator* generator) + void emitParenthesesTail(YarrGenerator* generator) { unsigned vectorSize = m_parenTails.size(); bool priorBacktrackFallThrough = false; @@ -430,7 +463,7 @@ class RegexGenerator : private MacroAssembler { m_parenTailsForIteration.clear(); } - void linkToNextIteration(RegexGenerator* generator) + void linkToNextIteration(YarrGenerator* generator) { m_jumpsToNextInteration.linkTo(m_nextIteration, generator); } @@ -605,6 +638,11 @@ class RegexGenerator : private MacroAssembler { m_dataLabelPtr = dp; } + void clearSubDataLabelPtr() + { + m_subDataLabelPtr = 0; + } + void setSubDataLabelPtr(DataLabelPtr* subDataLabelPtr) { m_subDataLabelPtr = subDataLabelPtr; @@ -652,7 +690,7 @@ class RegexGenerator : private MacroAssembler { m_backTrackJumps.append(masm->jump()); } - void jumpToBacktrack(RegexGenerator* generator, Jump jump) + void jumpToBacktrack(YarrGenerator* generator, Jump jump) { if (isJumpList()) { if (m_backtrackSourceLabel && (m_backtrackSourceLabel->isSet())) @@ -667,7 +705,7 @@ class RegexGenerator : private MacroAssembler { m_backTrackJumps.append(jump); } - void jumpToBacktrack(RegexGenerator* generator, JumpList& jumps) + void jumpToBacktrack(YarrGenerator* generator, JumpList& jumps) { if (isJumpList()) { if (m_backtrackSourceLabel && (m_backtrackSourceLabel->isSet())) @@ -682,18 +720,7 @@ class RegexGenerator : private MacroAssembler { m_backTrackJumps.append(jumps); } - bool linkDataLabelToHereIfExists(RegexGenerator* generator) - { - if (hasDataLabel()) { - generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(getDataLabel(), generator->label())); - clearDataLabel(); - return true; - } - - return false; - } - - bool plantJumpToBacktrackIfExists(RegexGenerator* generator) + bool plantJumpToBacktrackIfExists(YarrGenerator* generator) { if (isJumpList()) { if (m_backtrackSourceLabel && (m_backtrackSourceLabel->isSet())) @@ -721,7 +748,7 @@ class RegexGenerator : private MacroAssembler { return false; } - void linkAlternativeBacktracks(RegexGenerator* generator, bool nextIteration = false) + void linkAlternativeBacktracks(YarrGenerator* generator, bool nextIteration = false) { Label hereLabel = generator->label(); @@ -743,7 +770,7 @@ class RegexGenerator : private MacroAssembler { clear(); } - void linkAlternativeBacktracksTo(RegexGenerator* generator, Label label, bool nextIteration = false) + void linkAlternativeBacktracksTo(YarrGenerator* generator, Label label, bool nextIteration = false) { m_backTrackJumps.linkTo(label, generator); @@ -877,27 +904,36 @@ class RegexGenerator : private MacroAssembler { m_backtrack.jumpToBacktrack(masm); } - void jumpToBacktrack(RegexGenerator* generator, Jump jump) + void jumpToBacktrack(YarrGenerator* generator, Jump jump) { m_backtrack.jumpToBacktrack(generator, jump); } - void jumpToBacktrack(RegexGenerator* generator, JumpList& jumps) + void jumpToBacktrack(YarrGenerator* generator, JumpList& jumps) { m_backtrack.jumpToBacktrack(generator, jumps); } - bool plantJumpToBacktrackIfExists(RegexGenerator* generator) + bool plantJumpToBacktrackIfExists(YarrGenerator* generator) { return m_backtrack.plantJumpToBacktrackIfExists(generator); } - bool linkDataLabelToBacktrackIfExists(RegexGenerator* generator) + bool linkDataLabelToBacktrackIfExists(YarrGenerator* generator, DataLabelPtr dataLabel) { - if ((m_backtrack.isLabel()) && (m_backtrack.hasDataLabel())) { - generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(m_backtrack.getDataLabel(), m_backtrack.getLabel())); - m_backtrack.clearDataLabel(); - return true; + // If we have a stack offset backtrack destination, use it directly + if (m_backtrack.isStackOffset()) { + generator->m_expressionState.addIndirectJumpEntry(m_backtrack.getStackOffset(), dataLabel); + m_backtrack.clearSubDataLabelPtr(); + } else { + // Otherwise set the data label (which may be linked) + setBacktrackDataLabel(dataLabel); + + if ((m_backtrack.isLabel()) && (m_backtrack.hasDataLabel())) { + generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(m_backtrack.getDataLabel(), m_backtrack.getLabel())); + m_backtrack.clearDataLabel(); + return true; + } } return false; @@ -923,13 +959,13 @@ class RegexGenerator : private MacroAssembler { m_backtrack.setLabel(label); } - void linkAlternativeBacktracks(RegexGenerator* generator, bool nextIteration = false) + void linkAlternativeBacktracks(YarrGenerator* generator, bool nextIteration = false) { m_backtrack.linkAlternativeBacktracks(generator, nextIteration); m_linkedBacktrack = 0; } - void linkAlternativeBacktracksTo(RegexGenerator* generator, Label label, bool nextIteration = false) + void linkAlternativeBacktracksTo(YarrGenerator* generator, Label label, bool nextIteration = false) { m_backtrack.linkAlternativeBacktracksTo(generator, label, nextIteration); } @@ -945,18 +981,12 @@ class RegexGenerator : private MacroAssembler { m_linkedBacktrack->linkToNextBacktrack(followonBacktrack); } - void chainBacktrackJumps(JumpList* jumpList) - { - if (m_linkedBacktrack && !(m_linkedBacktrack->hasDestination())) - m_linkedBacktrack->setBacktrackJumpList(jumpList); - } - BacktrackDestination& getBacktrackDestination() { return m_backtrack; } - void propagateBacktrackingFrom(RegexGenerator* generator, BacktrackDestination& backtrack, bool doJump = true) + void propagateBacktrackingFrom(YarrGenerator* generator, BacktrackDestination& backtrack, bool doJump = true) { if (doJump) m_backtrack.jumpToBacktrack(generator, backtrack.getBacktrackJumps()); @@ -989,7 +1019,7 @@ class RegexGenerator : private MacroAssembler { { } - void processBacktracks(RegexGenerator* generator, TermGenerationState& state, TermGenerationState& parenthesesState, Label nonGreedyTryParentheses, Label fallThrough) + void processBacktracks(YarrGenerator* generator, TermGenerationState& state, TermGenerationState& parenthesesState, Label nonGreedyTryParentheses, Label fallThrough) { m_nonGreedyTryParentheses = nonGreedyTryParentheses; m_fallThrough = fallThrough; @@ -1014,8 +1044,6 @@ class RegexGenerator : private MacroAssembler { stateBacktrack.setBacktrackJumpList(&m_pattBacktrackJumps); stateBacktrack.setBacktrackSourceLabel(&m_backtrackFromAfterParens); } - - parenthesesState.chainBacktrackJumps(&m_pattBacktrackJumps); } void setNextIteration(Label nextIteration) @@ -1029,7 +1057,7 @@ class RegexGenerator : private MacroAssembler { m_pattBacktrackJumps.append(jump); } - bool generateCode(RegexGenerator* generator, JumpList& jumpsToNext, bool priorBackTrackFallThrough, bool nextBacktrackFallThrough) + bool generateCode(YarrGenerator* generator, JumpList& jumpsToNext, bool priorBackTrackFallThrough, bool nextBacktrackFallThrough) { const RegisterID indexTemporary = regT0; unsigned parenthesesFrameLocation = m_term.frameLocation; @@ -1565,11 +1593,9 @@ class RegexGenerator : private MacroAssembler { // Alternative did not match. - state.setBacktrackDataLabel(dataLabel); - // Do we have a backtrack destination? // if so, link the data label to it. - state.linkDataLabelToBacktrackIfExists(this); + state.linkDataLabelToBacktrackIfExists(this, dataLabel); if (!state.isLastAlternative() || countToCheck) state.linkAlternativeBacktracks(this); @@ -1605,7 +1631,7 @@ class RegexGenerator : private MacroAssembler { unsigned parenthesesFrameLocation = term.frameLocation; unsigned alternativeFrameLocation = parenthesesFrameLocation; if (term.quantityType != QuantifierFixedCount) - alternativeFrameLocation += RegexStackSpaceForBackTrackInfoParenthesesOnce; + alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce; // optimized case - no capture & no quantifier can be handled in a light-weight manner. if (!term.capture() && (term.quantityType == QuantifierFixedCount)) { @@ -1738,7 +1764,7 @@ class RegexGenerator : private MacroAssembler { ASSERT(term.quantityType == QuantifierFixedCount); unsigned parenthesesFrameLocation = term.frameLocation; - unsigned alternativeFrameLocation = parenthesesFrameLocation + RegexStackSpaceForBackTrackInfoParentheticalAssertion; + unsigned alternativeFrameLocation = parenthesesFrameLocation + YarrStackSpaceForBackTrackInfoParentheticalAssertion; int countCheckedAfterAssertion = state.checkedTotal - term.inputPosition; @@ -2163,7 +2189,7 @@ class RegexGenerator : private MacroAssembler { } public: - RegexGenerator(RegexPattern& pattern) + YarrGenerator(YarrPattern& pattern) : m_pattern(pattern) , m_shouldFallBack(false) { @@ -2182,7 +2208,7 @@ public: generateDisjunction(m_pattern.m_body); } - void compile(JSGlobalData* globalData, RegexCodeBlock& jitObject) + void compile(JSGlobalData* globalData, YarrCodeBlock& jitObject) { generate(); @@ -2196,17 +2222,20 @@ public: } private: - RegexPattern& m_pattern; + YarrPattern& m_pattern; bool m_shouldFallBack; GenerationState m_expressionState; }; -void jitCompileRegex(RegexPattern& pattern, JSGlobalData* globalData, RegexCodeBlock& jitObject) +void jitCompile(YarrPattern& pattern, JSGlobalData* globalData, YarrCodeBlock& jitObject) { - RegexGenerator generator(pattern); - generator.compile(globalData, jitObject); + YarrGenerator(pattern).compile(globalData, jitObject); } +int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output) +{ + return jitObject.execute(input, start, length, output); +} }} diff --git a/Source/JavaScriptCore/yarr/RegexJIT.h b/Source/JavaScriptCore/yarr/YarrJIT.h index 5e3dca1..414b575 100644 --- a/Source/JavaScriptCore/yarr/RegexJIT.h +++ b/Source/JavaScriptCore/yarr/YarrJIT.h @@ -23,13 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RegexJIT_h -#define RegexJIT_h +#ifndef YarrJIT_h +#define YarrJIT_h #if ENABLE(YARR_JIT) #include "MacroAssembler.h" -#include "RegexPattern.h" #include "UString.h" #if CPU(X86) && !COMPILER(MSVC) @@ -45,16 +44,16 @@ class ExecutablePool; namespace Yarr { -class RegexCodeBlock { - typedef int (*RegexJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL; +class YarrCodeBlock { + typedef int (*YarrJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL; public: - RegexCodeBlock() + YarrCodeBlock() : m_needFallBack(false) { } - ~RegexCodeBlock() + ~YarrCodeBlock() { } @@ -64,7 +63,7 @@ public: int execute(const UChar* input, unsigned start, unsigned length, int* output) { - return reinterpret_cast<RegexJITCode>(m_ref.m_code.executableAddress())(input, start, length, output); + return reinterpret_cast<YarrJITCode>(m_ref.m_code.executableAddress())(input, start, length, output); } #if ENABLE(REGEXP_TRACING) @@ -76,15 +75,8 @@ private: bool m_needFallBack; }; -void jitCompileRegex(RegexPattern& pattern, JSGlobalData* globalData, RegexCodeBlock& jitObject); - -inline int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output) -{ - return jitObject.execute(input, start, length, output); -} - } } // namespace JSC::Yarr #endif -#endif // RegexJIT_h +#endif // YarrJIT_h diff --git a/Source/JavaScriptCore/yarr/RegexParser.h b/Source/JavaScriptCore/yarr/YarrParser.h index ec5f589..8c5741a 100644 --- a/Source/JavaScriptCore/yarr/RegexParser.h +++ b/Source/JavaScriptCore/yarr/YarrParser.h @@ -23,17 +23,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RegexParser_h -#define RegexParser_h +#ifndef YarrParser_h +#define YarrParser_h #include "UString.h" -#include <limits.h> +#include "Yarr.h" #include <wtf/ASCIICType.h> #include <wtf/unicode/Unicode.h> namespace JSC { namespace Yarr { -static const unsigned quantifyInfinite = UINT_MAX; +#define REGEXP_ERROR_PREFIX "Invalid regular expression: " enum BuiltInCharacterClassID { DigitClassID, @@ -667,37 +667,29 @@ private: /* * parse(): * - * This method calls regexBegin(), calls parseTokens() to parse over the input - * patterns, calls regexEnd() or regexError() as appropriate, and converts any + * This method calls parseTokens() to parse over the input and converts any * error code to a const char* for a result. */ const char* parse() { - m_delegate.regexBegin(); - if (m_size > MAX_PATTERN_SIZE) m_err = PatternTooLarge; else parseTokens(); ASSERT(atEndOfPattern() || m_err); - if (m_err) - m_delegate.regexError(); - else - m_delegate.regexEnd(); - // The order of this array must match the ErrorCode enum. static const char* errorMessages[NumberOfErrorCodes] = { 0, // NoError - "regular expression too large", - "numbers out of order in {} quantifier", - "nothing to repeat", - "missing )", - "unmatched parentheses", - "unrecognized character after (?", - "missing terminating ] for character class", - "range out of order in character class", - "\\ at end of pattern" + REGEXP_ERROR_PREFIX "regular expression too large", + REGEXP_ERROR_PREFIX "numbers out of order in {} quantifier", + REGEXP_ERROR_PREFIX "nothing to repeat", + REGEXP_ERROR_PREFIX "missing )", + REGEXP_ERROR_PREFIX "unmatched parentheses", + REGEXP_ERROR_PREFIX "unrecognized character after (?", + REGEXP_ERROR_PREFIX "missing terminating ] for character class", + REGEXP_ERROR_PREFIX "range out of order in character class", + REGEXP_ERROR_PREFIX "\\ at end of pattern" }; return errorMessages[m_err]; @@ -839,14 +831,6 @@ private: * * void disjunction(); * - * void regexBegin(); - * void regexEnd(); - * void regexError(); - * - * Before any call recording tokens are made, regexBegin() will be called on the - * delegate once. Once parsing is complete either regexEnd() or regexError() will - * be called, as appropriate. - * * The regular expression is described by a sequence of assertion*() and atom*() * callbacks to the delegate, describing the terms in the regular expression. * Following an atom a quantifyAtom() call may occur to indicate that the previous @@ -884,4 +868,4 @@ const char* parse(Delegate& delegate, const UString& pattern, unsigned backRefer } } // namespace JSC::Yarr -#endif // RegexParser_h +#endif // YarrParser_h diff --git a/Source/JavaScriptCore/yarr/RegexPattern.cpp b/Source/JavaScriptCore/yarr/YarrPattern.cpp index e737d0e..112b65d 100644 --- a/Source/JavaScriptCore/yarr/RegexPattern.cpp +++ b/Source/JavaScriptCore/yarr/YarrPattern.cpp @@ -25,9 +25,10 @@ */ #include "config.h" +#include "YarrPattern.h" -#include "RegexInterpreter.h" -#include "RegexPattern.h" +#include "Yarr.h" +#include "YarrParser.h" #include <wtf/Vector.h> using namespace WTF; @@ -338,17 +339,20 @@ private: bool m_isCaseInsensitive; }; -class RegexPatternConstructor { +class YarrPatternConstructor { public: - RegexPatternConstructor(RegexPattern& pattern) + YarrPatternConstructor(YarrPattern& pattern) : m_pattern(pattern) , m_characterClassConstructor(pattern.m_ignoreCase) , m_beginCharHelper(&pattern.m_beginChars, pattern.m_ignoreCase) , m_invertParentheticalAssertion(false) { + m_pattern.m_body = new PatternDisjunction(); + m_alternative = m_pattern.m_body->addNewAlternative(); + m_pattern.m_disjunctions.append(m_pattern.m_body); } - ~RegexPatternConstructor() + ~YarrPatternConstructor() { } @@ -356,6 +360,10 @@ public: { m_pattern.reset(); m_characterClassConstructor.reset(); + + m_pattern.m_body = new PatternDisjunction(); + m_alternative = m_pattern.m_body->addNewAlternative(); + m_pattern.m_disjunctions.append(m_pattern.m_body); } void assertionBOL() @@ -605,19 +613,6 @@ public: m_alternative = m_alternative->m_parent->addNewAlternative(); } - void regexBegin() - { - m_pattern.m_body = new PatternDisjunction(); - m_alternative = m_pattern.m_body->addNewAlternative(); - m_pattern.m_disjunctions.append(m_pattern.m_body); - } - void regexEnd() - { - } - void regexError() - { - } - unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition) { alternative->m_hasFixedSize = true; @@ -636,7 +631,7 @@ public: case PatternTerm::TypeBackReference: term.inputPosition = currentInputPosition; term.frameLocation = currentCallFrameSize; - currentCallFrameSize += RegexStackSpaceForBackTrackInfoBackReference; + currentCallFrameSize += YarrStackSpaceForBackTrackInfoBackReference; alternative->m_hasFixedSize = false; break; @@ -647,7 +642,7 @@ public: term.inputPosition = currentInputPosition; if (term.quantityType != QuantifierFixedCount) { term.frameLocation = currentCallFrameSize; - currentCallFrameSize += RegexStackSpaceForBackTrackInfoPatternCharacter; + currentCallFrameSize += YarrStackSpaceForBackTrackInfoPatternCharacter; alternative->m_hasFixedSize = false; } else currentInputPosition += term.quantityCount; @@ -657,7 +652,7 @@ public: term.inputPosition = currentInputPosition; if (term.quantityType != QuantifierFixedCount) { term.frameLocation = currentCallFrameSize; - currentCallFrameSize += RegexStackSpaceForBackTrackInfoCharacterClass; + currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass; alternative->m_hasFixedSize = false; } else currentInputPosition += term.quantityCount; @@ -668,20 +663,20 @@ public: term.frameLocation = currentCallFrameSize; if (term.quantityCount == 1 && !term.parentheses.isCopy) { if (term.quantityType != QuantifierFixedCount) - currentCallFrameSize += RegexStackSpaceForBackTrackInfoParenthesesOnce; + currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce; currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition); // If quantity is fixed, then pre-check its minimum size. if (term.quantityType == QuantifierFixedCount) currentInputPosition += term.parentheses.disjunction->m_minimumSize; term.inputPosition = currentInputPosition; } else if (term.parentheses.isTerminal) { - currentCallFrameSize += RegexStackSpaceForBackTrackInfoParenthesesTerminal; + currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal; currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition); term.inputPosition = currentInputPosition; } else { term.inputPosition = currentInputPosition; setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition); - currentCallFrameSize += RegexStackSpaceForBackTrackInfoParentheses; + currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses; } // Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length. alternative->m_hasFixedSize = false; @@ -690,7 +685,7 @@ public: case PatternTerm::TypeParentheticalAssertion: term.inputPosition = currentInputPosition; term.frameLocation = currentCallFrameSize; - currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + RegexStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition); + currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition); break; } } @@ -702,7 +697,7 @@ public: unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition) { if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1)) - initialCallFrameSize += RegexStackSpaceForBackTrackInfoAlternative; + initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative; unsigned minimumInputSize = UINT_MAX; unsigned maximumCallFrameSize = 0; @@ -927,7 +922,7 @@ public: } private: - RegexPattern& m_pattern; + YarrPattern& m_pattern; PatternAlternative* m_alternative; CharacterClassConstructor m_characterClassConstructor; BeginCharHelper m_beginCharHelper; @@ -935,10 +930,9 @@ private: bool m_invertParentheticalAssertion; }; - -static const char* compileRegex(const UString& patternString, RegexPattern& pattern) +const char* YarrPattern::compile(const UString& patternString) { - RegexPatternConstructor constructor(pattern); + YarrPatternConstructor constructor(*this); if (const char* error = parse(constructor, patternString)) return error; @@ -947,8 +941,8 @@ static const char* compileRegex(const UString& patternString, RegexPattern& patt // Quoting Netscape's "What's new in JavaScript 1.2", // "Note: if the number of left parentheses is less than the number specified // in \#, the \# is taken as an octal escape as described in the next row." - if (pattern.containsIllegalBackReference()) { - unsigned numSubpatterns = pattern.m_numSubpatterns; + if (containsIllegalBackReference()) { + unsigned numSubpatterns = m_numSubpatterns; constructor.reset(); #if !ASSERT_DISABLED @@ -957,7 +951,7 @@ static const char* compileRegex(const UString& patternString, RegexPattern& patt parse(constructor, patternString, numSubpatterns); ASSERT(!error); - ASSERT(numSubpatterns == pattern.m_numSubpatterns); + ASSERT(numSubpatterns == m_numSubpatterns); } constructor.checkForTerminalParentheses(); @@ -967,9 +961,9 @@ static const char* compileRegex(const UString& patternString, RegexPattern& patt constructor.setupBeginChars(); return 0; -}; +} -RegexPattern::RegexPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error) +YarrPattern::YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error) : m_ignoreCase(ignoreCase) , m_multiline(multiline) , m_containsBackreferences(false) @@ -985,7 +979,7 @@ RegexPattern::RegexPattern(const UString& pattern, bool ignoreCase, bool multili , nonspacesCached(0) , nonwordcharCached(0) { - *error = compileRegex(pattern, *this); + *error = compile(pattern); } } } diff --git a/Source/JavaScriptCore/yarr/RegexPattern.h b/Source/JavaScriptCore/yarr/YarrPattern.h index 6833dd6..2172dda 100644 --- a/Source/JavaScriptCore/yarr/RegexPattern.h +++ b/Source/JavaScriptCore/yarr/YarrPattern.h @@ -24,8 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RegexPattern_h -#define RegexPattern_h +#ifndef YarrPattern_h +#define YarrPattern_h #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> @@ -34,15 +34,6 @@ namespace JSC { namespace Yarr { -#define RegexStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers. -#define RegexStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers. -#define RegexStackSpaceForBackTrackInfoBackReference 2 -#define RegexStackSpaceForBackTrackInfoAlternative 1 // One per alternative. -#define RegexStackSpaceForBackTrackInfoParentheticalAssertion 1 -#define RegexStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers. -#define RegexStackSpaceForBackTrackInfoParenthesesTerminal 1 -#define RegexStackSpaceForBackTrackInfoParentheses 2 - struct PatternDisjunction; struct CharacterRange { @@ -282,7 +273,7 @@ struct PatternDisjunction : FastAllocBase { // You probably don't want to be calling these functions directly // (please to be calling newlineCharacterClass() et al on your -// friendly neighborhood RegexPattern instance to get nicely +// friendly neighborhood YarrPattern instance to get nicely // cached copies). CharacterClass* newlineCreate(); CharacterClass* digitsCreate(); @@ -316,10 +307,10 @@ struct BeginChar { unsigned mask; }; -struct RegexPattern { - RegexPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error); +struct YarrPattern { + YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error); - ~RegexPattern() + ~YarrPattern() { deleteAllValues(m_disjunctions); deleteAllValues(m_userCharacterClasses); @@ -410,6 +401,8 @@ struct RegexPattern { Vector<BeginChar> m_beginChars; private: + const char* compile(const UString& patternString); + CharacterClass* newlineCached; CharacterClass* digitsCached; CharacterClass* spacesCached; @@ -421,4 +414,4 @@ private: } } // namespace JSC::Yarr -#endif // RegexPattern_h +#endif // YarrPattern_h diff --git a/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp b/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp new file mode 100644 index 0000000..51fda94 --- /dev/null +++ b/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "YarrSyntaxChecker.h" + +#include "YarrParser.h" + +namespace JSC { namespace Yarr { + +class SyntaxChecker { +public: + void assertionBOL() {} + void assertionEOL() {} + void assertionWordBoundary(bool) {} + void atomPatternCharacter(UChar) {} + void atomBuiltInCharacterClass(BuiltInCharacterClassID, bool) {} + void atomCharacterClassBegin(bool = false) {} + void atomCharacterClassAtom(UChar) {} + void atomCharacterClassRange(UChar, UChar) {} + void atomCharacterClassBuiltIn(BuiltInCharacterClassID, bool) {} + void atomCharacterClassEnd() {} + void atomParenthesesSubpatternBegin(bool = true) {} + void atomParentheticalAssertionBegin(bool = false) {} + void atomParenthesesEnd() {} + void atomBackReference(unsigned) {} + void quantifyAtom(unsigned, unsigned, bool) {} + void disjunction() {} +}; + +const char* checkSyntax(const UString& pattern) +{ + SyntaxChecker syntaxChecker; + return parse(syntaxChecker, pattern); +} + +}} // JSC::YARR diff --git a/Source/JavaScriptCore/yarr/YarrSyntaxChecker.h b/Source/JavaScriptCore/yarr/YarrSyntaxChecker.h new file mode 100644 index 0000000..e48cb9e --- /dev/null +++ b/Source/JavaScriptCore/yarr/YarrSyntaxChecker.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef YarrSyntaxChecker_h +#define YarrSyntaxChecker_h + +#include <UString.h> + +namespace JSC { namespace Yarr { + +const char* checkSyntax(const UString& pattern); + +}} // JSC::YARR + +#endif // YarrSyntaxChecker_h + |