diff options
Diffstat (limited to 'JavaScriptCore')
49 files changed, 1231 insertions, 437 deletions
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index 85860d8..045347a 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,483 @@ +2010-09-20 Michael Saboff <msaboff@apple.com> + + Reviewed by Gavin Barraclough. + + Fixed detection of alternative smaller than the first alternative + to only check looping alternatives. + https://bugs.webkit.org/show_bug.cgi?id=46049 + + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateDisjunction): + +2010-09-20 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by Geoffrey Garen. + + REGRESSION(67790): jsc tests are failed with YARR interpreter + https://bugs.webkit.org/show_bug.cgi?id=46083 + + Fix the initializing of the lastSubpatternId member of + parentheses. + + * yarr/RegexCompiler.cpp: + (JSC::Yarr::RegexPatternConstructor::atomParenthesesEnd): + +2010-09-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 46077 - ASSERT failure in YARR JIT + + We will currently attempt to loop if there are multiple alternatives, they are all + BOL predicated, and the last alternative is longer then the first - however if all + alternatives are BOL predicated the head of loop label will not have been set, and + we'll try to link a jump to an undefined label. Stop doing so. + + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateDisjunction): + +2010-09-20 Adam Roben <aroben@apple.com> + + Export RegExpObject::info from JavaScriptCore + + This allows obj->inherits(&RegExpObject::info) to work correctly from + outside JavaScriptCore.dll on Windows. + + Fixes <http://webkit.org/b/46098> + fast/loader/stateobjects/pushstate-object-types.html fails on Windows + + Reviewed by John Sullivan. + + * runtime/RegExpObject.h: Added JS_EXPORTDATA to the info member, as + we already have for some other classes whose info members have to be + used from outside the DLL. + +2010-09-19 Gavin Barraclough <barraclough@apple.com> + + Windows build fix pt 2. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-09-19 Gavin Barraclough <barraclough@apple.com> + + Windows build fix pt 1. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-09-19 Gavin Barraclough <barraclough@apple.com> + + Build fix - implicit double-to-int conversion invalid on 32-bit. + + * runtime/DatePrototype.cpp: + (JSC::fillStructuresUsingDateArgs): + (JSC::dateProtoFuncSetYear): + +2010-09-19 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 46065 - Unify implementation of ToInt32 and ToUInt32, don't use fmod. + + These methods implement the same conversion (see discussion in the notes + of sections of 9.5 and 9.6 of the spec), only differing in how the result + is interpretted. + + Date prototype is incorrectly using toInt32, and this is causing us to + provide an output value indicating whether the input to ToInt32 was finite + (the corresponding methods on Date are actually spec'ed to use ToInteger, + not ToInt32). This patch partially fixes this in order to remove this + bogus output value, hoewever more work will be require to bring Date + fully up to spec compliance (the constructor is still performing ToInt32 + conversions). + + * JavaScriptCore.exp: + * runtime/DatePrototype.cpp: + (JSC::fillStructuresUsingTimeArgs): + (JSC::fillStructuresUsingDateArgs): + (JSC::dateProtoFuncSetYear): + * runtime/JSValue.cpp: + (JSC::toInt32): + * runtime/JSValue.h: + (JSC::toUInt32): + (JSC::JSValue::toInt32): + (JSC::JSValue::toUInt32): + +2010-09-18 Darin Adler <darin@apple.com> + + First step in fixing Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + Removed incorrect symbol. The build will probably still fail, + but the failure will tell us what symbol to add. + +2010-09-18 Michael Saboff <msaboff@apple.com> + + Reviewed by Gavin Barraclough. + + Added code to unroll regular expressions containing ^. + Alternatives that begin with ^ are tagged during parsing + and rolled up in containing sub expression structs. + After parsing, a regular expression flagged as containing + a ^ (a.k.a. BOL) is processed further in optimizeBOL(). + A copy of the disjunction is made excluding alternatives that + are rooted with BOL. The original alternatives are flagged + to only be executed once. The copy of the other alternatives are + added to the original expression. + In the case that all original alternatives are flagged, there + won't be any looping alternatives. + The JIT generator will emit code accordingly, executing the + original alternatives once and then looping over the + alternatives that aren't anchored with a BOL (if any). + https://bugs.webkit.org/show_bug.cgi?id=45787 + + * yarr/RegexCompiler.cpp: + (JSC::Yarr::RegexPatternConstructor::assertionBOL): + (JSC::Yarr::RegexPatternConstructor::atomParenthesesEnd): + (JSC::Yarr::RegexPatternConstructor::copyDisjunction): + (JSC::Yarr::RegexPatternConstructor::copyTerm): + (JSC::Yarr::RegexPatternConstructor::optimizeBOL): + (JSC::Yarr::compileRegex): + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateDisjunction): + * yarr/RegexPattern.h: + (JSC::Yarr::PatternAlternative::PatternAlternative): + (JSC::Yarr::PatternAlternative::setOnceThrough): + (JSC::Yarr::PatternAlternative::onceThrough): + (JSC::Yarr::PatternDisjunction::PatternDisjunction): + (JSC::Yarr::RegexPattern::RegexPattern): + (JSC::Yarr::RegexPattern::reset): + +2010-09-18 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Darin Adler. + + Rename Wince files to WinCE + https://bugs.webkit.org/show_bug.cgi?id=37287 + + * wtf/unicode/Unicode.h: + * wtf/unicode/wince/UnicodeWinCE.cpp: Copied from JavaScriptCore/wtf/unicode/wince/UnicodeWince.cpp. + * wtf/unicode/wince/UnicodeWinCE.h: Copied from JavaScriptCore/wtf/unicode/wince/UnicodeWince.h. + * wtf/unicode/wince/UnicodeWince.cpp: Removed. + * wtf/unicode/wince/UnicodeWince.h: Removed. + * wtf/wince/FastMallocWinCE.h: Copied from JavaScriptCore/wtf/wince/FastMallocWince.h. + * wtf/wince/FastMallocWince.h: Removed. + +2010-09-18 Ademar de Souza Reis Jr <ademar.reis@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + Enable Platform Strategies on Qt + + [Qt] Turn on PLATFORM_STRATEGIES + https://bugs.webkit.org/show_bug.cgi?id=45831 + + * wtf/Platform.h: Enable Platform Strategies when building QtWebkit + +2010-09-17 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Imprecise tracking of variable capture leads to overly pessimistic creation of activations + https://bugs.webkit.org/show_bug.cgi?id=46020 + + The old logic for track free and captured variables would cause us + to decide we needed an activation in every function along the scope + chain between a variable capture and its declaration. We now track + captured variables precisely which requires a bit of additional work + + The most substantial change is that the parsing routine needs to + be passed the list of function parameters when reparsing a function + as when reparsing we don't parse the function declaration itself only + its body. + + * JavaScriptCore.exp: + * parser/JSParser.cpp: + (JSC::JSParser::Scope::Scope): + (JSC::JSParser::Scope::needsFullActivation): + We need to distinguish between use of a feature that requires + an activation and eval so we now get this additional flag. + (JSC::JSParser::Scope::collectFreeVariables): + (JSC::JSParser::Scope::getCapturedVariables): + We can't simply return the list of "capturedVariables" now as + is insufficiently precise, so we compute them instead. + (JSC::JSParser::popScope): + (JSC::jsParse): + (JSC::JSParser::JSParser): + (JSC::JSParser::parseProgram): + (JSC::JSParser::parseWithStatement): + (JSC::JSParser::parseTryStatement): + (JSC::JSParser::parseFunctionInfo): + (JSC::JSParser::parseFunctionDeclaration): + (JSC::JSParser::parseProperty): + (JSC::JSParser::parseMemberExpression): + * parser/JSParser.h: + * parser/Parser.cpp: + (JSC::Parser::parse): + * parser/Parser.h: + (JSC::Parser::parse): + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + (JSC::ProgramExecutable::checkSyntax): + (JSC::ProgramExecutable::compileInternal): + (JSC::FunctionExecutable::compileForCallInternal): + (JSC::FunctionExecutable::compileForConstructInternal): + (JSC::FunctionExecutable::reparseExceptionInfo): + (JSC::EvalExecutable::reparseExceptionInfo): + (JSC::FunctionExecutable::fromGlobalCode): + Pass function parameters (if available) to the parser. + +2010-09-17 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Add IsFloatingPoint and IsArithmetic type traits + https://bugs.webkit.org/show_bug.cgi?id=46018 + + * wtf/TypeTraits.h: + * wtf/TypeTraits.cpp: + +2010-09-17 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Oliver Hunt. + + [GTK] FontPlatformDataFreeType should use smart pointers to hold its members + https://bugs.webkit.org/show_bug.cgi?id=45917 + + Added support to PlatformRefPtr for handling HashTableDeletedValue. + + * wtf/PlatformRefPtr.h: + (WTF::PlatformRefPtr::PlatformRefPtr): Added a constructor that takes HashTableDeletedValue. + (WTF::PlatformRefPtr::isHashTableDeletedValue): Added. + +2010-09-16 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Crash due to timer triggered GC on one heap while another heap is active + https://bugs.webkit.org/show_bug.cgi?id=45932 + <rdar://problem/8318446> + + The GC timer may trigger for one heap while another heap is active. This + is safe, but requires us to ensure that we have temporarily associated the + thread's identifierTable with the heap we're collecting on. Otherwise we + may end up with the identifier tables in an inconsistent state leading to + an eventual crash. + + * runtime/Collector.cpp: + (JSC::Heap::allocate): + (JSC::Heap::reset): + (JSC::Heap::collectAllGarbage): + Add assertions to ensure we have the correct identifierTable active + while collecting. + * runtime/GCActivityCallbackCF.cpp: + (JSC::DefaultGCActivityCallbackPlatformData::trigger): + Temporarily make the expected IdentifierTable active + * wtf/WTFThreadData.h: + (JSC::IdentifierTable::remove): + Make it possible to see when IdentifierTable::remove has succeeded + * wtf/text/StringImpl.cpp: + (WTF::StringImpl::~StringImpl): + CRASH if an StringImpl is an Identifier but isn't present in the + active IdentifierTable. If we get to this state something has + gone wrong and we should just crash immediately. + +2010-09-16 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Xan Lopez. + + [GTK] Implement dissolveDragImageToFraction + https://bugs.webkit.org/show_bug.cgi?id=45826 + + * wtf/gobject/GTypedefs.h: Added forward declarations for GtkWindow and GdkEventExpose. + +2010-09-16 Eric Uhrhane <ericu@chromium.org> + + Reviewed by Jian Li. + + Unify FILE_SYSTEM and FILE_WRITER enables under the name FILE_SYSTEM. + https://bugs.webkit.org/show_bug.cgi?id=45798 + + * Configurations/FeatureDefines.xcconfig: + +2010-09-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Use free variable analysis to improve activation performance + https://bugs.webkit.org/show_bug.cgi?id=45837 + + Adds free and captured variable tracking to the JS parser. This + allows us to avoid construction of an activation object in some + cases. Future patches will make more use of this information to + improve those cases where activations are still needed. + + * parser/ASTBuilder.h: + * parser/JSParser.cpp: + (JSC::JSParser::Scope::Scope): + (JSC::JSParser::Scope::declareVariable): + (JSC::JSParser::Scope::useVariable): + (JSC::JSParser::Scope::collectFreeVariables): + (JSC::JSParser::Scope::capturedVariables): + (JSC::JSParser::ScopeRef::ScopeRef): + (JSC::JSParser::ScopeRef::operator->): + (JSC::JSParser::ScopeRef::index): + (JSC::JSParser::currentScope): + (JSC::JSParser::pushScope): + (JSC::JSParser::popScope): + (JSC::JSParser::parseProgram): + (JSC::JSParser::parseVarDeclarationList): + (JSC::JSParser::parseConstDeclarationList): + (JSC::JSParser::parseTryStatement): + (JSC::JSParser::parseFormalParameters): + (JSC::JSParser::parseFunctionInfo): + (JSC::JSParser::parseFunctionDeclaration): + (JSC::JSParser::parsePrimaryExpression): + * parser/Nodes.cpp: + (JSC::ScopeNodeData::ScopeNodeData): + (JSC::ScopeNode::ScopeNode): + (JSC::ProgramNode::ProgramNode): + (JSC::ProgramNode::create): + (JSC::EvalNode::EvalNode): + (JSC::EvalNode::create): + (JSC::FunctionBodyNode::FunctionBodyNode): + (JSC::FunctionBodyNode::create): + * parser/Nodes.h: + (JSC::ScopeNode::needsActivation): + (JSC::ScopeNode::hasCapturedVariables): + * parser/Parser.cpp: + (JSC::Parser::didFinishParsing): + * parser/Parser.h: + (JSC::Parser::parse): + * parser/SyntaxChecker.h: + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + (JSC::ProgramExecutable::compileInternal): + (JSC::FunctionExecutable::compileForCallInternal): + (JSC::FunctionExecutable::compileForConstructInternal): + * runtime/Executable.h: + (JSC::ScriptExecutable::needsActivation): + (JSC::ScriptExecutable::recordParse): + +2010-09-14 Hyung Song <beergun@company100.net> + + Reviewed by Kent Tamura. + + [BREWMP] Add IMemGroup and IMemSpace to OwnPtr type. + https://bugs.webkit.org/show_bug.cgi?id=44764 + + * wtf/OwnPtrCommon.h: + * wtf/brew/OwnPtrBrew.cpp: + (WTF::deleteOwnedPtr): + +2010-09-14 Darin Adler <darin@apple.com> + + Reviewed by Geoffrey Garen. + + Sort with non-numeric custom sort function fails on array with length but no values + https://bugs.webkit.org/show_bug.cgi?id=45781 + + * runtime/JSArray.cpp: + (JSC::JSArray::sort): Replaced early exit for an array of length zero to instead + exit for any array without values, even if it has a non-0 length. + +2010-09-14 Steve Falkenburg <sfalken@apple.com> + + Windows production build fix. + Roll out r65143. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make: + +2010-09-14 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Darin Adler. + + Share UnicodeMacrosFromICU.h + https://bugs.webkit.org/show_bug.cgi?id=45710 + + glib, qt4 and wince use the same macros from ICU. + Remove the code duplication and use the same header file. + + * wtf/unicode/UnicodeMacrosFromICU.h: Copied from JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h. + * wtf/unicode/glib/UnicodeMacrosFromICU.h: Removed. + * wtf/unicode/qt4/UnicodeQt4.h: + * wtf/unicode/wince/UnicodeWince.h: + +2010-09-13 Darin Adler <darin@apple.com> + + Reviewed by Adam Barth. + + Preparation for eliminating deprecatedParseURL + https://bugs.webkit.org/show_bug.cgi?id=45695 + + * wtf/text/WTFString.h: Added isAllSpecialCharacters, moved here from + the HTML tree builder. + +2010-09-13 Darin Fisher <darin@chromium.org> + + Reviewed by David Levin. + + Add option to conditionally compile smooth scrolling support. + https://bugs.webkit.org/show_bug.cgi?id=45689 + + ENABLE(SMOOTH_SCROLLING) is disabled by default for all platforms. + + * wtf/Platform.h: + +2010-09-13 Adam Roben <aroben@apple.com> + + Copy JavaScriptCore's generated sources to the right directory + + * JavaScriptCore.vcproj/JavaScriptCore.make: Fixed typo. + +2010-09-13 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Kent Tamura. + + [BREWMP] Don't call _msize + https://bugs.webkit.org/show_bug.cgi?id=45556 + + Because Brew MP uses its own memory allocator, it is not correct to use + _msize in fastMallocSize. Add !PLATFORM(BREWMP) guard. + + * wtf/FastMalloc.cpp: + (WTF::fastMallocSize): + +2010-09-11 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Andreas Kling. + + [Qt] V8 port: webcore project files changes + https://bugs.webkit.org/show_bug.cgi?id=45141 + + * JavaScriptCore.pro: Moved wtf specific files to wtf.pri, + so that they can also be used from WebCore.pro for v8 builds. + * wtf/wtf.pri: Added. + +2010-09-10 Fridrich Strba <fridrich.strba@bluewin.ch> + + Reviewed by Andreas Kling. + + Add a define missing when building with glib unicode backend + https://bugs.webkit.org/show_bug.cgi?id=45544 + + * wtf/unicode/glib/UnicodeMacrosFromICU.h: + +2010-09-10 Stephanie Lewis <slewis@apple.com> + + Reviewed by Alexey Proskuryakov. + + Refactor JavaScriptCore memory statistics so that WebKit doesn't need to know + about the JIT and other implementation details of JavaScriptCore. Necessary + to fix PPC build. + + https://bugs.webkit.org/show_bug.cgi?id=45528 + + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/MemoryStatistics.cpp: Added. + (JSC::memoryStatistics): + * runtime/MemoryStatistics.h: Added. + 2010-09-09 Michael Saboff <msaboff@apple.com> Reviewed by Gavin Barraclough. diff --git a/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/JavaScriptCore/Configurations/FeatureDefines.xcconfig index f2b4c09..2ed3a8e 100644 --- a/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -69,7 +69,6 @@ ENABLE_EVENTSOURCE = ENABLE_EVENTSOURCE; ENABLE_FILTERS = $(ENABLE_FILTERS_$(REAL_PLATFORM_NAME)); ENABLE_FILTERS_macosx = ENABLE_FILTERS; -ENABLE_FILE_WRITER = ; ENABLE_FILE_SYSTEM = ; ENABLE_GEOLOCATION = ENABLE_GEOLOCATION; @@ -120,4 +119,4 @@ ENABLE_XHTMLMP = ; ENABLE_XPATH = ENABLE_XPATH; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_LINK_PREFETCH) $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_WRITER) $(ENABLE_FILE_SYSTEM) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_LINK_PREFETCH) $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_SYSTEM) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); diff --git a/JavaScriptCore/Configurations/Version.xcconfig b/JavaScriptCore/Configurations/Version.xcconfig index 673e234..e82e464 100644 --- a/JavaScriptCore/Configurations/Version.xcconfig +++ b/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 534; -MINOR_VERSION = 8; +MINOR_VERSION = 9; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index ee0bfb7..13b9676 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -132,7 +132,6 @@ __ZN3JSC12JSGlobalData14sharedInstanceEv __ZN3JSC12JSGlobalData15dumpRegExpTraceEv __ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE __ZN3JSC12JSGlobalDataD1Ev -__ZN3JSC12RegisterFile18committedByteCountEv __ZN3JSC12SamplingTool5setupEv __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE __ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh @@ -151,6 +150,7 @@ __ZN3JSC13SamplingFlags4stopEv __ZN3JSC13SamplingFlags5startEv __ZN3JSC13SamplingFlags7s_flagsE __ZN3JSC13StatementNode6setLocEii +__ZN3JSC14heapStatisticsEPNS_12JSGlobalDataE __ZN3JSC14JSGlobalObject10globalExecEv __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj @@ -168,7 +168,6 @@ __ZN3JSC14TimeoutChecker5resetEv __ZN3JSC14throwTypeErrorEPNS_9ExecStateE __ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE __ZN3JSC15createTypeErrorEPNS_9ExecStateERKNS_7UStringE -__ZN3JSC15toInt32SlowCaseEdRb __ZN3JSC16InternalFunction4infoE __ZN3JSC16InternalFunction4nameEPNS_9ExecStateE __ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEPNS_14JSGlobalObjectEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_10IdentifierE @@ -178,7 +177,6 @@ __ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNam __ZN3JSC16WeakGCHandlePool4freeEPNS_12WeakGCHandleE __ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE __ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE -__ZN3JSC16toUInt32SlowCaseEdRb __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb __ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE __ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi @@ -193,10 +191,10 @@ __ZN3JSC18PropertyDescriptor17defaultAttributesE __ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j __ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE __ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE -__ZN3JSC19ExecutableAllocator18committedByteCountEv __ZN3JSC19initializeThreadingEv __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE __ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE +__ZN3JSC22globalMemoryStatisticsEv __ZN3JSC23AbstractSamplingCounter4dumpEv __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE @@ -241,7 +239,6 @@ __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE __ZN3JSC6JSLock9lockCountEv __ZN3JSC6JSLockC1EPNS_9ExecStateE -__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE __ZN3JSC7JSArray12markChildrenERNS_9MarkStackE __ZN3JSC7JSArray15setSubclassDataEPv __ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE @@ -264,6 +261,7 @@ __ZN3JSC7UStringC1EPKc __ZN3JSC7UStringC1EPKcj __ZN3JSC7UStringC1EPKt __ZN3JSC7UStringC1EPKtj +__ZN3JSC7toInt32Ed __ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE diff --git a/JavaScriptCore/JavaScriptCore.pro b/JavaScriptCore/JavaScriptCore.pro index 7f6b27d..f463f41 100644 --- a/JavaScriptCore/JavaScriptCore.pro +++ b/JavaScriptCore/JavaScriptCore.pro @@ -66,6 +66,7 @@ wince* { } include(pcre/pcre.pri) +include(wtf/wtf.pri) SOURCES += \ API/JSBase.cpp \ @@ -203,42 +204,11 @@ SOURCES += \ runtime/Structure.cpp \ runtime/TimeoutChecker.cpp \ runtime/UString.cpp \ - wtf/Assertions.cpp \ - wtf/ByteArray.cpp \ - wtf/CurrentTime.cpp \ - wtf/DateMath.cpp \ - wtf/dtoa.cpp \ - wtf/FastMalloc.cpp \ - wtf/HashTable.cpp \ - wtf/MD5.cpp \ - wtf/MainThread.cpp \ - wtf/qt/MainThreadQt.cpp \ - wtf/qt/StringQt.cpp \ - wtf/qt/ThreadingQt.cpp \ - wtf/PageAllocation.cpp \ - wtf/RandomNumber.cpp \ - wtf/RefCountedLeakCounter.cpp \ - wtf/ThreadingNone.cpp \ - wtf/Threading.cpp \ - wtf/TypeTraits.cpp \ - wtf/WTFThreadData.cpp \ - wtf/text/AtomicString.cpp \ - wtf/text/CString.cpp \ - wtf/text/StringImpl.cpp \ - wtf/text/StringStatics.cpp \ - wtf/text/WTFString.cpp \ - wtf/unicode/CollatorDefault.cpp \ - wtf/unicode/icu/CollatorICU.cpp \ - wtf/unicode/UTF8.cpp \ yarr/RegexCompiler.cpp \ yarr/RegexInterpreter.cpp \ yarr/RegexJIT.cpp # Generated files, simply list them for JavaScriptCore -!contains(DEFINES, USE_SYSTEM_MALLOC) { - SOURCES += wtf/TCSystemAlloc.cpp -} - # Disable C++0x mode in JSC for those who enabled it in their Qt's mkspec *-g++*:QMAKE_CXXFLAGS -= -std=c++0x -std=gnu++0x diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make index 4c47ac6..4f049c9 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make @@ -32,4 +32,4 @@ install: xcopy "$(OBJROOT)\lib\*" "$(DSTROOT)\AppleInternal\lib\" /e/v/i/h/y xcopy "$(OBJROOT)\bin\JavaScriptCore.resources\*" "$(DSTROOT)\AppleInternal\bin\JavaScriptCore.resources" /e/v/i/h/y -mkdir "$(DSTROOT)\AppleInternal\Sources\JavaScriptCore" - xcopy "$(OBJROOT)\obj\JavaScriptCore\DerivedSources\*" "$(DSTROOT)\AppleInternal\Sources\WebCore" /e/v/i/h/y + xcopy "$(OBJROOT)\obj\JavaScriptCore\DerivedSources\*" "$(DSTROOT)\AppleInternal\Sources\JavaScriptCore" /e/v/i/h/y diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 7226326..ba564f0 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -232,7 +232,6 @@ EXPORTS ?nonInlineNaN@JSC@@YANXZ ?objectCount@Heap@JSC@@QBEIXZ ?objectProtoFuncToString@JSC@@YI_JPAVExecState@1@@Z - ?parse@Parser@JSC@@AAEXPAVJSGlobalData@2@PAHPAVUString@2@@Z ?parseDateFromNullTerminatedCharacters@WTF@@YANPBD@Z ?pool@WeakGCHandle@JSC@@QAEPAVWeakGCHandlePool@2@XZ ?profiler@Profiler@JSC@@SAPAV12@XZ @@ -305,7 +304,7 @@ EXPORTS ?toBoolean@JSCell@JSC@@UBE_NPAVExecState@2@@Z ?toBoolean@JSObject@JSC@@UBE_NPAVExecState@2@@Z ?toBoolean@JSString@JSC@@EBE_NPAVExecState@2@@Z - ?toInt32SlowCase@JSC@@YAHNAA_N@Z + ?toInt32@JSC@@YAHN@Z ?toInteger@JSValue@JSC@@QBENPAVExecState@2@@Z ?toNumber@JSCell@JSC@@UBENPAVExecState@2@@Z ?toNumber@JSObject@JSC@@UBENPAVExecState@2@@Z @@ -324,7 +323,6 @@ EXPORTS ?toThisObject@JSString@JSC@@EBEPAVJSObject@2@PAVExecState@2@@Z ?toThisObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z ?toUInt32@Identifier@JSC@@SAIABVUString@2@AA_N@Z - ?toUInt32SlowCase@JSC@@YAINAA_N@Z ?tryFastCalloc@WTF@@YA?AUTryMallocReturnValue@1@II@Z ?tryFastMalloc@WTF@@YA?AUTryMallocReturnValue@1@I@Z ?tryLock@Mutex@WTF@@QAE_NXZ diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make index a9493a3..098ff08 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make @@ -1,5 +1,4 @@ all: - -if not exist "$(WEBKITLIBRARIESDIR)\tools\vsprops\.svn" del /s/q "$(WEBKITLIBRARIESDIR)\tools\vsprops\" -xcopy /y/d/e/i "..\..\..\WebKitLibraries\win\tools" "$(WEBKITLIBRARIESDIR)\tools" touch "$(WEBKITOUTPUTDIR)\buildfailed" bash build-generated-files.sh "$(WEBKITOUTPUTDIR)" "$(WEBKITLIBRARIESDIR)" diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index bee44b6..675d26d 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -258,6 +258,8 @@ 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, ); }; }; 905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */; }; 90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; 93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93052C320FB792190048FDC3 /* ParserArena.cpp */; }; @@ -859,6 +861,8 @@ 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>"; }; 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefCountedLeakCounter.cpp; sourceTree = "<group>"; }; 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedLeakCounter.h; sourceTree = "<group>"; }; 9303F567099118FA00AD71B8 /* OwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtr.h; sourceTree = "<group>"; }; @@ -1735,6 +1739,8 @@ A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */, F692A86A0255597D01FF60F7 /* MathObject.cpp */, F692A86B0255597D01FF60F7 /* MathObject.h */, + 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */, + 90213E3C123A40C200D422F3 /* MemoryStatistics.h */, BC02E9080E1839DB000F9297 /* NativeErrorConstructor.cpp */, BC02E9090E1839DB000F9297 /* NativeErrorConstructor.h */, BC02E90A0E1839DB000F9297 /* NativeErrorPrototype.cpp */, @@ -2307,6 +2313,7 @@ 9714AF4F122F289A0092D9F5 /* URLSegments.h in Headers */, 9714AF5F122F32070092D9F5 /* ParsedURL.h in Headers */, 9714AF60122F32070092D9F5 /* URLString.h in Headers */, + 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2760,6 +2767,7 @@ A74DE1D0120B875600D40D5B /* ARMv7Assembler.cpp in Sources */, 9714AF46122F28850092D9F5 /* URLSegments.cpp in Sources */, 9714AF5E122F32070092D9F5 /* ParsedURL.cpp in Sources */, + 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/parser/ASTBuilder.h b/JavaScriptCore/parser/ASTBuilder.h index dbf3c07..40023f8 100644 --- a/JavaScriptCore/parser/ASTBuilder.h +++ b/JavaScriptCore/parser/ASTBuilder.h @@ -100,6 +100,7 @@ public: typedef std::pair<ExpressionNode*, BinaryOpInfo> BinaryOperand; static const bool CreatesAST = true; + static const bool NeedsFreeVariableInfo = true; ExpressionNode* makeBinaryNode(int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end); diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp index 820811e..540dc3b 100644 --- a/JavaScriptCore/parser/JSParser.cpp +++ b/JavaScriptCore/parser/JSParser.cpp @@ -67,7 +67,7 @@ static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024; class JSParser { public: - JSParser(Lexer*, JSGlobalData*, SourceProvider*); + JSParser(Lexer*, JSGlobalData*, FunctionParameters*, SourceProvider*); bool parseProgram(); private: struct AllowInOverride { @@ -161,7 +161,7 @@ private: template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd); template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context); enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; - template <FunctionRequirements, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine); + template <FunctionRequirements, bool nameIsInContainingScope, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine); ALWAYS_INLINE int isBinaryOperator(JSTokenType token); bool allowAutomaticSemicolon(); @@ -199,15 +199,105 @@ private: int m_assignmentCount; int m_nonLHSCount; bool m_syntaxAlreadyValidated; + + struct Scope { + Scope() + : m_usesEval(false) + , m_needsFullActivation(false) + { + } + + void declareVariable(const Identifier* ident) + { + m_declaredVariables.add(ident->ustring().impl()); + } + + void useVariable(const Identifier* ident, bool isEval) + { + m_usesEval |= isEval; + m_usedVariables.add(ident->ustring().impl()); + } + + void needsFullActivation() { m_needsFullActivation = true; } + + void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) + { + if (nestedScope->m_usesEval) + m_usesEval = true; + IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); + for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { + if (nestedScope->m_declaredVariables.contains(*ptr)) + continue; + m_usedVariables.add(*ptr); + if (shouldTrackClosedVariables) + m_closedVariables.add(*ptr); + } + } + + void getCapturedVariables(IdentifierSet& capturedVariables) + { + if (m_needsFullActivation || m_usesEval) { + capturedVariables.swap(m_declaredVariables); + return; + } + for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) { + if (!m_declaredVariables.contains(*ptr)) + continue; + capturedVariables.add(*ptr); + } + } + private: + bool m_usesEval; + bool m_needsFullActivation; + IdentifierSet m_declaredVariables; + IdentifierSet m_usedVariables; + IdentifierSet m_closedVariables; + }; + + typedef Vector<Scope, 10> ScopeStack; + + struct ScopeRef { + ScopeRef(ScopeStack* scopeStack, unsigned index) + : m_scopeStack(scopeStack) + , m_index(index) + { + } + Scope* operator->() { return &m_scopeStack->at(m_index); } + unsigned index() const { return m_index; } + private: + ScopeStack* m_scopeStack; + unsigned m_index; + }; + + ScopeRef currentScope() + { + return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); + } + + ScopeRef pushScope() + { + m_scopeStack.append(Scope()); + return currentScope(); + } + + void popScope(ScopeRef scope, bool shouldTrackClosedVariables) + { + ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); + ASSERT(m_scopeStack.size() > 1); + m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); + m_scopeStack.removeLast(); + } + + ScopeStack m_scopeStack; }; -int jsParse(JSGlobalData* globalData, const SourceCode* source) +int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, const SourceCode* source) { - JSParser parser(globalData->lexer, globalData, source->provider()); + JSParser parser(globalData->lexer, globalData, parameters, source->provider()); return parser.parseProgram(); } -JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, SourceProvider* provider) +JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, SourceProvider* provider) : m_lexer(lexer) , m_endAddress(0) , m_error(false) @@ -223,16 +313,24 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, SourceProvider* provi m_endAddress = wtfThreadData().approximatedStackStart() - kMaxParserStackUsage; next(); m_lexer->setLastLineNumber(tokenLine()); + ScopeRef scope = pushScope(); + if (parameters) { + for (unsigned i = 0; i < parameters->size(); i++) + scope->declareVariable(¶meters->at(i)); + } } bool JSParser::parseProgram() { ASTBuilder context(m_globalData, m_lexer); + ScopeRef scope = currentScope(); SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context); if (!sourceElements || !consume(EOFTOK)) return true; + IdentifierSet capturedVariables; + scope->getCapturedVariables(capturedVariables); m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(), - m_lastLine, context.numConstants()); + m_lastLine, context.numConstants(), capturedVariables); return false; } @@ -327,6 +425,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr lastIdent = name; next(); bool hasInitializer = match(EQUAL); + currentScope()->declareVariable(name); context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0); if (hasInitializer) { int varDivot = tokenStart() + 1; @@ -358,6 +457,7 @@ template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationLi const Identifier* name = m_token.m_data.ident; next(); bool hasInitializer = match(EQUAL); + currentScope()->declareVariable(name); context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0)); TreeExpression initializer = 0; if (hasInitializer) { @@ -552,6 +652,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBui template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context) { ASSERT(match(WITH)); + currentScope()->needsFullActivation(); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -650,17 +751,21 @@ template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuild int lastLine = m_lastLine; if (match(CATCH)) { + currentScope()->needsFullActivation(); next(); consumeOrFail(OPENPAREN); matchOrFail(IDENT); ident = m_token.m_data.ident; next(); + ScopeRef catchScope = pushScope(); + catchScope->declareVariable(ident); consumeOrFail(CLOSEPAREN); matchOrFail(OPENBRACE); int initialEvalCount = context.evalCount(); catchBlock = parseBlockStatement(context); failIfFalse(catchBlock); catchHasEval = initialEvalCount != context.evalCount(); + popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo); } if (match(FINALLY)) { @@ -757,6 +862,7 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame { matchOrFail(IDENT); usesArguments = m_globalData->propertyNames->arguments == *m_token.m_data.ident; + currentScope()->declareVariable(m_token.m_data.ident); TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident); TreeFormalParameterList tail = list; next(); @@ -764,6 +870,7 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame next(); matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; + currentScope()->declareVariable(ident); next(); usesArguments = usesArguments || m_globalData->propertyNames->arguments == *ident; tail = context.createFormalParameterList(tail, *ident); @@ -780,11 +887,14 @@ template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBu return context.createFunctionBody(); } -template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine) +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(); if (match(IDENT)) { name = m_token.m_data.ident; next(); + if (!nameIsInContainingScope) + functionScope->declareVariable(name); } else if (requirements == FunctionNeedsName) return false; consumeOrFail(OPENPAREN); @@ -804,7 +914,7 @@ template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool J failIfFalse(body); if (usesArguments) context.setUsesArguments(body); - + popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo); matchOrFail(CLOSEBRACE); closeBracePos = m_token.m_data.intValue; next(); @@ -821,8 +931,9 @@ template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(Tr int openBracePos = 0; int closeBracePos = 0; int bodyStartLine = 0; - failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)); + failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); failIfFalse(name); + currentScope()->declareVariable(name); return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } @@ -1113,7 +1224,7 @@ template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty type = PropertyNode::Setter; else fail(); - failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine)); + failIfFalse((parseFunctionInfo<FunctionNeedsName, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); return context.template createGetterOrSetterProperty<complete>(type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } case NUMBER: { @@ -1281,6 +1392,7 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre int start = tokenStart(); const Identifier* ident = m_token.m_data.ident; next(); + currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident); return context.createResolve(ident, start); } case STRING: { @@ -1364,7 +1476,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree int closeBracePos = 0; int bodyStartLine = 0; next(); - failIfFalse(parseFunctionInfo<FunctionNoRequirements>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)); + failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); base = context.createFunctionExpr(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } else base = parsePrimaryExpression(context); diff --git a/JavaScriptCore/parser/JSParser.h b/JavaScriptCore/parser/JSParser.h index b5a21d9..ab18fab 100644 --- a/JavaScriptCore/parser/JSParser.h +++ b/JavaScriptCore/parser/JSParser.h @@ -28,6 +28,7 @@ namespace JSC { +class FunctionParameters; class Identifier; class JSGlobalData; class SourceCode; @@ -154,6 +155,6 @@ struct JSToken { JSTokenInfo m_info; }; -int jsParse(JSGlobalData*, const SourceCode*); +int jsParse(JSGlobalData*, FunctionParameters*, const SourceCode*); } #endif // JSParser_h diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp index c41d735..534e28a 100644 --- a/JavaScriptCore/parser/Nodes.cpp +++ b/JavaScriptCore/parser/Nodes.cpp @@ -75,7 +75,7 @@ StatementNode* SourceElements::singleStatement() const // -----------------------------ScopeNodeData --------------------------- -ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants) +ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, int numConstants) : m_numConstants(numConstants) , m_statements(statements) { @@ -84,6 +84,7 @@ ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, Var m_varStack.swap(*varStack); if (funcStack) m_functionStack.swap(*funcStack); + m_capturedVariables.swap(capturedVariables); } // ------------------------------ ScopeNode ----------------------------- @@ -95,10 +96,10 @@ ScopeNode::ScopeNode(JSGlobalData* globalData) { } -ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants) +ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) : StatementNode(globalData) , ParserArenaRefCounted(globalData) - , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants))) + , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, capturedVariables, numConstants))) , m_features(features) , m_source(source) { @@ -111,14 +112,14 @@ StatementNode* ScopeNode::singleStatement() const // ------------------------------ ProgramNode ----------------------------- -inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) +inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants) { } -PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->data()->m_arena.last() == node); node->data()->m_arena.removeLast(); @@ -129,14 +130,14 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElem // ------------------------------ EvalNode ----------------------------- -inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) +inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants) { } -PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); + RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->data()->m_arena.last() == node); node->data()->m_arena.removeLast(); @@ -158,8 +159,8 @@ inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) { } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) - : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) + : ScopeNode(globalData, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) { } @@ -181,9 +182,9 @@ FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData) return new FunctionBodyNode(globalData); } -PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) { - RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants); ASSERT(node->data()->m_arena.last() == node); node->data()->m_arena.removeLast(); diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h index d25079b..2d8448c 100644 --- a/JavaScriptCore/parser/Nodes.h +++ b/JavaScriptCore/parser/Nodes.h @@ -81,6 +81,8 @@ namespace JSC { OpLogicalOr }; + typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet; + namespace DeclarationStacks { enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; typedef Vector<std::pair<const Identifier*, unsigned> > VarStack; @@ -1376,13 +1378,14 @@ namespace JSC { typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, int numConstants); + ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants); ParserArena m_arena; VarStack m_varStack; FunctionStack m_functionStack; int m_numConstants; SourceElements* m_statements; + IdentifierSet m_capturedVariables; }; class ScopeNode : public StatementNode, public ParserArenaRefCounted { @@ -1391,7 +1394,7 @@ namespace JSC { typedef DeclarationStacks::FunctionStack FunctionStack; ScopeNode(JSGlobalData*); - ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants); + ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); using ParserArenaRefCounted::operator new; @@ -1409,7 +1412,8 @@ namespace JSC { bool usesArguments() const { return m_features & ArgumentsFeature; } void setUsesArguments() { m_features |= ArgumentsFeature; } bool usesThis() const { return m_features & ThisFeature; } - bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } + bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); } + bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); } VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } @@ -1437,24 +1441,24 @@ namespace JSC { class ProgramNode : public ScopeNode { public: - static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; private: - ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class EvalNode : public ScopeNode { public: - static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; private: - EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1470,7 +1474,7 @@ namespace JSC { class FunctionBodyNode : public ScopeNode { public: static FunctionBodyNode* create(JSGlobalData*); - static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); FunctionParameters* parameters() const { return m_parameters.get(); } size_t parameterCount() const { return m_parameters->size(); } @@ -1486,7 +1490,7 @@ namespace JSC { private: FunctionBodyNode(JSGlobalData*); - FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); Identifier m_ident; RefPtr<FunctionParameters> m_parameters; diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp index 39ff597..bd77742 100644 --- a/JavaScriptCore/parser/Parser.cpp +++ b/JavaScriptCore/parser/Parser.cpp @@ -39,7 +39,7 @@ extern int jscyyparse(void*); namespace JSC { -void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) +void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, int* errLine, UString* errMsg) { #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::JavaScriptParseTimeCounter); @@ -60,7 +60,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) Lexer& lexer = *globalData->lexer; lexer.setCode(*m_source, m_arena); - int parseError = jsParse(globalData, m_source); + int parseError = jsParse(globalData, parameters, m_source); int lineNumber = lexer.lineNumber(); bool lexError = lexer.sawError(); lexer.clear(); @@ -76,11 +76,12 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) } void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, - ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants) + ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars) { m_sourceElements = sourceElements; m_varDeclarations = varStack; m_funcDeclarations = funcStack; + m_capturedVariables.swap(capturedVars); m_features = features; m_lastLine = lastLine; m_numConstants = numConstants; diff --git a/JavaScriptCore/parser/Parser.h b/JavaScriptCore/parser/Parser.h index c167980..9134de1 100644 --- a/JavaScriptCore/parser/Parser.h +++ b/JavaScriptCore/parser/Parser.h @@ -48,15 +48,16 @@ namespace JSC { class Parser : public Noncopyable { public: template <class ParsedNode> - PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, JSObject** exception); + PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, FunctionParameters*, JSObject** exception); void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, - ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants); + ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, + int lastLine, int numConstants, IdentifierSet&); ParserArena& arena() { return m_arena; } private: - void parse(JSGlobalData*, int* errLine, UString* errMsg); + void parse(JSGlobalData*, FunctionParameters*, int* errLine, UString* errMsg); // Used to determine type of error to report. bool isFunctionBodyNode(ScopeNode*) { return false; } @@ -67,13 +68,14 @@ namespace JSC { SourceElements* m_sourceElements; ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; + IdentifierSet m_capturedVariables; CodeFeatures m_features; int m_lastLine; int m_numConstants; }; template <class ParsedNode> - PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, JSObject** exception) + PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, FunctionParameters* parameters, JSObject** exception) { ASSERT(exception && !*exception); int errLine; @@ -82,17 +84,18 @@ namespace JSC { m_source = &source; if (ParsedNode::scopeIsFunction) globalData->lexer->setIsReparsing(); - parse(globalData, &errLine, &errMsg); + parse(globalData, parameters, &errLine, &errMsg); RefPtr<ParsedNode> result; if (m_sourceElements) { result = ParsedNode::create(globalData, - m_sourceElements, - m_varDeclarations ? &m_varDeclarations->data : 0, - m_funcDeclarations ? &m_funcDeclarations->data : 0, - source, - m_features, - m_numConstants); + m_sourceElements, + m_varDeclarations ? &m_varDeclarations->data : 0, + m_funcDeclarations ? &m_funcDeclarations->data : 0, + m_capturedVariables, + source, + m_features, + m_numConstants); result->setLoc(m_source->firstLine(), m_lastLine); } else if (lexicalGlobalObject) { // We can never see a syntax error when reparsing a function, since we should have diff --git a/JavaScriptCore/parser/SyntaxChecker.h b/JavaScriptCore/parser/SyntaxChecker.h index e05facd..ce3ab61 100644 --- a/JavaScriptCore/parser/SyntaxChecker.h +++ b/JavaScriptCore/parser/SyntaxChecker.h @@ -70,6 +70,7 @@ public: typedef int BinaryOperand; static const bool CreatesAST = false; + static const bool NeedsFreeVariableInfo = false; int createSourceElements() { return 1; } int makeFunctionCallNode(int, int, int, int, int) { return 1; } diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 4a81913..93b91bb 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -43,6 +43,7 @@ #include <stdlib.h> #include <wtf/FastMalloc.h> #include <wtf/HashCountedSet.h> +#include <wtf/WTFThreadData.h> #include <wtf/UnusedParam.h> #include <wtf/VMTags.h> @@ -298,6 +299,7 @@ void Heap::recordExtraCost(size_t cost) void* Heap::allocate(size_t s) { + ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); typedef HeapConstants::Block Block; typedef HeapConstants::Cell Cell; @@ -1189,6 +1191,7 @@ bool Heap::isBusy() void Heap::reset() { + ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); JAVASCRIPTCORE_GC_BEGIN(); markRoots(); @@ -1211,6 +1214,7 @@ void Heap::reset() void Heap::collectAllGarbage() { + ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); JAVASCRIPTCORE_GC_BEGIN(); // If the last iteration through the heap deallocated blocks, we need diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp index 249f427..4983f29 100644 --- a/JavaScriptCore/runtime/DatePrototype.cpp +++ b/JavaScriptCore/runtime/DatePrototype.cpp @@ -301,19 +301,25 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms // hours if (maxArgs >= 4 && idx < numArgs) { t->hour = 0; - milliseconds += exec->argument(idx++).toInt32(exec, ok) * msPerHour; + double hours = exec->argument(idx++).toIntegerPreserveNaN(exec); + ok = isfinite(hours); + milliseconds += hours * msPerHour; } // minutes if (maxArgs >= 3 && idx < numArgs && ok) { t->minute = 0; - milliseconds += exec->argument(idx++).toInt32(exec, ok) * msPerMinute; + double minutes = exec->argument(idx++).toIntegerPreserveNaN(exec); + ok = isfinite(minutes); + milliseconds += minutes * msPerMinute; } // seconds if (maxArgs >= 2 && idx < numArgs && ok) { t->second = 0; - milliseconds += exec->argument(idx++).toInt32(exec, ok) * msPerSecond; + double seconds = exec->argument(idx++).toIntegerPreserveNaN(exec); + ok = isfinite(seconds); + milliseconds += seconds * msPerSecond; } if (!ok) @@ -321,7 +327,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms // milliseconds if (idx < numArgs) { - double millis = exec->argument(idx).toNumber(exec); + double millis = exec->argument(idx).toIntegerPreserveNaN(exec); ok = isfinite(millis); milliseconds += millis; } else @@ -346,17 +352,23 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms numArgs = maxArgs; // years - if (maxArgs >= 3 && idx < numArgs) - t->year = exec->argument(idx++).toInt32(exec, ok) - 1900; - + if (maxArgs >= 3 && idx < numArgs) { + double years = exec->argument(idx++).toIntegerPreserveNaN(exec); + ok = isfinite(years); + t->year = toInt32(years - 1900); + } // months - if (maxArgs >= 2 && idx < numArgs && ok) - t->month = exec->argument(idx++).toInt32(exec, ok); - + if (maxArgs >= 2 && idx < numArgs && ok) { + double months = exec->argument(idx++).toIntegerPreserveNaN(exec); + ok = isfinite(months); + t->month = toInt32(months); + } // days - if (idx < numArgs && ok) { + if (idx < numArgs && ok) { + double days = exec->argument(idx++).toIntegerPreserveNaN(exec); + ok = isfinite(days); t->monthDay = 0; - *ms += exec->argument(idx).toInt32(exec, ok) * msPerDay; + *ms += days * msPerDay; } return ok; @@ -1026,15 +1038,14 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec) gregorianDateTime.copyFrom(*other); } - bool ok = true; - int32_t year = exec->argument(0).toInt32(exec, ok); - if (!ok) { + double year = exec->argument(0).toIntegerPreserveNaN(exec); + if (!isfinite(year)) { JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return JSValue::encode(result); } - gregorianDateTime.year = (year > 99 || year < 0) ? year - 1900 : year; + gregorianDateTime.year = toInt32((year > 99 || year < 0) ? year - 1900 : year); JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, false)); thisDateObj->setInternalValue(result); return JSValue::encode(result); diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp index 41b5f1f..e14955c 100644 --- a/JavaScriptCore/runtime/Executable.cpp +++ b/JavaScriptCore/runtime/Executable.cpp @@ -96,12 +96,12 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception); + RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); if (!evalNode) { ASSERT(exception); return exception; } - recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine()); + recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine()); ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); @@ -131,7 +131,7 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec) JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception); + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); if (programNode) return 0; ASSERT(exception); @@ -145,12 +145,12 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception); + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); if (!programNode) { ASSERT(exception); return exception; } - recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine()); + recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine()); ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); @@ -178,7 +178,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain { JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception); + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception); if (!body) { ASSERT(exception); return exception; @@ -186,7 +186,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain if (m_forceUsesArguments) body->setUsesArguments(); body->finishParsing(m_parameters, m_name); - recordParse(body->features(), body->lineNo(), body->lastLine()); + recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine()); ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); @@ -219,7 +219,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope { JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception); + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception); if (!body) { ASSERT(exception); return exception; @@ -227,7 +227,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope if (m_forceUsesArguments) body->setUsesArguments(); body->finishParsing(m_parameters, m_name); - recordParse(body->features(), body->lineNo(), body->lastLine()); + recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine()); ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); @@ -267,7 +267,7 @@ void FunctionExecutable::markAggregate(MarkStack& markStack) PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { JSObject* exception = 0; - RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, &exception); + RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, m_parameters.get(), &exception); if (!newFunctionBody) return PassOwnPtr<ExceptionInfo>(); if (m_forceUsesArguments) @@ -301,7 +301,7 @@ PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { JSObject* exception = 0; - RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, &exception); + RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, 0, &exception); if (!newEvalBody) return PassOwnPtr<ExceptionInfo>(); @@ -341,7 +341,7 @@ void FunctionExecutable::recompile(ExecState*) PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) { JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, exception); + RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, 0, exception); if (!program) { ASSERT(*exception); return 0; diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h index 10dfb34..c168ac8 100644 --- a/JavaScriptCore/runtime/Executable.h +++ b/JavaScriptCore/runtime/Executable.h @@ -172,20 +172,22 @@ namespace JSC { bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return m_features & ArgumentsFeature; } - bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } + bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); } virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0; protected: - void recordParse(CodeFeatures features, int firstLine, int lastLine) + void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine) { m_features = features; + m_hasCapturedVariables = hasCapturedVariables; m_firstLine = firstLine; m_lastLine = lastLine; } SourceCode m_source; CodeFeatures m_features; + bool m_hasCapturedVariables; int m_firstLine; int m_lastLine; }; diff --git a/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index 06d4210..45329ca 100644 --- a/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -29,9 +29,12 @@ #include "config.h" #include "GCActivityCallback.h" +#include "APIShims.h" #include "Collector.h" +#include "JSGlobalData.h" #include "JSLock.h" #include <wtf/RetainPtr.h> +#include <wtf/WTFThreadData.h> #include <CoreFoundation/CoreFoundation.h> #if !PLATFORM(CF) @@ -52,8 +55,7 @@ const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10; void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef, void *info) { Heap* heap = static_cast<Heap*>(info); - JSLock lock(heap->globalData()); - + APIEntryShim shim(heap->globalData()); heap->collectAllGarbage(); } diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp index 55aa327..340cb75 100644 --- a/JavaScriptCore/runtime/JSArray.cpp +++ b/JavaScriptCore/runtime/JSArray.cpp @@ -1060,10 +1060,11 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, if (storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max())) return; - if (!storage->m_length) - return; - unsigned usedVectorLength = min(storage->m_length, m_vectorLength); + unsigned nodeCount = usedVectorLength + (storage->m_sparseValueMap ? storage->m_sparseValueMap->size() : 0); + + if (!nodeCount) + return; AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items tree.abstractor().m_exec = exec; @@ -1071,7 +1072,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, tree.abstractor().m_compareCallType = callType; tree.abstractor().m_compareCallData = &callData; tree.abstractor().m_globalThisValue = exec->globalThisValue(); - tree.abstractor().m_nodes.resize(usedVectorLength + (storage->m_sparseValueMap ? storage->m_sparseValueMap->size() : 0)); + tree.abstractor().m_nodes.grow(nodeCount); if (callType == CallTypeJS) tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, asFunction(compareFunction), 2, exec->exceptionSlot())); diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp index 6db6954..2a23a79 100644 --- a/JavaScriptCore/runtime/JSValue.cpp +++ b/JavaScriptCore/runtime/JSValue.cpp @@ -135,36 +135,49 @@ char* JSValue::description() } #endif -int32_t toInt32SlowCase(double d, bool& ok) +// This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec. +// Note that this operation is identical to ToUInt32 other than to interpretation +// of the resulting bit-pattern (as such this metod is also called to implement +// ToUInt32). +// +// The operation can be descibed as round towards zero, then select the 32 least +// bits of the resulting value in 2s-complement representation. +int32_t toInt32(double number) { - if (isnan(d) || isinf(d)) { - ok = false; + int64_t bits = WTF::bitwise_cast<int64_t>(number); + int32_t exp = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff; + + // If exponent < 0 there will be no bits to the left of the decimal point + // after rounding; if the exponent is > 83 then no bits of precision can be + // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits + // of fractional precision). + // Note this case handles 0, -0, and all infinte, NaN, & denormal value. + if (exp < 0 || exp > 83) return 0; - } - - ok = true; - - double d32 = fmod(trunc(d), D32); - if (d32 >= D32 / 2) - d32 -= D32; - else if (d32 < -D32 / 2) - d32 += D32; - return static_cast<int32_t>(d32); -} -uint32_t toUInt32SlowCase(double d, bool& ok) -{ - if (isnan(d) || isinf(d)) { - ok = false; - return 0; + // Select the appropriate 32-bits from the floating point mantissa. If the + // exponent is 52 then the bits we need to select are already aligned to the + // lowest bits of the 64-bit integer representation of tghe number, no need + // to shift. If the exponent is greater than 52 we need to shift the value + // left by (exp - 52), if the value is less than 52 we need to shift right + // accordingly. + int32_t result = (exp > 52) + ? static_cast<int32_t>(bits << (exp - 52)) + : static_cast<int32_t>(bits >> (52 - exp)); + + // IEEE-754 double precision values are stored omitting an implicit 1 before + // the decimal point; we need to reinsert this now. We may also the shifted + // invalid bits into the result that are not a part of the mantissa (the sign + // and exponent bits from the floatingpoint representation); mask these out. + if (exp < 32) { + int32_t missingOne = 1 << exp; + result &= missingOne - 1; + result += missingOne; } - ok = true; - - double d32 = fmod(trunc(d), D32); - if (d32 < 0) - d32 += D32; - return static_cast<uint32_t>(d32); + // If the input value was negative (we could test either 'number' or 'bits', + // but testing 'bits' is likely faster) invert the result appropriately. + return bits < 0 ? -result : result; } NEVER_INLINE double nonInlineNaN() diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index 4a6744d..b5834c1 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -56,8 +56,17 @@ namespace JSC { #endif double nonInlineNaN(); - int32_t toInt32SlowCase(double, bool& ok); - uint32_t toUInt32SlowCase(double, bool& ok); + + // This implements ToInt32, defined in ECMA-262 9.5. + int32_t toInt32(double); + + // This implements ToUInt32, defined in ECMA-262 9.6. + inline uint32_t toUInt32(double number) + { + // As commented in the spec, the operation of ToInt32 and ToUint32 only differ + // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6. + return toInt32(number); + } class JSValue { friend class JSImmediate; @@ -163,9 +172,7 @@ namespace JSC { double toInteger(ExecState*) const; double toIntegerPreserveNaN(ExecState*) const; int32_t toInt32(ExecState*) const; - int32_t toInt32(ExecState*, bool& ok) const; uint32_t toUInt32(ExecState*) const; - uint32_t toUInt32(ExecState*, bool& ok) const; #if ENABLE(JSC_ZOMBIES) bool isZombie() const; @@ -367,24 +374,6 @@ namespace JSC { inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); } inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; } - inline int32_t toInt32(double val) - { - if (!(val >= -2147483648.0 && val < 2147483648.0)) { - bool ignored; - return toInt32SlowCase(val, ignored); - } - return static_cast<int32_t>(val); - } - - inline uint32_t toUInt32(double val) - { - if (!(val >= 0.0 && val < 4294967296.0)) { - bool ignored; - return toUInt32SlowCase(val, ignored); - } - return static_cast<uint32_t>(val); - } - // FIXME: We should deprecate this and just use JSValue::asCell() instead. JSCell* asCell(JSValue); @@ -397,62 +386,13 @@ namespace JSC { { if (isInt32()) return asInt32(); - - double val = toNumber(exec); - - if (val >= -2147483648.0 && val < 2147483648.0) - return static_cast<int32_t>(val); - - bool ignored; - return toInt32SlowCase(val, ignored); + return JSC::toInt32(toNumber(exec)); } inline uint32_t JSValue::toUInt32(ExecState* exec) const { - if (isUInt32()) - return asUInt32(); - - double val = toNumber(exec); - - if (val >= 0.0 && val < 4294967296.0) - return static_cast<uint32_t>(val); - - bool ignored; - return toUInt32SlowCase(val, ignored); - } - - inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const - { - if (isInt32()) { - ok = true; - return asInt32(); - } - - double val = toNumber(exec); - - if (val >= -2147483648.0 && val < 2147483648.0) { - ok = true; - return static_cast<int32_t>(val); - } - - return toInt32SlowCase(val, ok); - } - - inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const - { - if (isUInt32()) { - ok = true; - return asInt32(); - } - - double val = toNumber(exec); - - if (val >= 0.0 && val < 4294967296.0) { - ok = true; - return static_cast<uint32_t>(val); - } - - return toUInt32SlowCase(val, ok); + // See comment on JSC::toUInt32, above. + return toInt32(exec); } #if USE(JSVALUE32_64) diff --git a/JavaScriptCore/runtime/MemoryStatistics.cpp b/JavaScriptCore/runtime/MemoryStatistics.cpp new file mode 100644 index 0000000..7fafa9c --- /dev/null +++ b/JavaScriptCore/runtime/MemoryStatistics.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MemoryStatistics.h" + +#include "ExecutableAllocator.h" +#include "JSGlobalData.h" +#include "RegisterFile.h" + +namespace JSC { + +Heap::Statistics heapStatistics(JSGlobalData* commonGlobalData) +{ + return commonGlobalData->heap.statistics(); +} + +GlobalMemoryStatistics globalMemoryStatistics() +{ + GlobalMemoryStatistics stats; + + stats.stackBytes = RegisterFile::committedByteCount(); +#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED) + stats.JITBytes = ExecutableAllocator::committedByteCount(); +#else + stats.JITBytes = 0; +#endif + return stats; +} + +} + + diff --git a/JavaScriptCore/runtime/MemoryStatistics.h b/JavaScriptCore/runtime/MemoryStatistics.h new file mode 100644 index 0000000..1b92eb9 --- /dev/null +++ b/JavaScriptCore/runtime/MemoryStatistics.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MemoryStatistics_h +#define MemoryStatistics_h + +#include "Collector.h" + +class JSGlobalData; + +namespace JSC { + +struct GlobalMemoryStatistics { + size_t stackBytes; + size_t JITBytes; +}; + +Heap::Statistics heapStatistics(JSGlobalData* commonGlobalData); +GlobalMemoryStatistics globalMemoryStatistics(); + +} + +#endif // MemoryStatistics_h + diff --git a/JavaScriptCore/runtime/RegExpObject.h b/JavaScriptCore/runtime/RegExpObject.h index f997374..19de929 100644 --- a/JavaScriptCore/runtime/RegExpObject.h +++ b/JavaScriptCore/runtime/RegExpObject.h @@ -45,7 +45,7 @@ namespace JSC { virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual const ClassInfo* classInfo() const { return &info; } - static const ClassInfo info; + static JS_EXPORTDATA const ClassInfo info; static PassRefPtr<Structure> createStructure(JSValue prototype) { diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index 0f240ff..1e537b9 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -384,7 +384,8 @@ size_t fastMallocSize(const void* p) { #if OS(DARWIN) return malloc_size(p); -#elif COMPILER(MSVC) +#elif COMPILER(MSVC) && !PLATFORM(BREWMP) + // Brew MP uses its own memory allocator, so _msize does not work on the Brew MP simulator. return _msize(const_cast<void*>(p)); #else return 1; diff --git a/JavaScriptCore/wtf/OwnPtrCommon.h b/JavaScriptCore/wtf/OwnPtrCommon.h index 37c135d..19256ea 100644 --- a/JavaScriptCore/wtf/OwnPtrCommon.h +++ b/JavaScriptCore/wtf/OwnPtrCommon.h @@ -46,6 +46,8 @@ typedef struct _IFileMgr IFileMgr; typedef struct _IFile IFile; typedef struct IBitmap IBitmap; typedef struct ISSL ISSL; +typedef struct IMemGroup IMemGroup; +typedef struct IMemSpace IMemSpace; #endif namespace WTF { @@ -73,6 +75,8 @@ namespace WTF { void deleteOwnedPtr(IBitmap*); void deleteOwnedPtr(ISSL*); void deleteOwnedPtr(ISocket*); + void deleteOwnedPtr(IMemGroup*); + void deleteOwnedPtr(IMemSpace*); #endif } // namespace WTF diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index e77fe98..30bc795 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -1057,6 +1057,10 @@ #define ENABLE_PAN_SCROLLING 1 #endif +#if !defined(ENABLE_SMOOTH_SCROLLING) +#define ENABLE_SMOOTH_SCROLLING 0 +#endif + /* Use the QXmlStreamReader implementation for XMLDocumentParser */ /* Use the QXmlQuery implementation for XSLTProcessor */ #if PLATFORM(QT) @@ -1123,7 +1127,7 @@ #define ENABLE_JSC_ZOMBIES 0 /* FIXME: Eventually we should enable this for all platforms and get rid of the define. */ -#if PLATFORM(MAC) || PLATFORM(WIN) +#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(QT) #define WTF_USE_PLATFORM_STRATEGIES 1 #endif diff --git a/JavaScriptCore/wtf/PlatformRefPtr.h b/JavaScriptCore/wtf/PlatformRefPtr.h index 2d05ac9..8ac16cb 100644 --- a/JavaScriptCore/wtf/PlatformRefPtr.h +++ b/JavaScriptCore/wtf/PlatformRefPtr.h @@ -24,6 +24,7 @@ #define PlatformRefPtr_h #include "AlwaysInline.h" +#include "RefPtr.h" #include <algorithm> namespace WTF { @@ -73,6 +74,10 @@ public: derefPlatformPtr(ptr); } + // Hash table deleted values, which are only constructed and never copied or destroyed. + PlatformRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } + bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } + T* get() const { return m_ptr; } T& operator*() const { return *m_ptr; } ALWAYS_INLINE T* operator->() const { return m_ptr; } diff --git a/JavaScriptCore/wtf/TypeTraits.cpp b/JavaScriptCore/wtf/TypeTraits.cpp index 9e51ad0..a55019b 100644 --- a/JavaScriptCore/wtf/TypeTraits.cpp +++ b/JavaScriptCore/wtf/TypeTraits.cpp @@ -47,6 +47,11 @@ COMPILE_ASSERT(!IsInteger<volatile char*>::value, WTF_IsInteger_volatile_char_po COMPILE_ASSERT(!IsInteger<double>::value, WTF_IsInteger_double_false); COMPILE_ASSERT(!IsInteger<float>::value, WTF_IsInteger_float_false); +COMPILE_ASSERT(IsFloatingPoint<float>::value, WTF_IsFloatingPoint_float_true); +COMPILE_ASSERT(IsFloatingPoint<double>::value, WTF_IsFloatingPoint_double_true); +COMPILE_ASSERT(IsFloatingPoint<long double>::value, WTF_IsFloatingPoint_long_double_true); +COMPILE_ASSERT(!IsFloatingPoint<int>::value, WTF_IsFloatingPoint_int_false); + COMPILE_ASSERT(IsPod<bool>::value, WTF_IsPod_bool_true); COMPILE_ASSERT(IsPod<char>::value, WTF_IsPod_char_true); COMPILE_ASSERT(IsPod<signed char>::value, WTF_IsPod_signed_char_true); diff --git a/JavaScriptCore/wtf/TypeTraits.h b/JavaScriptCore/wtf/TypeTraits.h index 62dbc49..cf9b4af 100644 --- a/JavaScriptCore/wtf/TypeTraits.h +++ b/JavaScriptCore/wtf/TypeTraits.h @@ -62,12 +62,16 @@ namespace WTF { template<> struct IsInteger<wchar_t> { static const bool value = true; }; #endif + template<typename T> struct IsFloatingPoint { static const bool value = false; }; + template<> struct IsFloatingPoint<float> { static const bool value = true; }; + template<> struct IsFloatingPoint<double> { static const bool value = true; }; + template<> struct IsFloatingPoint<long double> { static const bool value = true; }; + + template<typename T> struct IsArithmetic { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; }; + // IsPod is misnamed as it doesn't cover all plain old data (pod) types. // Specifically, it doesn't allow for enums or for structs. - template <typename T> struct IsPod { static const bool value = IsInteger<T>::value; }; - template <> struct IsPod<float> { static const bool value = true; }; - template <> struct IsPod<double> { static const bool value = true; }; - template <> struct IsPod<long double> { static const bool value = true; }; + template <typename T> struct IsPod { static const bool value = IsArithmetic<T>::value; }; template <typename P> struct IsPod<P*> { static const bool value = true; }; template<typename T> class IsConvertibleToInteger { diff --git a/JavaScriptCore/wtf/WTFThreadData.h b/JavaScriptCore/wtf/WTFThreadData.h index 20ffaca..7f91e1a 100644 --- a/JavaScriptCore/wtf/WTFThreadData.h +++ b/JavaScriptCore/wtf/WTFThreadData.h @@ -59,7 +59,14 @@ public: template<typename U, typename V> std::pair<HashSet<StringImpl*>::iterator, bool> add(U value); - void remove(StringImpl* r) { m_table.remove(r); } + bool remove(StringImpl* r) + { + HashSet<StringImpl*>::iterator iter = m_table.find(r); + if (iter == m_table.end()) + return false; + m_table.remove(iter); + return true; + } LiteralIdentifierTable& literalTable() { return m_literalTable; } diff --git a/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp b/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp index 28046bd..ce10fc3 100644 --- a/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp +++ b/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp @@ -28,6 +28,8 @@ #include <AEEBitmap.h> #include <AEEFile.h> +#include <AEEIMemGroup.h> +#include <AEEIMemSpace.h> #include <AEENet.h> #include <AEESSL.h> #include <AEEStdLib.h> @@ -58,6 +60,18 @@ void deleteOwnedPtr(ISSL* ptr) ISSL_Release(ptr); } +void deleteOwnedPtr(IMemGroup* ptr) +{ + if (ptr) + IMemGroup_Release(ptr); +} + +void deleteOwnedPtr(IMemSpace* ptr) +{ + if (ptr) + IMemSpace_Release(ptr); +} + void deleteOwnedPtr(ISocket* ptr) { if (ptr) diff --git a/JavaScriptCore/wtf/gobject/GTypedefs.h b/JavaScriptCore/wtf/gobject/GTypedefs.h index e79ba33..b1600c2 100644 --- a/JavaScriptCore/wtf/gobject/GTypedefs.h +++ b/JavaScriptCore/wtf/gobject/GTypedefs.h @@ -45,6 +45,7 @@ typedef struct _GdkCursor GdkCursor; typedef struct _GdkDragContext GdkDragContext; typedef struct _GdkDrawable GdkDrawable; typedef struct _GdkEventConfigure GdkEventConfigure; +typedef struct _GdkEventExpose GdkEventExpose; typedef struct _GdkPixbuf GdkPixbuf; typedef struct _GError GError; typedef struct _GFile GFile; @@ -79,6 +80,7 @@ typedef struct _GtkStyle GtkStyle; typedef struct _GtkTargetList GtkTargetList; typedef struct _GtkThemeParts GtkThemeParts; typedef struct _GtkWidget GtkWidget; +typedef struct _GtkWindow GtkWindow; #ifdef GTK_API_VERSION_2 typedef struct _GdkRectangle GdkRectangle; diff --git a/JavaScriptCore/wtf/text/StringImpl.cpp b/JavaScriptCore/wtf/text/StringImpl.cpp index a667525..7822c00 100644 --- a/JavaScriptCore/wtf/text/StringImpl.cpp +++ b/JavaScriptCore/wtf/text/StringImpl.cpp @@ -48,8 +48,10 @@ StringImpl::~StringImpl() if (isAtomic()) AtomicString::remove(this); #if USE(JSC) - if (isIdentifier()) - wtfThreadData().currentIdentifierTable()->remove(this); + if (isIdentifier()) { + if (!wtfThreadData().currentIdentifierTable()->remove(this)) + CRASH(); + } #endif BufferOwnership ownership = bufferOwnership(); diff --git a/JavaScriptCore/wtf/text/WTFString.h b/JavaScriptCore/wtf/text/WTFString.h index fafef12..8a4a6c7 100644 --- a/JavaScriptCore/wtf/text/WTFString.h +++ b/JavaScriptCore/wtf/text/WTFString.h @@ -53,6 +53,7 @@ class BString; namespace WTF { class CString; +struct StringHash; // Declarations of string operations @@ -72,6 +73,8 @@ intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trai double charactersToDouble(const UChar*, size_t, bool* ok = 0); float charactersToFloat(const UChar*, size_t, bool* ok = 0); +template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters(const UChar*, size_t); + class String { public: // Construct a null string, distinguishable from an empty string. @@ -220,6 +223,7 @@ public: String simplifyWhiteSpace() const; String removeCharacters(CharacterMatchFunctionPtr) const; + template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters() const; // Return the string with case folded for case insensitive comparison. String foldCase() const; @@ -423,7 +427,19 @@ inline void appendNumber(Vector<UChar>& vector, unsigned char number) } } -struct StringHash; +template<bool isSpecialCharacter(UChar)> inline bool isAllSpecialCharacters(const UChar* characters, size_t length) +{ + for (size_t i = 0; i < length; ++i) { + if (!isSpecialCharacter(characters[i])) + return false; + } + return true; +} + +template<bool isSpecialCharacter(UChar)> inline bool String::isAllSpecialCharacters() const +{ + return WTF::isAllSpecialCharacters<isSpecialCharacter>(characters(), length()); +} // StringHash is the default hash for String template<typename T> struct DefaultHash; @@ -440,17 +456,26 @@ template <> struct VectorTraits<String> : SimpleClassVectorTraits using WTF::CString; using WTF::String; - -using WTF::isSpaceOrNewline; -using WTF::find; -using WTF::reverseFind; using WTF::append; using WTF::appendNumber; -using WTF::equal; -using WTF::equalIgnoringCase; using WTF::charactersAreAllASCII; +using WTF::charactersToIntStrict; +using WTF::charactersToUIntStrict; +using WTF::charactersToInt64Strict; +using WTF::charactersToUInt64Strict; +using WTF::charactersToIntPtrStrict; using WTF::charactersToInt; -using WTF::charactersToFloat; +using WTF::charactersToUInt; +using WTF::charactersToInt64; +using WTF::charactersToUInt64; +using WTF::charactersToIntPtr; using WTF::charactersToDouble; +using WTF::charactersToFloat; +using WTF::equal; +using WTF::equalIgnoringCase; +using WTF::find; +using WTF::isAllSpecialCharacters; +using WTF::isSpaceOrNewline; +using WTF::reverseFind; #endif diff --git a/JavaScriptCore/wtf/unicode/Unicode.h b/JavaScriptCore/wtf/unicode/Unicode.h index d59439d..c755c6c 100644 --- a/JavaScriptCore/wtf/unicode/Unicode.h +++ b/JavaScriptCore/wtf/unicode/Unicode.h @@ -32,7 +32,7 @@ #elif USE(GLIB_UNICODE) #include <wtf/unicode/glib/UnicodeGLib.h> #elif USE(WINCE_UNICODE) -#include <wtf/unicode/wince/UnicodeWince.h> +#include <wtf/unicode/wince/UnicodeWinCE.h> #else #error "Unknown Unicode implementation" #endif diff --git a/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h b/JavaScriptCore/wtf/unicode/UnicodeMacrosFromICU.h index 1963576..f865ef1 100644 --- a/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h +++ b/JavaScriptCore/wtf/unicode/UnicodeMacrosFromICU.h @@ -36,6 +36,7 @@ #define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0) #define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00) +#define U16_LENGTH(c) ((uint32_t)(c) <= 0xffff ? 1 : 2) #define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800) #define U16_IS_SINGLE(c) !U_IS_SURROGATE(c) diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index badab66..c9e2e1c 100644 --- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -23,6 +23,8 @@ #ifndef WTF_UNICODE_QT4_H #define WTF_UNICODE_QT4_H +#include "UnicodeMacrosFromICU.h" + #include <QChar> #include <QString> @@ -63,49 +65,6 @@ typedef uint16_t UChar; #endif typedef uint32_t UChar32; -// some defines from ICU -// FIXME: This should use UnicodeMacrosFromICU.h instead! - -#define U_IS_BMP(c) ((UChar32)(c)<=0xffff) -#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) -#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) -#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) -#define U16_GET_SUPPLEMENTARY(lead, trail) \ - (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET) - -#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0) -#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00) -#define U16_LENGTH(c) ((uint32_t)(c) <= 0xffff ? 1 : 2) - -#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800) -#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c) -#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c) -#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) - -#define U16_NEXT(s, i, length, c) { \ - (c)=(s)[(i)++]; \ - if(U16_IS_LEAD(c)) { \ - uint16_t __c2; \ - if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \ - ++(i); \ - (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ - } \ - } \ -} - -#define U16_PREV(s, start, i, c) { \ - (c)=(s)[--(i)]; \ - if(U16_IS_TRAIL(c)) { \ - uint16_t __c2; \ - if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ - --(i); \ - (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ - } \ - } \ -} - -#define U_MASK(x) ((uint32_t)1<<(x)) - namespace WTF { namespace Unicode { diff --git a/JavaScriptCore/wtf/unicode/wince/UnicodeWince.cpp b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp index 42f0ff8..b52b05c 100644 --- a/JavaScriptCore/wtf/unicode/wince/UnicodeWince.cpp +++ b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp @@ -20,7 +20,7 @@ */ #include "config.h" -#include "UnicodeWince.h" +#include "UnicodeWinCE.h" #include <wchar.h> diff --git a/JavaScriptCore/wtf/unicode/wince/UnicodeWince.h b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h index 3866568..8cc9580 100644 --- a/JavaScriptCore/wtf/unicode/wince/UnicodeWince.h +++ b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h @@ -21,55 +21,15 @@ * */ -#ifndef UNICODE_WINCE_H -#define UNICODE_WINCE_H +#ifndef WTF_UnicodeWinCE_h +#define WTF_UnicodeWinCE_h + +#include "UnicodeMacrosFromICU.h" #include "ce_unicode.h" #define TO_MASK(x) (1 << (x)) -// some defines from ICU needed one or two places -// FIXME: This should use UnicodeMacrosFromICU.h instead! - -#define U_IS_BMP(c) ((UChar32)(c)<=0xffff) -#define U16_IS_LEAD(c) (((c) & 0xfffffc00) == 0xd800) -#define U16_IS_TRAIL(c) (((c) & 0xfffffc00) == 0xdc00) -#define U16_SURROGATE_OFFSET ((0xd800 << 10UL) + 0xdc00 - 0x10000) -#define U16_GET_SUPPLEMENTARY(lead, trail) \ - (((UChar32)(lead) << 10UL) + (UChar32)(trail) - U16_SURROGATE_OFFSET) - -#define U16_LEAD(supplementary) (UChar)(((supplementary) >> 10) + 0xd7c0) -#define U16_TRAIL(supplementary) (UChar)(((supplementary) & 0x3ff) | 0xdc00) -#define U16_LENGTH(c) ((uint32_t)(c) <= 0xffff ? 1 : 2) - -#define U_IS_SURROGATE(c) (((c) & 0xfffff800) == 0xd800) -#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c) -#define U16_IS_SURROGATE_LEAD(c) (((c) & 0x400) == 0) - -#define U16_NEXT(s, i, length, c) { \ - (c)=(s)[(i)++]; \ - if (U16_IS_LEAD(c)) { \ - uint16_t __c2; \ - if ((i) < (length) && U16_IS_TRAIL(__c2 = (s)[(i)])) { \ - ++(i); \ - (c) = U16_GET_SUPPLEMENTARY((c), __c2); \ - } \ - } \ -} - -#define U16_PREV(s, start, i, c) { \ - (c)=(s)[--(i)]; \ - if (U16_IS_TRAIL(c)) { \ - uint16_t __c2; \ - if ((i) > (start) && U16_IS_LEAD(__c2 = (s)[(i) - 1])) { \ - --(i); \ - (c) = U16_GET_SUPPLEMENTARY(__c2, (c)); \ - } \ - } \ -} - -#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c) - namespace WTF { namespace Unicode { @@ -216,5 +176,4 @@ namespace WTF { } // namespace WTF -#endif -// vim: ts=2 sw=2 et +#endif // WTF_UnicodeWinCE_h diff --git a/JavaScriptCore/wtf/wince/FastMallocWince.h b/JavaScriptCore/wtf/wince/FastMallocWinCE.h index 37174f0..d91a5f2 100644 --- a/JavaScriptCore/wtf/wince/FastMallocWince.h +++ b/JavaScriptCore/wtf/wince/FastMallocWinCE.h @@ -19,8 +19,8 @@ * */ -#ifndef FastMallocWince_h -#define FastMallocWince_h +#ifndef WTF_FastMallocWinCE_h +#define WTF_FastMallocWinCE_h #include <new.h> @@ -172,5 +172,4 @@ namespace WTF { #endif -#endif // FastMallocWince_h - +#endif // WTF_FastMallocWinCE_h diff --git a/JavaScriptCore/wtf/wtf.pri b/JavaScriptCore/wtf/wtf.pri new file mode 100644 index 0000000..84ac20e --- /dev/null +++ b/JavaScriptCore/wtf/wtf.pri @@ -0,0 +1,35 @@ +# wtf - qmake build info + +SOURCES += \ + wtf/Assertions.cpp \ + wtf/ByteArray.cpp \ + wtf/CurrentTime.cpp \ + wtf/DateMath.cpp \ + wtf/dtoa.cpp \ + wtf/FastMalloc.cpp \ + wtf/HashTable.cpp \ + wtf/MD5.cpp \ + wtf/MainThread.cpp \ + wtf/qt/MainThreadQt.cpp \ + wtf/qt/StringQt.cpp \ + wtf/qt/ThreadingQt.cpp \ + wtf/PageAllocation.cpp \ + wtf/RandomNumber.cpp \ + wtf/RefCountedLeakCounter.cpp \ + wtf/ThreadingNone.cpp \ + wtf/Threading.cpp \ + wtf/TypeTraits.cpp \ + wtf/WTFThreadData.cpp \ + wtf/text/AtomicString.cpp \ + wtf/text/CString.cpp \ + wtf/text/StringImpl.cpp \ + wtf/text/StringStatics.cpp \ + wtf/text/WTFString.cpp \ + wtf/unicode/CollatorDefault.cpp \ + wtf/unicode/icu/CollatorICU.cpp \ + wtf/unicode/UTF8.cpp + +!contains(DEFINES, USE_SYSTEM_MALLOC) { + SOURCES += wtf/TCSystemAlloc.cpp +} + diff --git a/JavaScriptCore/yarr/RegexCompiler.cpp b/JavaScriptCore/yarr/RegexCompiler.cpp index fa87186..9f9e028 100644 --- a/JavaScriptCore/yarr/RegexCompiler.cpp +++ b/JavaScriptCore/yarr/RegexCompiler.cpp @@ -240,6 +240,7 @@ public: RegexPatternConstructor(RegexPattern& pattern) : m_pattern(pattern) , m_characterClassConstructor(pattern.m_ignoreCase) + , m_invertParentheticalAssertion(false) { } @@ -255,6 +256,11 @@ public: void assertionBOL() { + if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) { + m_alternative->m_startsWithBOL = true; + m_alternative->m_containsBOL = true; + m_pattern.m_containsBOL = true; + } m_alternative->m_terms.append(PatternTerm::BOL()); } void assertionEOL() @@ -358,15 +364,36 @@ public: m_pattern.m_disjunctions.append(parenthesesDisjunction); m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, invert)); m_alternative = parenthesesDisjunction->addNewAlternative(); + m_invertParentheticalAssertion = invert; } void atomParenthesesEnd() { ASSERT(m_alternative->m_parent); ASSERT(m_alternative->m_parent->m_parent); + + PatternDisjunction* parenthesisDisjunction = m_alternative->m_parent; m_alternative = m_alternative->m_parent->m_parent; + + PatternTerm& lastTerm = m_alternative->lastTerm(); + + unsigned numParenAlternatives = parenthesisDisjunction->m_alternatives.size(); + unsigned numBOLAnchoredAlts = 0; + // Bubble up BOL flags + for (unsigned i = 0; i < numParenAlternatives; i++) { + if (parenthesisDisjunction->m_alternatives[i]->m_startsWithBOL) + numBOLAnchoredAlts++; + } + + if (numBOLAnchoredAlts) { + m_alternative->m_containsBOL = true; + // If all the alternatives in parens start with BOL, then so does this one + if (numBOLAnchoredAlts == numParenAlternatives) + m_alternative->m_startsWithBOL = true; + } - m_alternative->lastTerm().parentheses.lastSubpatternId = m_pattern.m_numSubpatterns; + lastTerm.parentheses.lastSubpatternId = m_pattern.m_numSubpatterns; + m_invertParentheticalAssertion = false; } void atomBackReference(unsigned subpatternId) @@ -397,32 +424,39 @@ public: m_alternative->m_terms.append(PatternTerm(subpatternId)); } - PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction) + // deep copy the argument disjunction. If filterStartsWithBOL is true, + // skip alternatives with m_startsWithBOL set true. + PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction, bool filterStartsWithBOL = false) { - PatternDisjunction* newDisjunction = new PatternDisjunction(); - - newDisjunction->m_parent = disjunction->m_parent; + PatternDisjunction* newDisjunction = 0; for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) { PatternAlternative* alternative = disjunction->m_alternatives[alt]; - PatternAlternative* newAlternative = newDisjunction->addNewAlternative(); - for (unsigned i = 0; i < alternative->m_terms.size(); ++i) - newAlternative->m_terms.append(copyTerm(alternative->m_terms[i])); + if (!filterStartsWithBOL || !alternative->m_startsWithBOL) { + if (!newDisjunction) { + newDisjunction = new PatternDisjunction(); + newDisjunction->m_parent = disjunction->m_parent; + } + PatternAlternative* newAlternative = newDisjunction->addNewAlternative(); + for (unsigned i = 0; i < alternative->m_terms.size(); ++i) + newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], filterStartsWithBOL)); + } } - - m_pattern.m_disjunctions.append(newDisjunction); + + if (newDisjunction) + m_pattern.m_disjunctions.append(newDisjunction); return newDisjunction; } - - PatternTerm copyTerm(PatternTerm& term) + + PatternTerm copyTerm(PatternTerm& term, bool filterStartsWithBOL = false) { if ((term.type != PatternTerm::TypeParenthesesSubpattern) && (term.type != PatternTerm::TypeParentheticalAssertion)) return PatternTerm(term); - + PatternTerm termCopy = term; - termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction); + termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction, filterStartsWithBOL); return termCopy; } - + void quantifyAtom(unsigned min, unsigned max, bool greedy) { ASSERT(min <= max); @@ -589,11 +623,40 @@ public: setupDisjunctionOffsets(m_pattern.m_body, 0, 0); } + void optimizeBOL() + { + // Look for expressions containing beginning of line (^) anchoring and unroll them. + // e.g. /^a|^b|c/ becomes /^a|^b|c/ which is executed once followed by /c/ which loops + // This code relies on the parsing code tagging alternatives with m_containsBOL and + // m_startsWithBOL and rolling those up to containing alternatives. + // At this point, this is only valid for non-multiline expressions. + PatternDisjunction* disjunction = m_pattern.m_body; + + if (!m_pattern.m_containsBOL || m_pattern.m_multiline) + return; + + PatternDisjunction* loopDisjunction = copyDisjunction(disjunction, true); + + // Set alternatives in disjunction to "onceThrough" + for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) + disjunction->m_alternatives[alt]->setOnceThrough(); + + if (loopDisjunction) { + // Move alternatives from loopDisjunction to disjunction + for (unsigned alt = 0; alt < loopDisjunction->m_alternatives.size(); ++alt) + disjunction->m_alternatives.append(loopDisjunction->m_alternatives[alt]); + + loopDisjunction->m_alternatives.clear(); + } + } + + private: RegexPattern& m_pattern; PatternAlternative* m_alternative; CharacterClassConstructor m_characterClassConstructor; bool m_invertCharacterClass; + bool m_invertParentheticalAssertion; }; @@ -621,6 +684,8 @@ const char* compileRegex(const UString& patternString, RegexPattern& pattern) ASSERT(numSubpatterns == pattern.m_numSubpatterns); } + constructor.optimizeBOL(); + constructor.setupOffsets(); return 0; diff --git a/JavaScriptCore/yarr/RegexJIT.cpp b/JavaScriptCore/yarr/RegexJIT.cpp index 7818b52..8740130 100644 --- a/JavaScriptCore/yarr/RegexJIT.cpp +++ b/JavaScriptCore/yarr/RegexJIT.cpp @@ -1207,21 +1207,26 @@ class RegexGenerator : private MacroAssembler { TermGenerationState state(disjunction, 0); state.resetAlternative(); - // Plant a check to see if there is sufficient input available to run the first alternative. - // Jumping back to the label 'firstAlternative' will get to this check, jumping to - // 'firstAlternativeInputChecked' will jump directly to matching the alternative having - // skipped this check. - - Label firstAlternative(this); - // check availability for the next alternative int countCheckedForCurrentAlternative = 0; int countToCheckForFirstAlternative = 0; bool hasShorterAlternatives = false; + bool setRepeatAlternativeLabels = false; JumpList notEnoughInputForPreviousAlternative; + Label firstAlternative; + Label firstAlternativeInputChecked; + // The label 'firstAlternative' is used to plant a check to see if there is + // sufficient input available to run the first repeating alternative. + // The label 'firstAlternativeInputChecked' will jump directly to matching + // the first repeating alternative having skipped this check. + if (state.alternativeValid()) { PatternAlternative* alternative = state.alternative(); + if (!alternative->onceThrough()) { + firstAlternative = Label(this); + setRepeatAlternativeLabels = true; + } countToCheckForFirstAlternative = alternative->m_minimumSize; state.checkedTotal += countToCheckForFirstAlternative; if (countToCheckForFirstAlternative) @@ -1229,15 +1234,17 @@ class RegexGenerator : private MacroAssembler { countCheckedForCurrentAlternative = countToCheckForFirstAlternative; } - Label firstAlternativeInputChecked(this); + if (setRepeatAlternativeLabels) + firstAlternativeInputChecked = Label(this); while (state.alternativeValid()) { - // Track whether any alternatives are shorter than the first one. - hasShorterAlternatives = hasShorterAlternatives || (countCheckedForCurrentAlternative < countToCheckForFirstAlternative); - PatternAlternative* alternative = state.alternative(); optimizeAlternative(alternative); + // Track whether any alternatives are shorter than the first one. + if (!alternative->onceThrough()) + hasShorterAlternatives = hasShorterAlternatives || (countCheckedForCurrentAlternative < countToCheckForFirstAlternative); + for (state.resetTerm(); state.termValid(); state.nextTerm()) generateTerm(state); @@ -1264,6 +1271,17 @@ class RegexGenerator : private MacroAssembler { // if there are any more alternatives, plant the check for input before looping. if (state.alternativeValid()) { PatternAlternative* nextAlternative = state.alternative(); + bool setAlternativeLoopLabel = false; + if (!setRepeatAlternativeLabels && !nextAlternative->onceThrough()) { + // We have handled non-repeating alternatives, jump to next iteration + // and loop over repeating alternatives. + state.jumpToBacktrack(jump(), this); + + firstAlternative = Label(this); + setRepeatAlternativeLabels = true; + setAlternativeLoopLabel = true; + } + int countToCheckForNextAlternative = nextAlternative->m_minimumSize; if (countCheckedForCurrentAlternative > countToCheckForNextAlternative) { // CASE 1: current alternative was longer than the next one. @@ -1302,6 +1320,12 @@ class RegexGenerator : private MacroAssembler { state.linkAlternativeBacktracks(this); } + if (setAlternativeLoopLabel) { + firstAlternativeInputChecked = Label(this); + countToCheckForFirstAlternative = countToCheckForNextAlternative; + setAlternativeLoopLabel = true; + } + state.checkedTotal -= countCheckedForCurrentAlternative; countCheckedForCurrentAlternative = countToCheckForNextAlternative; state.checkedTotal += countCheckedForCurrentAlternative; @@ -1312,75 +1336,83 @@ class RegexGenerator : private MacroAssembler { state.checkedTotal -= countCheckedForCurrentAlternative; - // How much more input need there be to be able to retry from the first alternative? - // examples: - // /yarr_jit/ or /wrec|pcre/ - // In these examples we need check for one more input before looping. - // /yarr_jit|pcre/ - // In this case we need check for 5 more input to loop (+4 to allow for the first alterative - // being four longer than the last alternative checked, and another +1 to effectively move - // the start position along by one). - // /yarr|rules/ or /wrec|notsomuch/ - // In these examples, provided that there was sufficient input to have just been matching for - // the second alternative we can loop without checking for available input (since the second - // alternative is longer than the first). In the latter example we need to decrement index - // (by 4) so the start position is only progressed by 1 from the last iteration. - int incrementForNextIter = (countToCheckForFirstAlternative - countCheckedForCurrentAlternative) + 1; - - // First, deal with the cases where there was sufficient input to try the last alternative. - if (incrementForNextIter > 0) // We need to check for more input anyway, fall through to the checking below. - state.linkAlternativeBacktracks(this); - else if (m_pattern.m_body->m_hasFixedSize && !incrementForNextIter) // No need to update anything, link these backtracks straight to the to pof the loop! - state.linkAlternativeBacktracksTo(firstAlternativeInputChecked, this); - else { // no need to check the input, but we do have some bookkeeping to do first. + if (!setRepeatAlternativeLabels) { + // If there are no alternatives that need repeating (all are marked 'onceThrough') then just link + // the match failures to this point, and fall through to the return below. state.linkAlternativeBacktracks(this); + notEnoughInputForPreviousAlternative.link(this); + } else { + // How much more input need there be to be able to retry from the first alternative? + // examples: + // /yarr_jit/ or /wrec|pcre/ + // In these examples we need check for one more input before looping. + // /yarr_jit|pcre/ + // In this case we need check for 5 more input to loop (+4 to allow for the first alterative + // being four longer than the last alternative checked, and another +1 to effectively move + // the start position along by one). + // /yarr|rules/ or /wrec|notsomuch/ + // In these examples, provided that there was sufficient input to have just been matching for + // the second alternative we can loop without checking for available input (since the second + // alternative is longer than the first). In the latter example we need to decrement index + // (by 4) so the start position is only progressed by 1 from the last iteration. + int incrementForNextIter = (countToCheckForFirstAlternative - countCheckedForCurrentAlternative) + 1; + + // First, deal with the cases where there was sufficient input to try the last alternative. + if (incrementForNextIter > 0) // We need to check for more input anyway, fall through to the checking below. + state.linkAlternativeBacktracks(this); + else if (m_pattern.m_body->m_hasFixedSize && !incrementForNextIter) // No need to update anything, link these backtracks straight to the to pof the loop! + state.linkAlternativeBacktracksTo(firstAlternativeInputChecked, this); + else { // no need to check the input, but we do have some bookkeeping to do first. + state.linkAlternativeBacktracks(this); - // Where necessary update our preserved start position. - if (!m_pattern.m_body->m_hasFixedSize) { - move(index, regT0); - sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0); - store32(regT0, Address(output)); - } + // Where necessary update our preserved start position. + if (!m_pattern.m_body->m_hasFixedSize) { + move(index, regT0); + sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0); + store32(regT0, Address(output)); + } - // Update index if necessary, and loop (without checking). - if (incrementForNextIter) - add32(Imm32(incrementForNextIter), index); - jump().linkTo(firstAlternativeInputChecked, this); - } + // Update index if necessary, and loop (without checking). + if (incrementForNextIter) + add32(Imm32(incrementForNextIter), index); + jump().linkTo(firstAlternativeInputChecked, this); + } - notEnoughInputForPreviousAlternative.link(this); - // Update our idea of the start position, if we're tracking this. - if (!m_pattern.m_body->m_hasFixedSize) { - if (countCheckedForCurrentAlternative - 1) { - move(index, regT0); - sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0); - store32(regT0, Address(output)); - } else - store32(index, Address(output)); + notEnoughInputForPreviousAlternative.link(this); + // Update our idea of the start position, if we're tracking this. + if (!m_pattern.m_body->m_hasFixedSize) { + if (countCheckedForCurrentAlternative - 1) { + move(index, regT0); + sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0); + store32(regT0, Address(output)); + } else + store32(index, Address(output)); + } + + // Check if there is sufficent input to run the first alternative again. + jumpIfAvailableInput(incrementForNextIter).linkTo(firstAlternativeInputChecked, this); + // No - insufficent input to run the first alteranative, are there any other alternatives we + // might need to check? If so, the last check will have left the index incremented by + // (countToCheckForFirstAlternative + 1), so we need test whether countToCheckForFirstAlternative + // LESS input is available, to have the effect of just progressing the start position by 1 + // from the last iteration. If this check passes we can just jump up to the check associated + // with the first alternative in the loop. This is a bit sad, since we'll end up trying the + // first alternative again, and this check will fail (otherwise the check planted just above + // here would have passed). This is a bit sad, however it saves trying to do something more + // complex here in compilation, and in the common case we should end up coallescing the checks. + // + // FIXME: a nice improvement here may be to stop trying to match sooner, based on the least + // of the minimum-alternative-lengths. E.g. if I have two alternatives of length 200 and 150, + // and a string of length 100, we'll end up looping index from 0 to 100, checking whether there + // is sufficient input to run either alternative (constantly failing). If there had been only + // one alternative, or if the shorter alternative had come first, we would have terminated + // immediately. :-/ + if (hasShorterAlternatives) + jumpIfAvailableInput(-countToCheckForFirstAlternative).linkTo(firstAlternative, this); + // index will now be a bit garbled (depending on whether 'hasShorterAlternatives' is true, + // it has either been incremented by 1 or by (countToCheckForFirstAlternative + 1) ... + // but since we're about to return a failure this doesn't really matter!) } - // Check if there is sufficent input to run the first alternative again. - jumpIfAvailableInput(incrementForNextIter).linkTo(firstAlternativeInputChecked, this); - // No - insufficent input to run the first alteranative, are there any other alternatives we - // might need to check? If so, the last check will have left the index incremented by - // (countToCheckForFirstAlternative + 1), so we need test whether countToCheckForFirstAlternative - // LESS input is available, to have the effect of just progressing the start position by 1 - // from the last iteration. If this check passes we can just jump up to the check associated - // with the first alternative in the loop. This is a bit sad, since we'll end up trying the - // first alternative again, and this check will fail (otherwise the check planted just above - // here would have passed). This is a bit sad, however it saves trying to do something more - // complex here in compilation, and in the common case we should end up coallescing the checks. - // - // FIXME: a nice improvement here may be to stop trying to match sooner, based on the least - // of the minimum-alternative-lengths. E.g. if I have two alternatives of length 200 and 150, - // and a string of length 100, we'll end up looping index from 0 to 100, checking whether there - // is sufficient input to run either alternative (constantly failing). If there had been only - // one alternative, or if the shorter alternative had come first, we would have terminated - // immediately. :-/ - if (hasShorterAlternatives) - jumpIfAvailableInput(-countToCheckForFirstAlternative).linkTo(firstAlternative, this); - // index will now be a bit garbled (depending on whether 'hasShorterAlternatives' is true, - // it has either been incremented by 1 or by (countToCheckForFirstAlternative + 1) ... - // but since we're about to return a failure this doesn't really matter!) if (m_pattern.m_body->m_callFrameSize) addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister); diff --git a/JavaScriptCore/yarr/RegexPattern.h b/JavaScriptCore/yarr/RegexPattern.h index 61d6ad6..eecbd43 100644 --- a/JavaScriptCore/yarr/RegexPattern.h +++ b/JavaScriptCore/yarr/RegexPattern.h @@ -207,6 +207,10 @@ struct PatternTerm { struct PatternAlternative : FastAllocBase { PatternAlternative(PatternDisjunction* disjunction) : m_parent(disjunction) + , m_onceThrough(false) + , m_hasFixedSize(false) + , m_startsWithBOL(false) + , m_containsBOL(false) { } @@ -221,16 +225,30 @@ struct PatternAlternative : FastAllocBase { ASSERT(m_terms.size()); m_terms.shrink(m_terms.size() - 1); } + + void setOnceThrough() + { + m_onceThrough = true; + } + + bool onceThrough() + { + return m_onceThrough; + } Vector<PatternTerm> m_terms; PatternDisjunction* m_parent; unsigned m_minimumSize; - bool m_hasFixedSize; + bool m_onceThrough : 1; + bool m_hasFixedSize : 1; + bool m_startsWithBOL : 1; + bool m_containsBOL : 1; }; struct PatternDisjunction : FastAllocBase { PatternDisjunction(PatternAlternative* parent = 0) : m_parent(parent) + , m_hasFixedSize(false) { } @@ -269,9 +287,10 @@ struct RegexPattern { RegexPattern(bool ignoreCase, bool multiline) : m_ignoreCase(ignoreCase) , m_multiline(multiline) + , m_containsBackreferences(false) + , m_containsBOL(false) , m_numSubpatterns(0) , m_maxBackReference(0) - , m_containsBackreferences(false) , newlineCached(0) , digitsCached(0) , spacesCached(0) @@ -294,6 +313,7 @@ struct RegexPattern { m_maxBackReference = 0; m_containsBackreferences = false; + m_containsBOL = false; newlineCached = 0; digitsCached = 0; @@ -357,11 +377,12 @@ struct RegexPattern { return nonwordcharCached; } - bool m_ignoreCase; - bool m_multiline; + bool m_ignoreCase : 1; + bool m_multiline : 1; + bool m_containsBackreferences : 1; + bool m_containsBOL : 1; unsigned m_numSubpatterns; unsigned m_maxBackReference; - bool m_containsBackreferences; PatternDisjunction* m_body; Vector<PatternDisjunction*, 4> m_disjunctions; Vector<CharacterClass*> m_userCharacterClasses; |