[INTL] Implement String.prototype.localeCompare in ECMA-402
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Apr 2016 17:05:51 +0000 (17:05 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Apr 2016 17:05:51 +0000 (17:05 +0000)
commitdfaf85ec8aa4132dac6977b8ccab4ac945e9120d
treef2c565c6d4459e164e10109647374de82a84504f
parentca75675a96ca9dd8a9bd710b0dea74a2b7637b3c
[INTL] Implement String.prototype.localeCompare in ECMA-402
https://bugs.webkit.org/show_bug.cgi?id=147607

Patch by Filip Pizlo <fpizlo@apple.com> and Andy VanWagoner <thetalecrafter@gmail.com> on 2016-04-24
Reviewed by Darin Adler.
Source/JavaScriptCore:

Part of this change is just rolling 194394 back in.

The other part is making that not a regression on CDjs. Other than the fact that it uses
bound functions, the problem with this new localeCompare implementation is that it uses
the arguments object. It uses it in a way that *seems* like ArgumentsEliminationPhase
ought to handle, but to my surprise it didn't:

- If we have a ForceExit GetByVal on the arguments object, we would previously assume that
  it escaped. That's false since we just exit at ForceExit. On the other hand we probably
  should be pruning unreachable paths before we get here, but that's a separate issue. I
  don't want to play with phase order right now.

- If we have a OutOfBounds GetByVal on the arguments object, then the best that would
  previously happen is that we'd compile it into an in-bounds arguments access. That's quite
  bad, as Andy's localeCompare illustrates: it uses out-of-bounds access on the arguments
  object to detect if an argument was passed. This change introduces an OutOfBounds version
  of GetMyArgumentByVal for this purpose.

This change required registering sane chain watchpoints. In the process, I noticed that the
old way of doing it had a race condition: we might register watchpoints for the structure
that had become insane. This change introduces a double-checking idiom that I believe works
because once the structure becomes insane it can't go back to sane and watchpoints
registration already involves executing the hardest possible fences.

* builtins/StringPrototype.js:
(repeat):
(localeCompare):
(search):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGArgumentsEliminationPhase.cpp:
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::refine):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGPreciseLocalClobberize.h:
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetByValOnString):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGValidate.cpp:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileGetMyArgumentByVal):
(JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileStringCharAt):
* ftl/FTLTypedPointer.h:
(JSC::FTL::TypedPointer::TypedPointer):
(JSC::FTL::TypedPointer::operator bool):
(JSC::FTL::TypedPointer::heap):
(JSC::FTL::TypedPointer::operator!): Deleted.
* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):

LayoutTests:

* js/dom/script-tests/string-prototype-properties.js:
* js/dom/string-prototype-properties-expected.txt:
* js/regress/locale-compare.html: Added.
* js/regress/locale-compare-expected.txt: Added.
* js/regress/scripts-tests/locale-compare.js: Added.
* js/script-tests/string-localeCompare.js:
* js/string-localeCompare-expected.txt:
* js/string-localeCompare.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@199967 268f45cc-cd09-0410-ab3c-d52691b4dbfc
32 files changed:
LayoutTests/ChangeLog
LayoutTests/js/dom/script-tests/string-prototype-properties.js
LayoutTests/js/dom/string-prototype-properties-expected.txt
LayoutTests/js/regress/locale-compare-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/locale-compare.html [new file with mode: 0644]
LayoutTests/js/regress/script-tests/locale-compare.js [new file with mode: 0644]
LayoutTests/js/regress/sortamorphic-load-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/sortamorphic-load.html [new file with mode: 0644]
LayoutTests/js/script-tests/string-localeCompare.js
LayoutTests/js/string-localeCompare-expected.txt
LayoutTests/js/string-localeCompare.html
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/StringPrototype.js
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp
Source/JavaScriptCore/dfg/DFGArrayMode.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/ftl/FTLTypedPointer.h
Source/JavaScriptCore/runtime/StringPrototype.cpp