<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[199075] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/199075">199075</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-04-05 15:13:16 -0700 (Tue, 05 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>
Source/JavaScriptCore:
DFG and FTL should constant-fold RegExpExec, RegExpTest, and StringReplace
https://bugs.webkit.org/show_bug.cgi?id=155270

Reviewed by Saam Barati.

This enables constant-folding of RegExpExec, RegExpTest, and StringReplace.

It's now possible to run Yarr on the JIT threads. Since previous work on constant-folding
strings gave the DFG an API for reasoning about JSString constants in terms of
JIT-thread-local WTF::Strings, it's now super easy to just pass strings to Yarr and build IR
based on the results.

But RegExpExec is hard: the folded version still must allocate a RegExpMatchesArray. We must
use the same Structure that the code would have used or else we'll pollute the program's
inline caches. Also, RegExpMatchesArray.h|cpp will allocate the array and its named
properties in one go - we don't want to lose that optimization. So, this patch enables
MaterializeNewObject to allocate objects or arrays with any number of indexed or named
properties. Previously it could only handle objects (but not arrays) and named properties
(but not indexed ones).

This also adds a few minor things for setting the RegExpConstructor cached result.

This is about a 2x speed-up on microbenchmarks when we fold a match success and about a
8x speed-up when we fold a match failure. It's a 10% speed-up on Octane/regexp.

* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGInsertionSet.cpp:
(JSC::DFG::InsertionSet::insertSlow):
(JSC::DFG::InsertionSet::execute):
* dfg/DFGInsertionSet.h:
(JSC::DFG::InsertionSet::insertCheck):
* dfg/DFGLazyJSValue.cpp:
(JSC::DFG::LazyJSValue::tryGetString):
* dfg/DFGMayExit.cpp:
(JSC::DFG::mayExit):
* dfg/DFGNode.h:
(JSC::DFG::StackAccessData::flushedAt):
(JSC::DFG::OpInfo::OpInfo): Deleted.
* dfg/DFGNodeType.h:
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGObjectMaterializationData.cpp:
(JSC::DFG::ObjectMaterializationData::dump):
(JSC::DFG::PhantomPropertyValue::dump): Deleted.
(JSC::DFG::ObjectMaterializationData::oneWaySimilarityScore): Deleted.
(JSC::DFG::ObjectMaterializationData::similarityScore): Deleted.
* dfg/DFGObjectMaterializationData.h:
(JSC::DFG::PhantomPropertyValue::PhantomPropertyValue): Deleted.
(JSC::DFG::PhantomPropertyValue::operator==): Deleted.
* dfg/DFGOpInfo.h: Added.
(JSC::DFG::OpInfo::OpInfo):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGPromotedHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGPromotedHeapLocation.h:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::~SpeculativeJIT):
(JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
(JSC::DFG::SpeculativeJIT::emitGetLength):
(JSC::DFG::SpeculativeJIT::compileLazyJSConstant):
(JSC::DFG::SpeculativeJIT::compileMaterializeNewObject):
(JSC::DFG::SpeculativeJIT::compileRecordRegExpCachedResult):
(JSC::DFG::SpeculativeJIT::emitAllocateJSArray): Deleted.
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::emitAllocateDestructibleObject):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStoreBarrierInsertionPhase.cpp:
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::StrengthReductionPhase):
(JSC::DFG::StrengthReductionPhase::handleNode):
(JSC::DFG::StrengthReductionPhase::handleCommutativity):
(JSC::DFG::StrengthReductionPhase::executeInsertionSet):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validate):
(JSC::DFG::Validate::validateCPS):
* ftl/FTLAbstractHeapRepository.cpp:
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeCreateActivation):
(JSC::FTL::DFG::LowerDFGToB3::compileSetRegExpObjectLastIndex):
(JSC::FTL::DFG::LowerDFGToB3::compileRecordRegExpCachedResult):
(JSC::FTL::DFG::LowerDFGToB3::didOverflowStack):
(JSC::FTL::DFG::LowerDFGToB3::storageForTransition):
(JSC::FTL::DFG::LowerDFGToB3::initializeArrayElements):
(JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::isNotCellOrMisc):
(JSC::FTL::DFG::LowerDFGToB3::unboxDouble):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationPopulateObjectInOSR):
(JSC::FTL::operationNewObjectWithButterfly): Deleted.
* ftl/FTLOperations.h:
* inspector/ContentSearchUtilities.cpp:
* runtime/JSObject.h:
(JSC::JSObject::createRawObject):
(JSC::JSFinalObject::create):
* runtime/RegExp.cpp:
(JSC::RegExp::compile):
(JSC::RegExp::match):
(JSC::RegExp::matchConcurrently):
(JSC::RegExp::compileMatchOnly):
(JSC::RegExp::deleteCode):
* runtime/RegExp.h:
* runtime/RegExpCachedResult.h:
(JSC::RegExpCachedResult::offsetOfLastRegExp):
(JSC::RegExpCachedResult::offsetOfLastInput):
(JSC::RegExpCachedResult::offsetOfResult):
(JSC::RegExpCachedResult::offsetOfReified):
* runtime/RegExpConstructor.h:
(JSC::RegExpConstructor::offsetOfCachedResult):
* runtime/RegExpInlines.h:
(JSC::RegExp::hasCodeFor):
(JSC::RegExp::compileIfNecessary):
(JSC::RegExp::matchInline):
(JSC::RegExp::hasMatchOnlyCodeFor):
(JSC::RegExp::compileIfNecessaryMatchOnly):
* runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::execInline):
* runtime/StringPrototype.cpp:
(JSC::substituteBackreferencesSlow):
(JSC::substituteBackreferencesInline):
(JSC::substituteBackreferences):
(JSC::StringRange::StringRange):
* runtime/StringPrototype.h:
* runtime/VM.h:
* tests/stress/simple-regexp-exec-folding-fail.js: Added.
(foo):
* tests/stress/simple-regexp-exec-folding.js: Added.
(foo):
* tests/stress/simple-regexp-test-folding-fail.js: Added.
(foo):
* tests/stress/simple-regexp-test-folding.js: Added.
(foo):
* yarr/RegularExpression.cpp:
* yarr/Yarr.h:
* yarr/YarrInterpreter.cpp:
(JSC::Yarr::Interpreter::interpret):
(JSC::Yarr::ByteCompiler::ByteCompiler):
(JSC::Yarr::ByteCompiler::compile):
(JSC::Yarr::ByteCompiler::checkInput):
(JSC::Yarr::byteCompile):
(JSC::Yarr::interpret):
* yarr/YarrInterpreter.h:
(JSC::Yarr::BytecodePattern::BytecodePattern):

Source/WTF:
DFG and FTL should constant-fold RegExpExec
https://bugs.webkit.org/show_bug.cgi?id=155270

Reviewed by Saam Barati.

Make executeInsertions() return the amount by which the vector increased in size. This is a
convenient feature that I use in DFG::InsertionSet.

* wtf/Insertion.h:
(WTF::executeInsertions):

LayoutTests:
DFG and FTL should constant-fold RegExpExec
https://bugs.webkit.org/show_bug.cgi?id=155270

Reviewed by Saam Barati.

* js/regress/script-tests/simple-regexp-exec-folding-fail.js: Added.
* js/regress/script-tests/simple-regexp-exec-folding.js: Added.
* js/regress/script-tests/simple-regexp-test-folding-fail.js: Added.
* js/regress/script-tests/simple-regexp-test-folding.js: Added.
* js/regress/simple-regexp-exec-folding-expected.txt: Added.
* js/regress/simple-regexp-exec-folding-fail-expected.txt: Added.
* js/regress/simple-regexp-exec-folding-fail.html: Added.
* js/regress/simple-regexp-exec-folding.html: Added.
* js/regress/simple-regexp-test-folding-expected.txt: Added.
* js/regress/simple-regexp-test-folding-fail-expected.txt: Added.
* js/regress/simple-regexp-test-folding-fail.html: Added.
* js/regress/simple-regexp-test-folding.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInsertionSetcpp">trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInsertionSeth">trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMayExitcpp">trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectMaterializationDatacpp">trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectMaterializationDatah">trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationcpp">trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationh">trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGValidatecpp">trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositorycpp">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOperationscpp">trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOperationsh">trunk/Source/JavaScriptCore/ftl/FTLOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorContentSearchUtilitiescpp">trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjecth">trunk/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpcpp">trunk/Source/JavaScriptCore/runtime/RegExp.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExph">trunk/Source/JavaScriptCore/runtime/RegExp.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpCachedResulth">trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpConstructorh">trunk/Source/JavaScriptCore/runtime/RegExpConstructor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpInlinesh">trunk/Source/JavaScriptCore/runtime/RegExpInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpObjectInlinesh">trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStringPrototypecpp">trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStringPrototypeh">trunk/Source/JavaScriptCore/runtime/StringPrototype.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrRegularExpressioncpp">trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrh">trunk/Source/JavaScriptCore/yarr/Yarr.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrInterpretercpp">trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrInterpreterh">trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfInsertionh">trunk/Source/WTF/wtf/Insertion.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressscripttestssimpleregexpexecfoldingfailjs">trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding-fail.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssimpleregexpexecfoldingjs">trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssimpleregexptestfoldingfailjs">trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding-fail.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssimpleregexptestfoldingjs">trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding.js</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexpexecfoldingexpectedtxt">trunk/LayoutTests/js/regress/simple-regexp-exec-folding-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexpexecfoldingfailexpectedtxt">trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexpexecfoldingfailhtml">trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail.html</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexpexecfoldinghtml">trunk/LayoutTests/js/regress/simple-regexp-exec-folding.html</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexptestfoldingexpectedtxt">trunk/LayoutTests/js/regress/simple-regexp-test-folding-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexptestfoldingfailexpectedtxt">trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexptestfoldingfailhtml">trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail.html</a></li>
<li><a href="#trunkLayoutTestsjsregresssimpleregexptestfoldinghtml">trunk/LayoutTests/js/regress/simple-regexp-test-folding.html</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOpInfoh">trunk/Source/JavaScriptCore/dfg/DFGOpInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssimpleregexpexecfoldingfailjs">trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding-fail.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssimpleregexpexecfoldingjs">trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssimpleregexptestfoldingfailjs">trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding-fail.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssimpleregexptestfoldingjs">trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/LayoutTests/ChangeLog        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2016-03-19  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG and FTL should constant-fold RegExpExec
+        https://bugs.webkit.org/show_bug.cgi?id=155270
+
+        Reviewed by Saam Barati.
+
+        * js/regress/script-tests/simple-regexp-exec-folding-fail.js: Added.
+        * js/regress/script-tests/simple-regexp-exec-folding.js: Added.
+        * js/regress/script-tests/simple-regexp-test-folding-fail.js: Added.
+        * js/regress/script-tests/simple-regexp-test-folding.js: Added.
+        * js/regress/simple-regexp-exec-folding-expected.txt: Added.
+        * js/regress/simple-regexp-exec-folding-fail-expected.txt: Added.
+        * js/regress/simple-regexp-exec-folding-fail.html: Added.
+        * js/regress/simple-regexp-exec-folding.html: Added.
+        * js/regress/simple-regexp-test-folding-expected.txt: Added.
+        * js/regress/simple-regexp-test-folding-fail-expected.txt: Added.
+        * js/regress/simple-regexp-test-folding-fail.html: Added.
+        * js/regress/simple-regexp-test-folding.html: Added.
+
</ins><span class="cx"> 2016-04-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         PolymorphicAccess should have a MegamorphicLoad case
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssimpleregexpexecfoldingfailjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding-fail.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding-fail.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding-fail.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+(function() {
+    for (var i = 0; i &lt; 1000000; ++i)
+        /foo/.exec(&quot;bar&quot;);
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssimpleregexpexecfoldingjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/simple-regexp-exec-folding.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+(function() {
+    for (var i = 0; i &lt; 1000000; ++i)
+        /foo/.exec(&quot;foo&quot;);
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssimpleregexptestfoldingfailjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding-fail.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding-fail.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding-fail.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+(function() {
+    for (var i = 0; i &lt; 1000000; ++i)
+        /foo/.test(&quot;bar&quot;);
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssimpleregexptestfoldingjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/simple-regexp-test-folding.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+(function() {
+    for (var i = 0; i &lt; 1000000; ++i)
+        /foo/.test(&quot;foo&quot;);
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexpexecfoldingexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-exec-folding-expected.txt (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-exec-folding-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-exec-folding-expected.txt        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/simple-regexp-exec-folding
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexpexecfoldingfailexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail-expected.txt (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail-expected.txt        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/simple-regexp-exec-folding-fail
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexpexecfoldingfailhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail.html (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-exec-folding-fail.html        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/simple-regexp-exec-folding-fail.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexpexecfoldinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-exec-folding.html (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-exec-folding.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-exec-folding.html        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/simple-regexp-exec-folding.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexptestfoldingexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-test-folding-expected.txt (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-test-folding-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-test-folding-expected.txt        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/simple-regexp-test-folding
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexptestfoldingfailexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail-expected.txt (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail-expected.txt        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/simple-regexp-test-folding-fail
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexptestfoldingfailhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail.html (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-test-folding-fail.html        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/simple-regexp-test-folding-fail.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimpleregexptestfoldinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-regexp-test-folding.html (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-regexp-test-folding.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-regexp-test-folding.html        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/simple-regexp-test-folding.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,3 +1,171 @@
</span><ins>+2016-03-19  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG and FTL should constant-fold RegExpExec, RegExpTest, and StringReplace
+        https://bugs.webkit.org/show_bug.cgi?id=155270
+
+        Reviewed by Saam Barati.
+
+        This enables constant-folding of RegExpExec, RegExpTest, and StringReplace.
+
+        It's now possible to run Yarr on the JIT threads. Since previous work on constant-folding
+        strings gave the DFG an API for reasoning about JSString constants in terms of
+        JIT-thread-local WTF::Strings, it's now super easy to just pass strings to Yarr and build IR
+        based on the results.
+
+        But RegExpExec is hard: the folded version still must allocate a RegExpMatchesArray. We must
+        use the same Structure that the code would have used or else we'll pollute the program's
+        inline caches. Also, RegExpMatchesArray.h|cpp will allocate the array and its named
+        properties in one go - we don't want to lose that optimization. So, this patch enables
+        MaterializeNewObject to allocate objects or arrays with any number of indexed or named
+        properties. Previously it could only handle objects (but not arrays) and named properties
+        (but not indexed ones).
+
+        This also adds a few minor things for setting the RegExpConstructor cached result.
+
+        This is about a 2x speed-up on microbenchmarks when we fold a match success and about a
+        8x speed-up when we fold a match failure. It's a 10% speed-up on Octane/regexp.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGInsertionSet.cpp:
+        (JSC::DFG::InsertionSet::insertSlow):
+        (JSC::DFG::InsertionSet::execute):
+        * dfg/DFGInsertionSet.h:
+        (JSC::DFG::InsertionSet::insertCheck):
+        * dfg/DFGLazyJSValue.cpp:
+        (JSC::DFG::LazyJSValue::tryGetString):
+        * dfg/DFGMayExit.cpp:
+        (JSC::DFG::mayExit):
+        * dfg/DFGNode.h:
+        (JSC::DFG::StackAccessData::flushedAt):
+        (JSC::DFG::OpInfo::OpInfo): Deleted.
+        * dfg/DFGNodeType.h:
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        * dfg/DFGObjectMaterializationData.cpp:
+        (JSC::DFG::ObjectMaterializationData::dump):
+        (JSC::DFG::PhantomPropertyValue::dump): Deleted.
+        (JSC::DFG::ObjectMaterializationData::oneWaySimilarityScore): Deleted.
+        (JSC::DFG::ObjectMaterializationData::similarityScore): Deleted.
+        * dfg/DFGObjectMaterializationData.h:
+        (JSC::DFG::PhantomPropertyValue::PhantomPropertyValue): Deleted.
+        (JSC::DFG::PhantomPropertyValue::operator==): Deleted.
+        * dfg/DFGOpInfo.h: Added.
+        (JSC::DFG::OpInfo::OpInfo):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGPromotedHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGPromotedHeapLocation.h:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::~SpeculativeJIT):
+        (JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
+        (JSC::DFG::SpeculativeJIT::emitGetLength):
+        (JSC::DFG::SpeculativeJIT::compileLazyJSConstant):
+        (JSC::DFG::SpeculativeJIT::compileMaterializeNewObject):
+        (JSC::DFG::SpeculativeJIT::compileRecordRegExpCachedResult):
+        (JSC::DFG::SpeculativeJIT::emitAllocateJSArray): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::emitAllocateDestructibleObject):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStoreBarrierInsertionPhase.cpp:
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::StrengthReductionPhase):
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        (JSC::DFG::StrengthReductionPhase::handleCommutativity):
+        (JSC::DFG::StrengthReductionPhase::executeInsertionSet):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        (JSC::DFG::Validate::validateCPS):
+        * ftl/FTLAbstractHeapRepository.cpp:
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeCreateActivation):
+        (JSC::FTL::DFG::LowerDFGToB3::compileSetRegExpObjectLastIndex):
+        (JSC::FTL::DFG::LowerDFGToB3::compileRecordRegExpCachedResult):
+        (JSC::FTL::DFG::LowerDFGToB3::didOverflowStack):
+        (JSC::FTL::DFG::LowerDFGToB3::storageForTransition):
+        (JSC::FTL::DFG::LowerDFGToB3::initializeArrayElements):
+        (JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorage):
+        (JSC::FTL::DFG::LowerDFGToB3::isNotCellOrMisc):
+        (JSC::FTL::DFG::LowerDFGToB3::unboxDouble):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::operationPopulateObjectInOSR):
+        (JSC::FTL::operationNewObjectWithButterfly): Deleted.
+        * ftl/FTLOperations.h:
+        * inspector/ContentSearchUtilities.cpp:
+        * runtime/JSObject.h:
+        (JSC::JSObject::createRawObject):
+        (JSC::JSFinalObject::create):
+        * runtime/RegExp.cpp:
+        (JSC::RegExp::compile):
+        (JSC::RegExp::match):
+        (JSC::RegExp::matchConcurrently):
+        (JSC::RegExp::compileMatchOnly):
+        (JSC::RegExp::deleteCode):
+        * runtime/RegExp.h:
+        * runtime/RegExpCachedResult.h:
+        (JSC::RegExpCachedResult::offsetOfLastRegExp):
+        (JSC::RegExpCachedResult::offsetOfLastInput):
+        (JSC::RegExpCachedResult::offsetOfResult):
+        (JSC::RegExpCachedResult::offsetOfReified):
+        * runtime/RegExpConstructor.h:
+        (JSC::RegExpConstructor::offsetOfCachedResult):
+        * runtime/RegExpInlines.h:
+        (JSC::RegExp::hasCodeFor):
+        (JSC::RegExp::compileIfNecessary):
+        (JSC::RegExp::matchInline):
+        (JSC::RegExp::hasMatchOnlyCodeFor):
+        (JSC::RegExp::compileIfNecessaryMatchOnly):
+        * runtime/RegExpObjectInlines.h:
+        (JSC::RegExpObject::execInline):
+        * runtime/StringPrototype.cpp:
+        (JSC::substituteBackreferencesSlow):
+        (JSC::substituteBackreferencesInline):
+        (JSC::substituteBackreferences):
+        (JSC::StringRange::StringRange):
+        * runtime/StringPrototype.h:
+        * runtime/VM.h:
+        * tests/stress/simple-regexp-exec-folding-fail.js: Added.
+        (foo):
+        * tests/stress/simple-regexp-exec-folding.js: Added.
+        (foo):
+        * tests/stress/simple-regexp-test-folding-fail.js: Added.
+        (foo):
+        * tests/stress/simple-regexp-test-folding.js: Added.
+        (foo):
+        * yarr/RegularExpression.cpp:
+        * yarr/Yarr.h:
+        * yarr/YarrInterpreter.cpp:
+        (JSC::Yarr::Interpreter::interpret):
+        (JSC::Yarr::ByteCompiler::ByteCompiler):
+        (JSC::Yarr::ByteCompiler::compile):
+        (JSC::Yarr::ByteCompiler::checkInput):
+        (JSC::Yarr::byteCompile):
+        (JSC::Yarr::interpret):
+        * yarr/YarrInterpreter.h:
+        (JSC::Yarr::BytecodePattern::BytecodePattern):
+
</ins><span class="cx"> 2016-04-05  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         We should support the ability to do a non-effectful getById
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -488,6 +488,7 @@
</span><span class="cx">                 0F7C11AD1BC3862C00C74CDB /* CopyBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FA1C8F629300480151 /* RegExpInlines.h */; };
</span><span class="cx">                 0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */; };
</span><ins>+                0F7C39FF1C90C55B00480151 /* DFGOpInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */; };
</ins><span class="cx">                 0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
</span><span class="cx">                 0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2638,6 +2639,7 @@
</span><span class="cx">                 0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyBarrier.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7C39FA1C8F629300480151 /* RegExpInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpObjectInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOpInfo.h; path = dfg/DFGOpInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F8023E91613832300A0BA45 /* ByValInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByValInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayAllocationProfile.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -6246,6 +6248,7 @@
</span><span class="cx">                                 0F2B9CDD19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h */,
</span><span class="cx">                                 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */,
</span><span class="cx">                                 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */,
</span><ins>+                                0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */,
</ins><span class="cx">                                 A7D89CEE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.cpp */,
</span><span class="cx">                                 A7D89CEF17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h */,
</span><span class="cx">                                 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */,
</span><span class="lines">@@ -7448,6 +7451,7 @@
</span><span class="cx">                                 0F64EAF31C4ECD0600621E9B /* AirArgInlines.h in Headers */,
</span><span class="cx">                                 A5EA710519F6DE740098F5EC /* generate_objc_configuration_header.py in Headers */,
</span><span class="cx">                                 A5EA710619F6DE760098F5EC /* generate_objc_configuration_implementation.py in Headers */,
</span><ins>+                                0F7C39FF1C90C55B00480151 /* DFGOpInfo.h in Headers */,
</ins><span class="cx">                                 A5EA710719F6DE780098F5EC /* generate_objc_protocol_type_conversions_header.py in Headers */,
</span><span class="cx">                                 0F338DF61BE93D550013C88F /* B3ConstrainedValue.h in Headers */,
</span><span class="cx">                                 A5EA710819F6DE7A0098F5EC /* generate_objc_frontend_dispatcher_implementation.py in Headers */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1955,6 +1955,7 @@
</span><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case SetRegExpObjectLastIndex:
</span><ins>+    case RecordRegExpCachedResult:
</ins><span class="cx">         break;
</span><span class="cx">         
</span><span class="cx">     case GetFromArguments:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -917,6 +917,10 @@
</span><span class="cx">         write(RegExpObject_lastIndex);
</span><span class="cx">         def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node-&gt;child1()), LazyNode(node-&gt;child2().node()));
</span><span class="cx">         return;
</span><ins>+
+    case RecordRegExpCachedResult:
+        write(RegExpState);
+        return;
</ins><span class="cx">         
</span><span class="cx">     case GetFromArguments: {
</span><span class="cx">         AbstractHeap heap(DirectArgumentsProperties, node-&gt;capturedArgumentsOffset().offset());
</span><span class="lines">@@ -1080,7 +1084,9 @@
</span><span class="cx">         if (node-&gt;child2().useKind() == RegExpObjectUse
</span><span class="cx">             &amp;&amp; node-&gt;child3().useKind() == StringUse) {
</span><span class="cx">             read(RegExpState);
</span><ins>+            read(RegExpObject_lastIndex);
</ins><span class="cx">             write(RegExpState);
</span><ins>+            write(RegExpObject_lastIndex);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         read(World);
</span><span class="lines">@@ -1092,7 +1098,9 @@
</span><span class="cx">             &amp;&amp; node-&gt;child2().useKind() == RegExpObjectUse
</span><span class="cx">             &amp;&amp; node-&gt;child3().useKind() == StringUse) {
</span><span class="cx">             read(RegExpState);
</span><ins>+            read(RegExpObject_lastIndex);
</ins><span class="cx">             write(RegExpState);
</span><ins>+            write(RegExpObject_lastIndex);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         read(World);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -117,6 +117,7 @@
</span><span class="cx">     case PutClosureVar:
</span><span class="cx">     case GetRegExpObjectLastIndex:
</span><span class="cx">     case SetRegExpObjectLastIndex:
</span><ins>+    case RecordRegExpCachedResult:
</ins><span class="cx">     case GetGlobalVar:
</span><span class="cx">     case GetGlobalLexicalVariable:
</span><span class="cx">     case PutGlobalVariable:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1300,6 +1300,7 @@
</span><span class="cx">         case StoreBarrier:
</span><span class="cx">         case GetRegExpObjectLastIndex:
</span><span class="cx">         case SetRegExpObjectLastIndex:
</span><ins>+        case RecordRegExpCachedResult:
</ins><span class="cx">             // These are just nodes that we don't currently expect to see during fixup.
</span><span class="cx">             // If we ever wanted to insert them prior to fixup, then we just have to create
</span><span class="cx">             // fixup rules for them.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -315,6 +315,8 @@
</span><span class="cx">             out.print(anotherComma, pointerDumpInContext(freeze(m_codeBlock-&gt;constantBuffer(node-&gt;startConstant())[i]), context));
</span><span class="cx">         out.print(&quot;]&quot;);
</span><span class="cx">     }
</span><ins>+    if (node-&gt;hasLazyJSValue())
+        out.print(comma, node-&gt;lazyJSValue());
</ins><span class="cx">     if (node-&gt;hasIndexingType())
</span><span class="cx">         out.print(comma, IndexingTypeDump(node-&gt;indexingType()));
</span><span class="cx">     if (node-&gt;hasTypedArrayType())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInsertionSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -45,9 +45,9 @@
</span><span class="cx">     m_insertions.insert(0, insertion);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InsertionSet::execute(BasicBlock* block)
</del><ins>+size_t InsertionSet::execute(BasicBlock* block)
</ins><span class="cx"> {
</span><del>-    executeInsertions(*block, m_insertions);
</del><ins>+    return executeInsertions(*block, m_insertions);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInsertionSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -129,7 +129,7 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void execute(BasicBlock* block);
</del><ins>+    size_t execute(BasicBlock* block);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void insertSlow(const Insertion&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMayExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -131,6 +131,7 @@
</span><span class="cx">     case StoreBarrier:
</span><span class="cx">     case PutByOffset:
</span><span class="cx">     case PutClosureVar:
</span><ins>+    case RecordRegExpCachedResult:
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case StrCat:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #include &quot;DFGNodeOrigin.h&quot;
</span><span class="cx"> #include &quot;DFGNodeType.h&quot;
</span><span class="cx"> #include &quot;DFGObjectMaterializationData.h&quot;
</span><ins>+#include &quot;DFGOpInfo.h&quot;
</ins><span class="cx"> #include &quot;DFGTransition.h&quot;
</span><span class="cx"> #include &quot;DFGUseKind.h&quot;
</span><span class="cx"> #include &quot;DFGVariableAccessData.h&quot;
</span><span class="lines">@@ -219,20 +220,6 @@
</span><span class="cx">     FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-// This type used in passing an immediate argument to Node constructor;
-// distinguishes an immediate value (typically an index into a CodeBlock data structure - 
-// a constant index, argument, or identifier) from a Node*.
-struct OpInfo {
-    OpInfo() : m_value(0) { }
-    explicit OpInfo(int32_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
-    explicit OpInfo(uint32_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
-#if OS(DARWIN) || USE(JSVALUE64)
-    explicit OpInfo(size_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
-#endif
-    explicit OpInfo(void* value) : m_value(reinterpret_cast&lt;uintptr_t&gt;(value)) { }
-    uintptr_t m_value;
-};
-
</del><span class="cx"> // === Node ===
</span><span class="cx"> //
</span><span class="cx"> // Node represents a single operation in the data flow graph.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -224,6 +224,7 @@
</span><span class="cx">     macro(VarInjectionWatchpoint, NodeMustGenerate) \
</span><span class="cx">     macro(GetRegExpObjectLastIndex, NodeResultJS) \
</span><span class="cx">     macro(SetRegExpObjectLastIndex, NodeMustGenerate) \
</span><ins>+    macro(RecordRegExpCachedResult, NodeMustGenerate | NodeHasVarArgs) \
</ins><span class="cx">     macro(CheckCell, NodeMustGenerate) \
</span><span class="cx">     macro(CheckNotEmpty, NodeMustGenerate) \
</span><span class="cx">     macro(CheckBadCell, NodeMustGenerate) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1974,7 +1974,7 @@
</span><span class="cx"> 
</span><span class="cx">                 case NamedPropertyPLoc: {
</span><span class="cx">                     ASSERT(location.base() == allocation.identifier());
</span><del>-                    data.m_properties.append(PhantomPropertyValue(location.info()));
</del><ins>+                    data.m_properties.append(location.descriptor());
</ins><span class="cx">                     Node* value = resolve(block, location);
</span><span class="cx">                     if (m_sinkCandidates.contains(value))
</span><span class="cx">                         m_graph.m_varArgChildren.append(m_bottom);
</span><span class="lines">@@ -2024,7 +2024,7 @@
</span><span class="cx"> 
</span><span class="cx">                 case ClosureVarPLoc: {
</span><span class="cx">                     ASSERT(location.base() == allocation.identifier());
</span><del>-                    data.m_properties.append(PhantomPropertyValue(location.info()));
</del><ins>+                    data.m_properties.append(location.descriptor());
</ins><span class="cx">                     Node* value = resolve(block, location);
</span><span class="cx">                     if (m_sinkCandidates.contains(value))
</span><span class="cx">                         m_graph.m_varArgChildren.append(m_bottom);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectMaterializationDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,32 +32,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><del>-void PhantomPropertyValue::dump(PrintStream&amp; out) const
-{
-    out.print(&quot;id&quot;, m_identifierNumber);
-}
-
</del><span class="cx"> void ObjectMaterializationData::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     out.print(&quot;[&quot;, listDump(m_properties), &quot;]&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-float ObjectMaterializationData::oneWaySimilarityScore(
-    const ObjectMaterializationData&amp; other) const
-{
-    unsigned numHits = 0;
-    for (PhantomPropertyValue value : m_properties) {
-        if (other.m_properties.contains(value))
-            numHits++;
-    }
-    return static_cast&lt;float&gt;(numHits) / static_cast&lt;float&gt;(m_properties.size());
-}
-
-float ObjectMaterializationData::similarityScore(const ObjectMaterializationData&amp; other) const
-{
-    return std::min(oneWaySimilarityScore(other), other.oneWaySimilarityScore(*this));
-}
-
</del><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectMaterializationDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;DFGPromotedHeapLocation.h&quot;
</ins><span class="cx"> #include &lt;limits.h&gt;
</span><span class="cx"> #include &lt;wtf/MathExtras.h&gt;
</span><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="lines">@@ -35,38 +36,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><del>-struct PhantomPropertyValue {
-    PhantomPropertyValue()
-        : m_identifierNumber(UINT_MAX)
-    {
-    }
-    
-    PhantomPropertyValue(unsigned identifierNumber)
-        : m_identifierNumber(identifierNumber)
-    {
-    }
-    
-    unsigned m_identifierNumber;
-    
-    bool operator==(const PhantomPropertyValue&amp; other) const
-    {
-        return m_identifierNumber == other.m_identifierNumber;
-    }
-    
-    void dump(PrintStream&amp;) const;
-};
-
</del><span class="cx"> struct ObjectMaterializationData {
</span><span class="cx">     // Determines the meaning of the passed nodes.
</span><del>-    Vector&lt;PhantomPropertyValue&gt; m_properties;
</del><ins>+    Vector&lt;PromotedLocationDescriptor&gt; m_properties;
</ins><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><del>-    
-    // The fraction of my properties that the other data has.
-    float oneWaySimilarityScore(const ObjectMaterializationData&amp;) const;
-    
-    // The minimum of the two possible one-way scores.
-    float similarityScore(const ObjectMaterializationData&amp;) const;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOpInfoh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGOpInfo.h (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOpInfo.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGOpInfo.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGOpInfo_h
+#define DFGOpInfo_h
+
+#include &lt;wtf/StdLibExtras.h&gt;
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+// This type used in passing an immediate argument to Node constructor;
+// distinguishes an immediate value (typically an index into a CodeBlock data structure - 
+// a constant index, argument, or identifier) from a Node*.
+struct OpInfo {
+    OpInfo() : m_value(0) { }
+    explicit OpInfo(int32_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
+    explicit OpInfo(uint32_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
+#if OS(DARWIN) || USE(JSVALUE64)
+    explicit OpInfo(size_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
+#endif
+    explicit OpInfo(void* value) : m_value(reinterpret_cast&lt;uintptr_t&gt;(value)) { }
+    uintptr_t m_value;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGOpInfo_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1397,6 +1397,60 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+
+    Butterfly* butterfly;
+    if (structure-&gt;outOfLineCapacity() || hasIndexedProperties(structure-&gt;indexingType())) {
+        IndexingHeader header;
+        header.setVectorLength(length);
+        header.setPublicLength(0);
+        
+        butterfly = Butterfly::create(
+            vm, nullptr, 0, structure-&gt;outOfLineCapacity(),
+            hasIndexedProperties(structure-&gt;indexingType()), header,
+            length * sizeof(EncodedJSValue));
+    } else
+        butterfly = nullptr;
+
+    JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
+    result-&gt;butterfly(); // Ensure that the butterfly is in to-space.
+    return bitwise_cast&lt;char*&gt;(result);
+}
+
+JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    
+    Butterfly* butterfly = Butterfly::create(
+        vm, nullptr, 0, structure-&gt;outOfLineCapacity(), false, IndexingHeader(), 0);
+    
+    JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
+    result-&gt;butterfly(); // Ensure that the butterfly is in to-space.
+    return result;
+}
+
+JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+
+    IndexingHeader header;
+    header.setVectorLength(length);
+    header.setPublicLength(0);
+    Butterfly* butterfly = Butterfly::create(
+        vm, nullptr, 0, structure-&gt;outOfLineCapacity(), true, header,
+        sizeof(EncodedJSValue) * length);
+
+    // Paradoxically this may allocate a JSArray. That's totally cool.
+    JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
+    result-&gt;butterfly(); // Ensure that the butterfly is in to-space.
+    return result;
+}
+
</ins><span class="cx"> void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
</span><span class="cx"> {
</span><span class="cx">     exec-&gt;vm().typeProfilerLog()-&gt;processLogEntries(ASCIILiteral(&quot;Log Full, called from inside DFG.&quot;));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -155,6 +155,10 @@
</span><span class="cx"> 
</span><span class="cx"> size_t JIT_OPERATION operationDefaultHasInstance(ExecState*, JSCell* value, JSCell* proto);
</span><span class="cx"> 
</span><ins>+char* JIT_OPERATION operationNewRawObject(ExecState*, Structure*, int32_t) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState*, Structure*) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState*, Structure*, unsigned length) WTF_INTERNAL;
+
</ins><span class="cx"> void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState*) WTF_INTERNAL;
</span><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*, void*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -668,6 +668,7 @@
</span><span class="cx">         case GetStack:
</span><span class="cx">         case GetRegExpObjectLastIndex:
</span><span class="cx">         case SetRegExpObjectLastIndex:
</span><ins>+        case RecordRegExpCachedResult:
</ins><span class="cx">         case LazyJSConstant: {
</span><span class="cx">             // This node should never be visible at this stage of compilation. It is
</span><span class="cx">             // inserted by fixup(), which follows this phase.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -74,6 +74,10 @@
</span><span class="cx">     case NamedPropertyPLoc:
</span><span class="cx">         out.print(&quot;NamedPropertyPLoc&quot;);
</span><span class="cx">         return;
</span><ins>+
+    case IndexedPropertyPLoc:
+        out.print(&quot;IndexedPropertyPLoc&quot;);
+        return;
</ins><span class="cx">         
</span><span class="cx">     case ArgumentPLoc:
</span><span class="cx">         out.print(&quot;ArgumentPLoc&quot;);
</span><span class="lines">@@ -102,6 +106,14 @@
</span><span class="cx">     case ClosureVarPLoc:
</span><span class="cx">         out.print(&quot;ClosureVarPLoc&quot;);
</span><span class="cx">         return;
</span><ins>+
+    case PublicLengthPLoc:
+        out.print(&quot;PublicLengthPLoc&quot;);
+        return;
+
+    case VectorLengthPLoc:
+        out.print(&quot;VectorLengthPLoc&quot;);
+        return;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,25 +28,41 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><del>-#include &quot;DFGNode.h&quot;
</del><ins>+#include &quot;DFGEdge.h&quot;
+#include &quot;DFGNodeOrigin.h&quot;
+#include &quot;DFGOpInfo.h&quot;
+#include &lt;wtf/HashTable.h&gt;
</ins><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><ins>+struct Node;
+
+// Promoted locations are like heap locations but are meant to be more precise. A heap location is
+// applicable to CSE scenarios, where it makes sense to speak of a location very abstractly. A
+// promoted heap location is for cases where we speak of a specific object and the compiler knows
+// this object's identity - for example, the object allocation has been eliminated and we turned the
+// fields into local variables. Because these two cases have subtly different needs, we use subtly
+// different structures. One of the really significant differences is that promoted locations can be
+// spoken of using either a descriptor which does not refer to any Node*'s or with a heap location,
+// which is a descriptor with a Node* base.
+
</ins><span class="cx"> enum PromotedLocationKind {
</span><span class="cx">     InvalidPromotedLocationKind,
</span><span class="cx">     
</span><del>-    StructurePLoc,
</del><ins>+    ActivationScopePLoc,
</ins><span class="cx">     ActivationSymbolTablePLoc,
</span><del>-    NamedPropertyPLoc,
</del><ins>+    ArgumentCountPLoc,
</ins><span class="cx">     ArgumentPLoc,
</span><del>-    ArgumentCountPLoc,
</del><span class="cx">     ArgumentsCalleePLoc,
</span><del>-
</del><ins>+    ClosureVarPLoc,
+    FunctionActivationPLoc,
</ins><span class="cx">     FunctionExecutablePLoc,
</span><del>-    FunctionActivationPLoc,
-    ActivationScopePLoc,
-    ClosureVarPLoc
</del><ins>+    IndexedPropertyPLoc,
+    NamedPropertyPLoc,
+    PublicLengthPLoc,
+    StructurePLoc,
+    VectorLengthPLoc
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class PromotedLocationDescriptor {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -336,6 +336,7 @@
</span><span class="cx">     case StringReplace:
</span><span class="cx">     case GetRegExpObjectLastIndex:
</span><span class="cx">     case SetRegExpObjectLastIndex:
</span><ins>+    case RecordRegExpCachedResult:
</ins><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="cx">     case BottomValue:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx"> #include &quot;JSGeneratorFunction.h&quot;
</span><span class="cx"> #include &quot;JSLexicalEnvironment.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><ins>+#include &quot;RegExpConstructor.h&quot;
</ins><span class="cx"> #include &quot;ScopedArguments.h&quot;
</span><span class="cx"> #include &quot;ScratchRegisterAllocator.h&quot;
</span><span class="cx"> #include &quot;WriteBarrierBuffer.h&quot;
</span><span class="lines">@@ -77,27 +78,54 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::emitAllocateJSArray(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements)
</del><ins>+void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength)
</ins><span class="cx"> {
</span><del>-    ASSERT(hasUndecided(structure-&gt;indexingType()) || hasInt32(structure-&gt;indexingType()) || hasDouble(structure-&gt;indexingType()) || hasContiguous(structure-&gt;indexingType()));
</del><ins>+    IndexingType indexingType = structure-&gt;indexingType();
+    bool hasIndexingHeader = hasIndexedProperties(indexingType);
+
+    unsigned inlineCapacity = structure-&gt;inlineCapacity();
+    unsigned outOfLineCapacity = structure-&gt;outOfLineCapacity();
</ins><span class="cx">     
</span><span class="cx">     GPRTemporary scratch(this);
</span><span class="cx">     GPRTemporary scratch2(this);
</span><span class="cx">     GPRReg scratchGPR = scratch.gpr();
</span><span class="cx">     GPRReg scratch2GPR = scratch2.gpr();
</span><ins>+
+    ASSERT(vectorLength &gt;= numElements);
+    vectorLength = std::max(BASE_VECTOR_LEN, vectorLength);
</ins><span class="cx">     
</span><del>-    unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements);
-    
</del><span class="cx">     JITCompiler::JumpList slowCases;
</span><del>-    
-    slowCases.append(
-        emitAllocateBasicStorage(TrustedImm32(vectorLength * sizeof(JSValue) + sizeof(IndexingHeader)), storageGPR));
-    m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR);
-    emitAllocateJSObject&lt;JSArray&gt;(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
-    
-    m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
-    m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-    
</del><ins>+
+    size_t size = 0;
+    if (hasIndexingHeader)
+        size += vectorLength * sizeof(JSValue) + sizeof(IndexingHeader);
+    size += outOfLineCapacity * sizeof(JSValue);
+
+    if (size) {
+        slowCases.append(
+            emitAllocateBasicStorage(TrustedImm32(size), storageGPR));
+        if (hasIndexingHeader)
+            m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR);
+        else
+            m_jit.addPtr(TrustedImm32(sizeof(IndexingHeader)), storageGPR);
+    } else
+        m_jit.move(TrustedImmPtr(0), storageGPR);
+
+    size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
+    MarkedAllocator* allocatorPtr = &amp;m_jit.vm()-&gt;heap.allocatorForObjectWithoutDestructor(allocationSize);
+    m_jit.move(TrustedImmPtr(allocatorPtr), scratchGPR);
+    emitAllocateJSObject(resultGPR, scratchGPR, TrustedImmPtr(structure), storageGPR, scratch2GPR, slowCases);
+
+    if (hasIndexingHeader)
+        m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+
+    // I want a slow path that also loads out the storage pointer, and that's
+    // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
+    // of work for a very small piece of functionality. :-/
+    addSlowPathGenerator(std::make_unique&lt;CallArrayAllocatorSlowPathGenerator&gt;(
+        slowCases, this, operationNewRawObject, resultGPR, storageGPR,
+        structure, vectorLength));
+
</ins><span class="cx">     if (hasDouble(structure-&gt;indexingType()) &amp;&amp; numElements &lt; vectorLength) {
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         m_jit.move(TrustedImm64(bitwise_cast&lt;int64_t&gt;(PNaN)), scratchGPR);
</span><span class="lines">@@ -113,12 +141,8 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    // I want a slow path that also loads out the storage pointer, and that's
-    // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
-    // of work for a very small piece of functionality. :-/
-    addSlowPathGenerator(std::make_unique&lt;CallArrayAllocatorSlowPathGenerator&gt;(
-        slowCases, this, operationNewArrayWithSize, resultGPR, storageGPR,
-        structure, numElements));
</del><ins>+    if (hasIndexingHeader)
+        m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::emitGetLength(InlineCallFrame* inlineCallFrame, GPRReg lengthGPR, bool includeThis)
</span><span class="lines">@@ -7653,6 +7677,125 @@
</span><span class="cx">     jsValueResult(resultRegs, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileMaterializeNewObject(Node* node)
+{
+    Structure* structure = node-&gt;structureSet()[0];
+    ASSERT(m_jit.graph().varArgChild(node, 0)-&gt;dynamicCastConstant&lt;Structure*&gt;() == structure);
+
+    ObjectMaterializationData&amp; data = node-&gt;objectMaterializationData();
+        
+    IndexingType indexingType = structure-&gt;indexingType();
+    bool hasIndexingHeader = hasIndexedProperties(indexingType);
+    int32_t publicLength = 0;
+    int32_t vectorLength = 0;
+
+    if (hasIndexingHeader) {
+        for (unsigned i = data.m_properties.size(); i--;) {
+            Edge edge = m_jit.graph().varArgChild(node, 1 + i);
+            switch (data.m_properties[i].kind()) {
+            case PublicLengthPLoc:
+                publicLength = edge-&gt;asInt32();
+                break;
+            case VectorLengthPLoc:
+                vectorLength = edge-&gt;asInt32();
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+    GPRTemporary result(this);
+    GPRTemporary storage(this);
+    GPRReg resultGPR = result.gpr();
+    GPRReg storageGPR = storage.gpr();
+    
+    emitAllocateRawObject(resultGPR, structure, storageGPR, 0, vectorLength);
+    
+    m_jit.store32(
+        JITCompiler::TrustedImm32(publicLength),
+        JITCompiler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+
+    for (unsigned i = data.m_properties.size(); i--;) {
+        Edge edge = m_jit.graph().varArgChild(node, 1 + i);
+        PromotedLocationDescriptor descriptor = data.m_properties[i];
+        switch (descriptor.kind()) {
+        case IndexedPropertyPLoc: {
+            JSValueOperand value(this, edge);
+            m_jit.storeValue(
+                value.jsValueRegs(),
+                JITCompiler::Address(storageGPR, sizeof(EncodedJSValue) * descriptor.info()));
+            break;
+        }
+
+        case NamedPropertyPLoc: {
+            StringImpl* uid = m_jit.graph().identifiers()[descriptor.info()];
+            for (PropertyMapEntry entry : structure-&gt;getPropertiesConcurrently()) {
+                if (uid != entry.key)
+                    continue;
+
+                JSValueOperand value(this, edge);
+                GPRReg baseGPR = isInlineOffset(entry.offset) ? resultGPR : storageGPR;
+                m_jit.storeValue(
+                    value.jsValueRegs(),
+                    JITCompiler::Address(baseGPR, offsetRelativeToBase(entry.offset)));
+            }
+            break;
+        }
+            
+        default:
+            break;
+        }
+    }
+
+    cellResult(resultGPR, node);
+}
+
+void SpeculativeJIT::compileRecordRegExpCachedResult(Node* node)
+{
+    Edge constructorEdge = m_jit.graph().varArgChild(node, 0);
+    Edge regExpEdge = m_jit.graph().varArgChild(node, 1);
+    Edge stringEdge = m_jit.graph().varArgChild(node, 2);
+    Edge startEdge = m_jit.graph().varArgChild(node, 3);
+    Edge endEdge = m_jit.graph().varArgChild(node, 4);
+
+    SpeculateCellOperand constructor(this, constructorEdge);
+    SpeculateCellOperand regExp(this, regExpEdge);
+    SpeculateCellOperand string(this, stringEdge);
+    SpeculateInt32Operand start(this, startEdge);
+    SpeculateInt32Operand end(this, endEdge);
+
+    GPRReg constructorGPR = constructor.gpr();
+    GPRReg regExpGPR = regExp.gpr();
+    GPRReg stringGPR = string.gpr();
+    GPRReg startGPR = start.gpr();
+    GPRReg endGPR = end.gpr();
+
+    ptrdiff_t offset = RegExpConstructor::offsetOfCachedResult();
+
+    m_jit.storePtr(
+        regExpGPR,
+        JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfLastRegExp()));
+    m_jit.storePtr(
+        stringGPR,
+        JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfLastInput()));
+    m_jit.store32(
+        startGPR,
+        JITCompiler::Address(
+            constructorGPR,
+            offset + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)));
+    m_jit.store32(
+        endGPR,
+        JITCompiler::Address(
+            constructorGPR,
+            offset + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end)));
+    m_jit.store8(
+        TrustedImm32(0),
+        JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfReified()));
+
+    noResult(node);
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -2410,6 +2410,8 @@
</span><span class="cx">     void compileGetRegExpObjectLastIndex(Node*);
</span><span class="cx">     void compileSetRegExpObjectLastIndex(Node*);
</span><span class="cx">     void compileLazyJSConstant(Node*);
</span><ins>+    void compileMaterializeNewObject(Node*);
+    void compileRecordRegExpCachedResult(Node*);
</ins><span class="cx">     
</span><span class="cx">     void moveTrueTo(GPRReg);
</span><span class="cx">     void moveFalseTo(GPRReg);
</span><span class="lines">@@ -2525,7 +2527,7 @@
</span><span class="cx">         m_jit.storePtr(TrustedImmPtr(structure-&gt;classInfo()), MacroAssembler::Address(resultGPR, JSDestructibleObject::classInfoOffset()));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void emitAllocateJSArray(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements);
</del><ins>+    void emitAllocateRawObject(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements, unsigned vectorLength);
</ins><span class="cx">     
</span><span class="cx">     void emitGetLength(InlineCallFrame*, GPRReg lengthGPR, bool includeThis = false);
</span><span class="cx">     void emitGetLength(CodeOrigin, GPRReg lengthGPR, bool includeThis = false);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -3048,6 +3048,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><ins>+    case RecordRegExpCachedResult: {
+        compileRecordRegExpCachedResult(node);
+        break;
+    }
+        
</ins><span class="cx">     case ArrayPush: {
</span><span class="cx">         ASSERT(node-&gt;arrayMode().isJSArray());
</span><span class="cx">         
</span><span class="lines">@@ -3493,7 +3498,7 @@
</span><span class="cx">             GPRReg resultGPR = result.gpr();
</span><span class="cx">             GPRReg storageGPR = storage.gpr();
</span><span class="cx"> 
</span><del>-            emitAllocateJSArray(resultGPR, structure, storageGPR, numElements);
</del><ins>+            emitAllocateRawObject(resultGPR, structure, storageGPR, numElements, numElements);
</ins><span class="cx">             
</span><span class="cx">             // At this point, one way or another, resultGPR and storageGPR have pointers to
</span><span class="cx">             // the JSArray and the Butterfly, respectively.
</span><span class="lines">@@ -3729,7 +3734,7 @@
</span><span class="cx">             GPRReg resultGPR = result.gpr();
</span><span class="cx">             GPRReg storageGPR = storage.gpr();
</span><span class="cx"> 
</span><del>-            emitAllocateJSArray(resultGPR, globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
</del><ins>+            emitAllocateRawObject(resultGPR, globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements, numElements);
</ins><span class="cx">             
</span><span class="cx">             if (node-&gt;indexingType() == ArrayWithDouble) {
</span><span class="cx">                 JSValue* data = m_jit.codeBlock()-&gt;constantBuffer(node-&gt;startConstant());
</span><span class="lines">@@ -4980,7 +4985,10 @@
</span><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">         
</span><del>-        
</del><ins>+    case MaterializeNewObject:
+        compileMaterializeNewObject(node);
+        break;
+
</ins><span class="cx">     case Unreachable:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="lines">@@ -5007,7 +5015,6 @@
</span><span class="cx">     case PhantomCreateActivation:
</span><span class="cx">     case PutHint:
</span><span class="cx">     case CheckStructureImmediate:
</span><del>-    case MaterializeNewObject:
</del><span class="cx">     case MaterializeCreateActivation:
</span><span class="cx">     case PutStack:
</span><span class="cx">     case KillStack:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -3188,6 +3188,11 @@
</span><span class="cx">         compileSetRegExpObjectLastIndex(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+
+    case RecordRegExpCachedResult: {
+        compileRecordRegExpCachedResult(node);
+        break;
+    }
</ins><span class="cx">         
</span><span class="cx">     case ArrayPush: {
</span><span class="cx">         ASSERT(node-&gt;arrayMode().isJSArray());
</span><span class="lines">@@ -3559,7 +3564,7 @@
</span><span class="cx">             GPRReg resultGPR = result.gpr();
</span><span class="cx">             GPRReg storageGPR = storage.gpr();
</span><span class="cx"> 
</span><del>-            emitAllocateJSArray(resultGPR, structure, storageGPR, numElements);
</del><ins>+            emitAllocateRawObject(resultGPR, structure, storageGPR, numElements, numElements);
</ins><span class="cx">             
</span><span class="cx">             // At this point, one way or another, resultGPR and storageGPR have pointers to
</span><span class="cx">             // the JSArray and the Butterfly, respectively.
</span><span class="lines">@@ -3795,7 +3800,7 @@
</span><span class="cx">             GPRReg resultGPR = result.gpr();
</span><span class="cx">             GPRReg storageGPR = storage.gpr();
</span><span class="cx"> 
</span><del>-            emitAllocateJSArray(resultGPR, globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
</del><ins>+            emitAllocateRawObject(resultGPR, globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements, numElements);
</ins><span class="cx">             
</span><span class="cx">             DFG_ASSERT(m_jit.graph(), node, indexingType &amp; IsArray);
</span><span class="cx">             JSValue* data = m_jit.codeBlock()-&gt;constantBuffer(node-&gt;startConstant());
</span><span class="lines">@@ -4989,6 +4994,10 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case MaterializeNewObject:
+        compileMaterializeNewObject(node);
+        break;
+
</ins><span class="cx"> #if ENABLE(FTL_JIT)        
</span><span class="cx">     case CheckTierUpInLoop: {
</span><span class="cx">         MacroAssembler::Jump done = m_jit.branchAdd32(
</span><span class="lines">@@ -5079,7 +5088,6 @@
</span><span class="cx">     case GetMyArgumentByVal:
</span><span class="cx">     case PutHint:
</span><span class="cx">     case CheckStructureImmediate:
</span><del>-    case MaterializeNewObject:
</del><span class="cx">     case MaterializeCreateActivation:
</span><span class="cx">     case PutStack:
</span><span class="cx">     case KillStack:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -253,11 +253,19 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><ins>+            case PutById:
+            case PutByIdFlush:
+            case PutByIdDirect:
</ins><span class="cx">             case PutStructure: {
</span><span class="cx">                 considerBarrier(m_node-&gt;child1());
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-                
</del><ins>+
+            case RecordRegExpCachedResult: {
+                considerBarrier(m_graph.varArgChild(m_node, 0));
+                break;
+            }
+
</ins><span class="cx">             case PutClosureVar:
</span><span class="cx">             case PutToArguments:
</span><span class="cx">             case SetRegExpObjectLastIndex:
</span><span class="lines">@@ -266,13 +274,6 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><del>-            case PutById:
-            case PutByIdFlush:
-            case PutByIdDirect: {
-                considerBarrier(m_node-&gt;child1());
-                break;
-            }
-
</del><span class="cx">             case PutByOffset: {
</span><span class="cx">                 considerBarrier(m_node-&gt;child2(), m_node-&gt;child3());
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -36,11 +36,15 @@
</span><span class="cx"> #include &quot;DFGPredictionPropagationPhase.h&quot;
</span><span class="cx"> #include &quot;DFGVariableAccessDataDump.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;RegExpConstructor.h&quot;
+#include &quot;StringPrototype.h&quot;
</ins><span class="cx"> #include &lt;cstdlib&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><span class="cx"> class StrengthReductionPhase : public Phase {
</span><ins>+    static const bool verbose = false;
+    
</ins><span class="cx"> public:
</span><span class="cx">     StrengthReductionPhase(Graph&amp; graph)
</span><span class="cx">         : Phase(graph, &quot;strength reduction&quot;)
</span><span class="lines">@@ -331,11 +335,368 @@
</span><span class="cx">                 if (!!string) {
</span><span class="cx">                     m_graph.convertToConstant(m_node, jsNumber(string.length()));
</span><span class="cx">                     m_changed = true;
</span><ins>+                    break;
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case GetGlobalObject: {
+            if (JSObject* object = m_node-&gt;child1()-&gt;dynamicCastConstant&lt;JSObject*&gt;()) {
+                m_graph.convertToConstant(m_node, object-&gt;globalObject());
+                m_changed = true;
+                break;
+            }
+            break;
+        }
+
+        case RegExpExec:
+        case RegExpTest: {
+            JSGlobalObject* globalObject = m_node-&gt;child1()-&gt;dynamicCastConstant&lt;JSGlobalObject*&gt;();
+            if (!globalObject) {
+                if (verbose)
+                    dataLog(&quot;Giving up because no global object.\n&quot;);
+                break;
+            }
+
+            if (globalObject-&gt;isHavingABadTime()) {
+                if (verbose)
+                    dataLog(&quot;Giving up because bad time.\n&quot;);
+                break;
+            }
+
+            Node* regExpObjectNode = m_node-&gt;child2().node();
+            RegExp* regExp;
+            if (RegExpObject* regExpObject = regExpObjectNode-&gt;dynamicCastConstant&lt;RegExpObject*&gt;())
+                regExp = regExpObject-&gt;regExp();
+            else if (regExpObjectNode-&gt;op() == NewRegexp)
+                regExp = codeBlock()-&gt;regexp(regExpObjectNode-&gt;regexpIndex());
+            else {
+                if (verbose)
+                    dataLog(&quot;Giving up because the regexp is unknown.\n&quot;);
+                break;
+            }
+
+            Node* stringNode = m_node-&gt;child3().node();
+            
+            // NOTE: This mostly already protects us from having the compiler execute a regexp
+            // operation on a ginormous string by preventing us from getting our hands on ginormous
+            // strings in the first place.
+            String string = m_node-&gt;child3()-&gt;tryGetString(m_graph);
+            if (!string) {
+                if (verbose)
+                    dataLog(&quot;Giving up because the string is unknown.\n&quot;);
+                break;
+            }
+
+            FrozenValue* regExpFrozenValue = m_graph.freeze(regExp);
+
+            // Refuse to do things with regular expressions that have a ginormous number of
+            // subpatterns.
+            unsigned ginormousNumberOfSubPatterns = 1000;
+            if (regExp-&gt;numSubpatterns() &gt; ginormousNumberOfSubPatterns) {
+                if (verbose)
+                    dataLog(&quot;Giving up because of pattern limit.\n&quot;);
+                break;
+            }
+
+            unsigned lastIndex;
+            if (regExp-&gt;globalOrSticky()) {
+                // This will only work if we can prove what the value of lastIndex is. To do this
+                // safely, we need to execute the insertion set so that we see any previous strength
+                // reductions. This is needed for soundness since otherwise the effectfulness of any
+                // previous strength reductions would be invisible to us.
+                executeInsertionSet();
+                lastIndex = UINT_MAX;
+                for (unsigned otherNodeIndex = m_nodeIndex; otherNodeIndex--;) {
+                    Node* otherNode = m_block-&gt;at(otherNodeIndex);
+                    if (otherNode == regExpObjectNode) {
+                        lastIndex = 0;
+                        break;
+                    }
+                    if (otherNode-&gt;op() == SetRegExpObjectLastIndex
+                        &amp;&amp; otherNode-&gt;child1() == regExpObjectNode
+                        &amp;&amp; otherNode-&gt;child2()-&gt;isInt32Constant()
+                        &amp;&amp; otherNode-&gt;child2()-&gt;asInt32() &gt;= 0) {
+                        lastIndex = static_cast&lt;unsigned&gt;(otherNode-&gt;child2()-&gt;asInt32());
+                        break;
+                    }
+                    if (writesOverlap(m_graph, otherNode, RegExpObject_lastIndex))
+                        break;
+                }
+                if (lastIndex == UINT_MAX) {
+                    if (verbose)
+                        dataLog(&quot;Giving up because the last index is not known.\n&quot;);
+                    break;
+                }
+            } else
+                lastIndex = 0;
+
+            m_graph.watchpoints().addLazily(globalObject-&gt;havingABadTimeWatchpoint());
+            
+            Structure* structure = globalObject-&gt;regExpMatchesArrayStructure();
+            if (structure-&gt;indexingType() != ArrayWithContiguous) {
+                // This is further protection against a race with haveABadTime.
+                if (verbose)
+                    dataLog(&quot;Giving up because the structure has the wrong indexing type.\n&quot;);
+                break;
+            }
+            m_graph.registerStructure(structure);
+
+            RegExpConstructor* constructor = globalObject-&gt;regExpConstructor();
+            FrozenValue* constructorFrozenValue = m_graph.freeze(constructor);
+
+            MatchResult result;
+            Vector&lt;int, 32&gt; ovector;
+            // We have to call the kind of match function that the main thread would have called.
+            // Otherwise, we might not have the desired Yarr code compiled, and the match will fail.
+            if (m_node-&gt;op() == RegExpExec) {
+                int position;
+                if (!regExp-&gt;matchConcurrently(vm(), string, lastIndex, position, ovector)) {
+                    if (verbose)
+                        dataLog(&quot;Giving up because match failed.\n&quot;);
+                    break;
+                }
+                result.start = position;
+                result.end = ovector[1];
+            } else {
+                if (!regExp-&gt;matchConcurrently(vm(), string, lastIndex, result)) {
+                    if (verbose)
+                        dataLog(&quot;Giving up because match failed.\n&quot;);
+                    break;
+                }
+            }
+
+            // We've constant-folded the regexp. Now we're committed to replacing RegExpExec/Test.
+
+            m_changed = true;
+
+            NodeOrigin origin = m_node-&gt;origin;
+
+            m_insertionSet.insertNode(
+                m_nodeIndex, SpecNone, Check, origin, m_node-&gt;children.justChecks());
+
+            if (m_node-&gt;op() == RegExpExec) {
+                if (result) {
+                    StructureSet* structureSet = m_graph.addStructureSet(structure);
+
+                    // Create an array modeling the JS array that we will try to allocate. This is
+                    // basically createRegExpMatchesArray but over C++ strings instead of JSStrings.
+                    Vector&lt;String&gt; resultArray;
+                    resultArray.append(string.substring(result.start, result.end - result.start));
+                    for (unsigned i = 1; i &lt;= regExp-&gt;numSubpatterns(); ++i) {
+                        int start = ovector[2 * i];
+                        if (start &gt;= 0)
+                            resultArray.append(string.substring(start, ovector[2 * i + 1] - start));
+                        else
+                            resultArray.append(String());
+                    }
+
+                    unsigned publicLength = resultArray.size();
+                    unsigned vectorLength = std::max(BASE_VECTOR_LEN, publicLength);
+
+                    UniquedStringImpl* indexUID = vm().propertyNames-&gt;index.impl();
+                    UniquedStringImpl* inputUID = vm().propertyNames-&gt;input.impl();
+                    unsigned indexIndex = m_graph.identifiers().ensure(indexUID);
+                    unsigned inputIndex = m_graph.identifiers().ensure(inputUID);
+
+                    unsigned firstChild = m_graph.m_varArgChildren.size();
+                    m_graph.m_varArgChildren.append(
+                        m_insertionSet.insertConstantForUse(
+                            m_nodeIndex, origin, structure, KnownCellUse));
+                    ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
+            
+                    m_graph.m_varArgChildren.append(
+                        m_insertionSet.insertConstantForUse(
+                            m_nodeIndex, origin, jsNumber(publicLength), KnownInt32Use));
+                    data-&gt;m_properties.append(PublicLengthPLoc);
+            
+                    m_graph.m_varArgChildren.append(
+                        m_insertionSet.insertConstantForUse(
+                            m_nodeIndex, origin, jsNumber(vectorLength), KnownInt32Use));
+                    data-&gt;m_properties.append(VectorLengthPLoc);
+
+                    m_graph.m_varArgChildren.append(
+                        m_insertionSet.insertConstantForUse(
+                            m_nodeIndex, origin, jsNumber(result.start), UntypedUse));
+                    data-&gt;m_properties.append(
+                        PromotedLocationDescriptor(NamedPropertyPLoc, indexIndex));
+
+                    m_graph.m_varArgChildren.append(Edge(stringNode, UntypedUse));
+                    data-&gt;m_properties.append(
+                        PromotedLocationDescriptor(NamedPropertyPLoc, inputIndex));
+
+                    auto materializeString = [&amp;] (const String&amp; string) -&gt; Node* {
+                        if (string.isNull())
+                            return nullptr;
+                        if (string.isEmpty()) {
+                            return m_insertionSet.insertConstant(
+                                m_nodeIndex, origin, vm().smallStrings.emptyString());
+                        }
+                        LazyJSValue value = LazyJSValue::newString(m_graph, string);
+                        return m_insertionSet.insertNode(
+                            m_nodeIndex, SpecNone, LazyJSConstant, origin,
+                            OpInfo(m_graph.m_lazyJSValues.add(value)));
+                    };
+
+                    for (unsigned i = 0; i &lt; resultArray.size(); ++i) {
+                        if (Node* node = materializeString(resultArray[i])) {
+                            m_graph.m_varArgChildren.append(Edge(node, UntypedUse));
+                            data-&gt;m_properties.append(
+                                PromotedLocationDescriptor(IndexedPropertyPLoc, i));
+                        }
+                    }
+            
+                    Node* resultNode = m_insertionSet.insertNode(
+                        m_nodeIndex, SpecArray, Node::VarArg, MaterializeNewObject, origin,
+                        OpInfo(structureSet), OpInfo(data), firstChild,
+                        m_graph.m_varArgChildren.size() - firstChild);
+                
+                    m_node-&gt;convertToIdentityOn(resultNode);
+                } else
+                    m_graph.convertToConstant(m_node, jsNull());
+            } else
+                m_graph.convertToConstant(m_node, jsBoolean(!!result));
+
+            // Whether it's Exec or Test, we need to tell the constructor and RegExpObject what's up.
+            // Because SetRegExpObjectLastIndex may exit and it clobbers exit state, we do that
+            // first.
+            
+            if (regExp-&gt;globalOrSticky()) {
+                m_insertionSet.insertNode(
+                    m_nodeIndex, SpecNone, SetRegExpObjectLastIndex, origin,
+                    Edge(regExpObjectNode, RegExpObjectUse),
+                    m_insertionSet.insertConstantForUse(
+                        m_nodeIndex, origin, jsNumber(result ? result.end : 0), UntypedUse));
+                
+                origin = origin.withInvalidExit();
+            }
+
+            if (result) {
+                unsigned firstChild = m_graph.m_varArgChildren.size();
+                m_graph.m_varArgChildren.append(
+                    m_insertionSet.insertConstantForUse(
+                        m_nodeIndex, origin, constructorFrozenValue, KnownCellUse));
+                m_graph.m_varArgChildren.append(
+                    m_insertionSet.insertConstantForUse(
+                        m_nodeIndex, origin, regExpFrozenValue, KnownCellUse));
+                m_graph.m_varArgChildren.append(Edge(stringNode, KnownCellUse));
+                m_graph.m_varArgChildren.append(
+                    m_insertionSet.insertConstantForUse(
+                        m_nodeIndex, origin, jsNumber(result.start), KnownInt32Use));
+                m_graph.m_varArgChildren.append(
+                    m_insertionSet.insertConstantForUse(
+                        m_nodeIndex, origin, jsNumber(result.end), KnownInt32Use));
+                m_insertionSet.insertNode(
+                    m_nodeIndex, SpecNone, Node::VarArg, RecordRegExpCachedResult, origin,
+                    OpInfo(), OpInfo(), firstChild, m_graph.m_varArgChildren.size() - firstChild);
+
+                origin = origin.withInvalidExit();
+            }
+            
+            m_node-&gt;origin = origin;
+            break;
+        }
+
+        case StringReplace: {
+            Node* stringNode = m_node-&gt;child1().node();
+            String string = stringNode-&gt;tryGetString(m_graph);
+            if (!string)
+                break;
+            
+            Node* regExpObjectNode = m_node-&gt;child2().node();
+            RegExp* regExp;
+            if (RegExpObject* regExpObject = regExpObjectNode-&gt;dynamicCastConstant&lt;RegExpObject*&gt;())
+                regExp = regExpObject-&gt;regExp();
+            else if (regExpObjectNode-&gt;op() == NewRegexp)
+                regExp = codeBlock()-&gt;regexp(regExpObjectNode-&gt;regexpIndex());
+            else {
+                if (verbose)
+                    dataLog(&quot;Giving up because the regexp is unknown.\n&quot;);
+                break;
+            }
+
+            String replace = m_node-&gt;child3()-&gt;tryGetString(m_graph);
+            if (!string)
+                break;
+
+            StringBuilder builder;
+
+            unsigned lastIndex = 0;
+            unsigned startPosition = 0;
+            bool ok = true;
+            do {
+                MatchResult result;
+                Vector&lt;int, 32&gt; ovector;
+                // Model which version of match() is called by the main thread.
+                if (replace.isEmpty() &amp;&amp; regExp-&gt;global()) {
+                    if (!regExp-&gt;matchConcurrently(vm(), string, startPosition, result)) {
+                        ok = false;
+                        break;
+                    }
+                } else {
+                    int position;
+                    if (!regExp-&gt;matchConcurrently(vm(), string, startPosition, position, ovector)) {
+                        ok = false;
+                        break;
+                    }
+                    
+                    result.start = position;
+                    result.end = ovector[1];
+                }
+                
+                if (!result)
+                    break;
+
+                unsigned replLen = replace.length();
+                if (lastIndex &lt; result.start || replLen) {
+                    builder.append(string, lastIndex, result.start - lastIndex);
+                    if (replLen)
+                        builder.append(substituteBackreferences(replace, string, ovector.data(), regExp));
+                }
+
+                lastIndex = result.end;
+                startPosition = lastIndex;
+
+                // special case of empty match
+                if (result.empty()) {
+                    startPosition++;
+                    if (startPosition &gt; string.length())
+                        break;
+                }
+            } while (regExp-&gt;global());
+            if (!ok)
+                break;
+
+            // We are committed at this point.
+            m_changed = true;
+
+            NodeOrigin origin = m_node-&gt;origin;
+
+            if (regExp-&gt;global()) {
+                m_insertionSet.insertNode(
+                    m_nodeIndex, SpecNone, SetRegExpObjectLastIndex, origin,
+                    Edge(regExpObjectNode, RegExpObjectUse),
+                    m_insertionSet.insertConstantForUse(
+                        m_nodeIndex, origin, jsNumber(0), UntypedUse));
+                
+                origin = origin.withInvalidExit();
+            }
+
+            if (!lastIndex &amp;&amp; builder.isEmpty())
+                m_node-&gt;convertToIdentityOn(stringNode);
+            else {
+                if (lastIndex &lt; string.length())
+                    builder.append(string, lastIndex, string.length() - lastIndex);
+                
+                m_node-&gt;convertToLazyJSConstant(
+                    m_graph, LazyJSValue::newString(m_graph, builder.toString()));
+            }
+
+            m_node-&gt;origin = origin;
+            break;
+        }
+
</ins><span class="cx">         default:
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -380,6 +741,11 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
+    void executeInsertionSet()
+    {
+        m_nodeIndex += m_insertionSet.execute(m_block);
+    }
</ins><span class="cx">     
</span><span class="cx">     InsertionSet m_insertionSet;
</span><span class="cx">     BasicBlock* m_block;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -281,6 +281,18 @@
</span><span class="cx">                         VALIDATE((node), !variant.oldStructureForTransition()-&gt;dfgShouldWatch());
</span><span class="cx">                     }
</span><span class="cx">                     break;
</span><ins>+                case MaterializeNewObject:
+                    for (Structure* structure : node-&gt;structureSet()) {
+                        // This only supports structures that are JSFinalObject or JSArray.
+                        VALIDATE(
+                            (node),
+                            structure-&gt;classInfo() == JSFinalObject::info()
+                            || structure-&gt;classInfo() == JSArray::info());
+
+                        // We only support certain indexing shapes.
+                        VALIDATE((node), !hasAnyArrayStorage(structure-&gt;indexingType()));
+                    }
+                    break;
</ins><span class="cx">                 case DoubleConstant:
</span><span class="cx">                 case Int52Constant:
</span><span class="cx">                     VALIDATE((node), node-&gt;isNumberConstant());
</span><span class="lines">@@ -505,13 +517,42 @@
</span><span class="cx">                 case GetMyArgumentByVal:
</span><span class="cx">                 case PutHint:
</span><span class="cx">                 case CheckStructureImmediate:
</span><del>-                case MaterializeNewObject:
</del><span class="cx">                 case MaterializeCreateActivation:
</span><span class="cx">                 case PutStack:
</span><span class="cx">                 case KillStack:
</span><span class="cx">                 case GetStack:
</span><span class="cx">                     VALIDATE((node), !&quot;unexpected node type in CPS&quot;);
</span><span class="cx">                     break;
</span><ins>+                case MaterializeNewObject: {
+                    // CPS only allows array lengths to be constant. This constraint only exists
+                    // because we don't have DFG support for anything more and we don't need any
+                    // other kind of support for now.
+                    ObjectMaterializationData&amp; data = node-&gt;objectMaterializationData();
+                    for (unsigned i = data.m_properties.size(); i--;) {
+                        PromotedLocationDescriptor descriptor = data.m_properties[i];
+                        Edge edge = m_graph.varArgChild(node, 1 + i);
+                        switch (descriptor.kind()) {
+                        case PublicLengthPLoc:
+                        case VectorLengthPLoc:
+                            VALIDATE((node, edge), edge-&gt;isInt32Constant());
+                            break;
+                        default:
+                            break;
+                        }
+                    }
+
+                    // CPS only allows one structure.
+                    VALIDATE((node), node-&gt;structureSet().size() == 1);
+
+                    // CPS disallows int32 and double arrays. Those require weird type checks and
+                    // conversions. They are not needed in the DFG right now. We should add support
+                    // for these if the DFG ever needs it.
+                    for (Structure* structure : node-&gt;structureSet()) {
+                        VALIDATE((node), !hasInt32(structure-&gt;indexingType()));
+                        VALIDATE((node), !hasDouble(structure-&gt;indexingType()));
+                    }
+                    break;
+                }
</ins><span class="cx">                 case Phantom:
</span><span class="cx">                     VALIDATE((node), m_graph.m_fixpointState != FixpointNotConverged);
</span><span class="cx">                     break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include &quot;JSPropertyNameEnumerator.h&quot;
</span><span class="cx"> #include &quot;JSScope.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;RegExpConstructor.h&quot;
</ins><span class="cx"> #include &quot;RegExpObject.h&quot;
</span><span class="cx"> #include &quot;ScopedArguments.h&quot;
</span><span class="cx"> #include &quot;ScopedArgumentsTable.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -77,6 +77,11 @@
</span><span class="cx">     macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \
</span><span class="cx">     macro(JSWrapperObject_internalValue, JSWrapperObject::internalValueOffset()) \
</span><span class="cx">     macro(MarkedAllocator_freeListHead, MarkedAllocator::offsetOfFreeListHead()) \
</span><ins>+    macro(RegExpConstructor_cachedResult_lastRegExp, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastRegExp()) \
+    macro(RegExpConstructor_cachedResult_lastInput, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastInput()) \
+    macro(RegExpConstructor_cachedResult_result_start, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)) \
+    macro(RegExpConstructor_cachedResult_result_end, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end)) \
+    macro(RegExpConstructor_cachedResult_reified, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfReified()) \
</ins><span class="cx">     macro(RegExpObject_lastIndex, RegExpObject::offsetOfLastIndex()) \
</span><span class="cx">     macro(RegExpObject_lastIndexIsWritable, RegExpObject::offsetOfLastIndexIsWritable()) \
</span><span class="cx">     macro(ScopedArguments_overrodeThings, ScopedArguments::offsetOfOverrodeThings()) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -228,6 +228,7 @@
</span><span class="cx">     case StringReplace:
</span><span class="cx">     case GetRegExpObjectLastIndex:
</span><span class="cx">     case SetRegExpObjectLastIndex:
</span><ins>+    case RecordRegExpCachedResult:
</ins><span class="cx">     case SetFunctionName:
</span><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -941,6 +941,9 @@
</span><span class="cx">         case SetRegExpObjectLastIndex:
</span><span class="cx">             compileSetRegExpObjectLastIndex();
</span><span class="cx">             break;
</span><ins>+        case RecordRegExpCachedResult:
+            compileRecordRegExpCachedResult();
+            break;
</ins><span class="cx"> 
</span><span class="cx">         case PhantomLocal:
</span><span class="cx">         case LoopHint:
</span><span class="lines">@@ -3724,33 +3727,9 @@
</span><span class="cx">             
</span><span class="cx">             m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
</span><span class="cx">             m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
</span><ins>+
+            initializeArrayElements(m_node-&gt;indexingType(), vectorLength, butterfly);
</ins><span class="cx">             
</span><del>-            if (hasDouble(m_node-&gt;indexingType())) {
-                LBasicBlock initLoop = m_out.newBlock();
-                LBasicBlock initDone = m_out.newBlock();
-                
-                ValueFromBlock originalIndex = m_out.anchor(vectorLength);
-                ValueFromBlock originalPointer = m_out.anchor(butterfly);
-                m_out.branch(
-                    m_out.notZero32(vectorLength), unsure(initLoop), unsure(initDone));
-                
-                LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone);
-                LValue index = m_out.phi(m_out.int32, originalIndex);
-                LValue pointer = m_out.phi(m_out.intPtr, originalPointer);
-                
-                m_out.store64(
-                    m_out.constInt64(bitwise_cast&lt;int64_t&gt;(PNaN)),
-                    TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer));
-                
-                LValue nextIndex = m_out.sub(index, m_out.int32One);
-                m_out.addIncomingToPhi(index, m_out.anchor(nextIndex));
-                m_out.addIncomingToPhi(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
-                m_out.branch(
-                    m_out.notZero32(nextIndex), unsure(initLoop), unsure(initDone));
-                
-                m_out.appendTo(initDone, initLastNext);
-            }
-            
</del><span class="cx">             ValueFromBlock fastResult = m_out.anchor(object);
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx">             
</span><span class="lines">@@ -6294,11 +6273,21 @@
</span><span class="cx">         // Lower the values first, to avoid creating values inside a control flow diamond.
</span><span class="cx">         
</span><span class="cx">         Vector&lt;LValue, 8&gt; values;
</span><del>-        for (unsigned i = 0; i &lt; data.m_properties.size(); ++i)
-            values.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
</del><ins>+        for (unsigned i = 0; i &lt; data.m_properties.size(); ++i) {
+            Edge edge = m_graph.varArgChild(m_node, 1 + i);
+            switch (data.m_properties[i].kind()) {
+            case PublicLengthPLoc:
+            case VectorLengthPLoc:
+                values.append(lowInt32(edge));
+                break;
+            default:
+                values.append(lowJSValue(edge));
+                break;
+            }
+        }
</ins><span class="cx">         
</span><span class="cx">         const StructureSet&amp; set = m_node-&gt;structureSet();
</span><del>-        
</del><ins>+
</ins><span class="cx">         Vector&lt;LBasicBlock, 1&gt; blocks(set.size());
</span><span class="cx">         for (unsigned i = set.size(); i--;)
</span><span class="cx">             blocks[i] = m_out.newBlock();
</span><span class="lines">@@ -6323,21 +6312,51 @@
</span><span class="cx">             LValue object;
</span><span class="cx">             LValue butterfly;
</span><span class="cx">             
</span><del>-            if (structure-&gt;outOfLineCapacity()) {
</del><ins>+            if (structure-&gt;outOfLineCapacity() || hasIndexedProperties(structure-&gt;indexingType())) {
</ins><span class="cx">                 size_t allocationSize = JSFinalObject::allocationSize(structure-&gt;inlineCapacity());
</span><span class="cx">                 MarkedAllocator* allocator = &amp;vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
</span><ins>+
+                bool hasIndexingHeader = hasIndexedProperties(structure-&gt;indexingType());
+                unsigned indexingHeaderSize = 0;
+                LValue indexingPayloadSizeInBytes = m_out.intPtrZero;
+                LValue vectorLength = m_out.int32Zero;
+                LValue publicLength = m_out.int32Zero;
+                if (hasIndexingHeader) {
+                    indexingHeaderSize = sizeof(IndexingHeader);
+                    for (unsigned i = data.m_properties.size(); i--;) {
+                        PromotedLocationDescriptor descriptor = data.m_properties[i];
+                        switch (descriptor.kind()) {
+                        case PublicLengthPLoc:
+                            publicLength = values[i];
+                            break;
+                        case VectorLengthPLoc:
+                            vectorLength = values[i];
+                            break;
+                        default:
+                            break;
+                        }
+                    }
+                    indexingPayloadSizeInBytes =
+                        m_out.mul(m_out.zeroExtPtr(vectorLength), m_out.intPtrEight);
+                }
+
+                LValue butterflySize = m_out.add(
+                    m_out.constIntPtr(
+                        structure-&gt;outOfLineCapacity() * sizeof(JSValue) + indexingHeaderSize),
+                    indexingPayloadSizeInBytes);
</ins><span class="cx">                 
</span><span class="cx">                 LBasicBlock slowPath = m_out.newBlock();
</span><span class="cx">                 LBasicBlock continuation = m_out.newBlock();
</span><span class="cx">                 
</span><span class="cx">                 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
</span><span class="cx">                 
</span><del>-                LValue endOfStorage = allocateBasicStorageAndGetEnd(
-                    m_out.constIntPtr(structure-&gt;outOfLineCapacity() * sizeof(JSValue)),
-                    slowPath);
-                
</del><ins>+                LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, slowPath);
+
</ins><span class="cx">                 LValue fastButterflyValue = m_out.add(
</span><del>-                    m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage);
</del><ins>+                    m_out.sub(endOfStorage, indexingPayloadSizeInBytes),
+                    m_out.constIntPtr(sizeof(IndexingHeader) - indexingHeaderSize));
+
+                m_out.store32(vectorLength, fastButterflyValue, m_heaps.Butterfly_vectorLength);
</ins><span class="cx">                 
</span><span class="cx">                 LValue fastObjectValue = allocateObject(
</span><span class="cx">                     m_out.constIntPtr(allocator), structure, fastButterflyValue, slowPath);
</span><span class="lines">@@ -6348,12 +6367,24 @@
</span><span class="cx">                 
</span><span class="cx">                 m_out.appendTo(slowPath, continuation);
</span><span class="cx"> 
</span><del>-                LValue slowObjectValue = lazySlowPath(
-                    [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
-                        return createLazyCallGenerator(
-                            operationNewObjectWithButterfly, locations[0].directGPR(),
-                            CCallHelpers::TrustedImmPtr(structure));
-                    });
</del><ins>+                LValue slowObjectValue;
+                if (hasIndexingHeader) {
+                    slowObjectValue = lazySlowPath(
+                        [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
+                            return createLazyCallGenerator(
+                                operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength,
+                                locations[0].directGPR(), CCallHelpers::TrustedImmPtr(structure),
+                                locations[1].directGPR());
+                        },
+                        vectorLength);
+                } else {
+                    slowObjectValue = lazySlowPath(
+                        [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
+                            return createLazyCallGenerator(
+                                operationNewObjectWithButterfly, locations[0].directGPR(),
+                                CCallHelpers::TrustedImmPtr(structure));
+                        });
+                }
</ins><span class="cx">                 ValueFromBlock slowObject = m_out.anchor(slowObjectValue);
</span><span class="cx">                 ValueFromBlock slowButterfly = m_out.anchor(
</span><span class="cx">                     m_out.loadPtr(slowObjectValue, m_heaps.JSObject_butterfly));
</span><span class="lines">@@ -6364,6 +6395,111 @@
</span><span class="cx">                 
</span><span class="cx">                 object = m_out.phi(m_out.intPtr, fastObject, slowObject);
</span><span class="cx">                 butterfly = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
</span><ins>+
+                m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
+
+                initializeArrayElements(structure-&gt;indexingType(), vectorLength, butterfly);
+
+                HashMap&lt;int32_t, LValue, DefaultHash&lt;int32_t&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;int32_t&gt;&gt; indexMap;
+                Vector&lt;int32_t&gt; indices;
+                for (unsigned i = data.m_properties.size(); i--;) {
+                    PromotedLocationDescriptor descriptor = data.m_properties[i];
+                    if (descriptor.kind() != IndexedPropertyPLoc)
+                        continue;
+                    int32_t index = static_cast&lt;int32_t&gt;(descriptor.info());
+                    
+                    auto result = indexMap.add(index, values[i]);
+                    DFG_ASSERT(m_graph, m_node, result); // Duplicates are illegal.
+
+                    indices.append(index);
+                }
+
+                if (!indices.isEmpty()) {
+                    std::sort(indices.begin(), indices.end());
+                    
+                    Vector&lt;LBasicBlock&gt; blocksWithStores(indices.size());
+                    Vector&lt;LBasicBlock&gt; blocksWithChecks(indices.size());
+                    
+                    for (unsigned i = indices.size(); i--;) {
+                        blocksWithStores[i] = m_out.newBlock();
+                        blocksWithChecks[i] = m_out.newBlock(); // blocksWithChecks[0] is the continuation.
+                    }
+
+                    LBasicBlock indexLastNext = m_out.m_nextBlock;
+                    
+                    for (unsigned i = indices.size(); i--;) {
+                        int32_t index = indices[i];
+                        LValue value = indexMap.get(index);
+                        
+                        m_out.branch(
+                            m_out.below(m_out.constInt32(index), publicLength),
+                            unsure(blocksWithStores[i]), unsure(blocksWithChecks[i]));
+
+                        m_out.appendTo(blocksWithStores[i], blocksWithChecks[i]);
+
+                        // This has to type-check and convert its inputs, but it cannot do so in a
+                        // way that updates AI. That's a bit annoying, but if you think about how
+                        // sinking works, it's actually not a bad thing. We are virtually guaranteed
+                        // that these type checks will not fail, since the type checks that guarded
+                        // the original stores to the array are still somewhere above this point.
+                        Output::StoreType storeType;
+                        IndexedAbstractHeap* heap;
+                        switch (structure-&gt;indexingType()) {
+                        case ALL_INT32_INDEXING_TYPES:
+                            // FIXME: This could use the proven type if we had the Edge for the
+                            // value. https://bugs.webkit.org/show_bug.cgi?id=155311
+                            speculate(BadType, noValue(), nullptr, isNotInt32(value));
+                            storeType = Output::Store64;
+                            heap = &amp;m_heaps.indexedInt32Properties;
+                            break;
+
+                        case ALL_DOUBLE_INDEXING_TYPES: {
+                            // FIXME: If the source is ValueRep, we should avoid emitting any
+                            // checks. We could also avoid emitting checks if we had the Edge of
+                            // this value. https://bugs.webkit.org/show_bug.cgi?id=155311
+
+                            LBasicBlock intCase = m_out.newBlock();
+                            LBasicBlock doubleCase = m_out.newBlock();
+                            LBasicBlock continuation = m_out.newBlock();
+
+                            m_out.branch(isInt32(value), unsure(intCase), unsure(doubleCase));
+
+                            LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
+
+                            ValueFromBlock intResult =
+                                m_out.anchor(m_out.intToDouble(unboxInt32(value)));
+                            m_out.jump(continuation);
+
+                            m_out.appendTo(doubleCase, continuation);
+
+                            speculate(BadType, noValue(), nullptr, isNumber(value));
+                            ValueFromBlock doubleResult = m_out.anchor(unboxDouble(value));
+                            m_out.jump(continuation);
+
+                            m_out.appendTo(continuation, lastNext);
+                            value = m_out.phi(Double, intResult, doubleResult);
+                            storeType = Output::StoreDouble;
+                            heap = &amp;m_heaps.indexedDoubleProperties;
+                            break;
+                        }
+
+                        case ALL_CONTIGUOUS_INDEXING_TYPES:
+                            storeType = Output::Store64;
+                            heap = &amp;m_heaps.indexedContiguousProperties;
+                            break;
+
+                        default:
+                            DFG_CRASH(m_graph, m_node, &quot;Invalid indexing type&quot;);
+                            break;
+                        }
+                        
+                        m_out.store(value, m_out.address(butterfly, heap-&gt;at(index)), storeType);
+
+                        m_out.jump(blocksWithChecks[i]);
+                        m_out.appendTo(
+                            blocksWithChecks[i], i ? blocksWithStores[i - 1] : indexLastNext);
+                    }
+                }
</ins><span class="cx">             } else {
</span><span class="cx">                 // In the easy case where we can do a one-shot allocation, we simply allocate the
</span><span class="cx">                 // object to directly have the desired structure.
</span><span class="lines">@@ -6373,12 +6509,14 @@
</span><span class="cx">             
</span><span class="cx">             for (PropertyMapEntry entry : structure-&gt;getPropertiesConcurrently()) {
</span><span class="cx">                 for (unsigned i = data.m_properties.size(); i--;) {
</span><del>-                    PhantomPropertyValue value = data.m_properties[i];
-                    if (m_graph.identifiers()[value.m_identifierNumber] != entry.key)
</del><ins>+                    PromotedLocationDescriptor descriptor = data.m_properties[i];
+                    if (descriptor.kind() != NamedPropertyPLoc)
</ins><span class="cx">                         continue;
</span><ins>+                    if (m_graph.identifiers()[descriptor.info()] != entry.key)
+                        continue;
</ins><span class="cx">                     
</span><span class="cx">                     LValue base = isInlineOffset(entry.offset) ? object : butterfly;
</span><del>-                    storeProperty(values[i], base, value.m_identifierNumber, entry.offset);
</del><ins>+                    storeProperty(values[i], base, descriptor.info(), entry.offset);
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="lines">@@ -6443,9 +6581,11 @@
</span><span class="cx">         LValue activation = m_out.phi(m_out.intPtr, fastResult, slowResult);
</span><span class="cx">         RELEASE_ASSERT(data.m_properties.size() == table-&gt;scopeSize());
</span><span class="cx">         for (unsigned i = 0; i &lt; data.m_properties.size(); ++i) {
</span><del>-            m_out.store64(values[i],
-                activation,
-                m_heaps.JSEnvironmentRecord_variables[data.m_properties[i].m_identifierNumber]);
</del><ins>+            PromotedLocationDescriptor descriptor = data.m_properties[i];
+            ASSERT(descriptor.kind() == ClosureVarPLoc);
+            m_out.store64(
+                values[i], activation,
+                m_heaps.JSEnvironmentRecord_variables[descriptor.info()]);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (validationEnabled()) {
</span><span class="lines">@@ -6454,7 +6594,9 @@
</span><span class="cx">             for (auto iter = table-&gt;begin(locker), end = table-&gt;end(locker); iter != end; ++iter) {
</span><span class="cx">                 bool found = false;
</span><span class="cx">                 for (unsigned i = 0; i &lt; data.m_properties.size(); ++i) {
</span><del>-                    if (iter-&gt;value.scopeOffset().offset() == data.m_properties[i].m_identifierNumber) {
</del><ins>+                    PromotedLocationDescriptor descriptor = data.m_properties[i];
+                    ASSERT(descriptor.kind() == ClosureVarPLoc);
+                    if (iter-&gt;value.scopeOffset().offset() == descriptor.info()) {
</ins><span class="cx">                         found = true;
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="lines">@@ -6627,6 +6769,29 @@
</span><span class="cx">         m_out.store64(value, regExp, m_heaps.RegExpObject_lastIndex);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void compileRecordRegExpCachedResult()
+    {
+        Edge constructorEdge = m_graph.varArgChild(m_node, 0);
+        Edge regExpEdge = m_graph.varArgChild(m_node, 1);
+        Edge stringEdge = m_graph.varArgChild(m_node, 2);
+        Edge startEdge = m_graph.varArgChild(m_node, 3);
+        Edge endEdge = m_graph.varArgChild(m_node, 4);
+        
+        LValue constructor = lowCell(constructorEdge);
+        LValue regExp = lowCell(regExpEdge);
+        LValue string = lowCell(stringEdge);
+        LValue start = lowInt32(startEdge);
+        LValue end = lowInt32(endEdge);
+
+        m_out.storePtr(regExp, constructor, m_heaps.RegExpConstructor_cachedResult_lastRegExp);
+        m_out.storePtr(string, constructor, m_heaps.RegExpConstructor_cachedResult_lastInput);
+        m_out.store32(start, constructor, m_heaps.RegExpConstructor_cachedResult_result_start);
+        m_out.store32(end, constructor, m_heaps.RegExpConstructor_cachedResult_result_end);
+        m_out.store32As8(
+            m_out.constInt32(0),
+            m_out.address(constructor, m_heaps.RegExpConstructor_cachedResult_reified));
+    }
+
</ins><span class="cx">     LValue didOverflowStack()
</span><span class="cx">     {
</span><span class="cx">         // This does a very simple leaf function analysis. The invariant of FTL call
</span><span class="lines">@@ -6984,6 +7149,39 @@
</span><span class="cx">         
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><ins>+
+    void initializeArrayElements(IndexingType indexingType, LValue vectorLength, LValue butterfly)
+    {
+        if (!hasDouble(indexingType)) {
+            // The GC already initialized everything to JSValue() for us.
+            return;
+        }
+
+        // Doubles must be initialized to PNaN.
+        LBasicBlock initLoop = m_out.newBlock();
+        LBasicBlock initDone = m_out.newBlock();
+        
+        ValueFromBlock originalIndex = m_out.anchor(vectorLength);
+        ValueFromBlock originalPointer = m_out.anchor(butterfly);
+        m_out.branch(
+            m_out.notZero32(vectorLength), unsure(initLoop), unsure(initDone));
+        
+        LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone);
+        LValue index = m_out.phi(m_out.int32, originalIndex);
+        LValue pointer = m_out.phi(m_out.intPtr, originalPointer);
+        
+        m_out.store64(
+            m_out.constInt64(bitwise_cast&lt;int64_t&gt;(PNaN)),
+            TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer));
+        
+        LValue nextIndex = m_out.sub(index, m_out.int32One);
+        m_out.addIncomingToPhi(index, m_out.anchor(nextIndex));
+        m_out.addIncomingToPhi(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
+        m_out.branch(
+            m_out.notZero32(nextIndex), unsure(initLoop), unsure(initDone));
+        
+        m_out.appendTo(initDone, initLastNext);
+    }
</ins><span class="cx">     
</span><span class="cx">     LValue allocatePropertyStorage(LValue object, Structure* previousStructure)
</span><span class="cx">     {
</span><span class="lines">@@ -9167,7 +9365,7 @@
</span><span class="cx">             return proven;
</span><span class="cx">         return m_out.testNonZero64(jsValue, m_tagTypeNumber);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     LValue unboxDouble(LValue jsValue)
</span><span class="cx">     {
</span><span class="cx">         return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -41,19 +41,6 @@
</span><span class="cx"> 
</span><span class="cx"> using namespace JSC::DFG;
</span><span class="cx"> 
</span><del>-extern &quot;C&quot; JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure)
-{
-    VM&amp; vm = exec-&gt;vm();
-    NativeCallFrameTracer tracer(&amp;vm, exec);
-    
-    Butterfly* butterfly = Butterfly::create(
-        vm, nullptr, 0, structure-&gt;outOfLineCapacity(), false, IndexingHeader(), 0);
-    
-    JSObject* result = JSFinalObject::create(exec, structure, butterfly);
-    result-&gt;butterfly(); // Ensure that the butterfly is in to-space.
-    return result;
-}
-
</del><span class="cx"> extern &quot;C&quot; void JIT_OPERATION operationPopulateObjectInOSR(
</span><span class="cx">     ExecState* exec, ExitTimeObjectMaterialization* materialization,
</span><span class="cx">     EncodedJSValue* encodedValue, EncodedJSValue* values)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOperations.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOperations.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/ftl/FTLOperations.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -37,8 +37,6 @@
</span><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; {
</span><span class="cx"> 
</span><del>-JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState*, Structure*) WTF_INTERNAL;
-
</del><span class="cx"> JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
</span><span class="cx">     ExecState*, ExitTimeObjectMaterialization*, EncodedJSValue*) WTF_INTERNAL;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorContentSearchUtilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;InspectorValues.h&quot;
</span><span class="cx"> #include &quot;RegularExpression.h&quot;
</span><span class="cx"> #include &quot;Yarr.h&quot;
</span><ins>+#include &quot;YarrInterpreter.h&quot;
</ins><span class="cx"> #include &lt;wtf/BumpPointerAllocator.h&gt;
</span><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -97,6 +97,10 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef JSCell Base;
</span><span class="cx"> 
</span><ins>+    // This is a super dangerous method for JITs. Sometimes the JITs will want to create either a
+    // JSFinalObject or a JSArray. This is the method that will do that.
+    static JSObject* createRawObject(ExecState* exec, Structure* structure, Butterfly* = nullptr);
+
</ins><span class="cx">     JS_EXPORT_PRIVATE static size_t estimatedSize(JSCell*);
</span><span class="cx">     JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx">     JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&amp;, CopyToken);
</span><span class="lines">@@ -1041,6 +1045,20 @@
</span><span class="cx"> 
</span><span class="cx"> JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectPrivateFuncInstanceOf(ExecState*);
</span><span class="cx"> 
</span><ins>+inline JSObject* JSObject::createRawObject(
+    ExecState* exec, Structure* structure, Butterfly* butterfly)
+{
+    JSObject* finalObject = new (
+        NotNull, 
+        allocateCell&lt;JSFinalObject&gt;(
+            *exec-&gt;heap(),
+            JSFinalObject::allocationSize(structure-&gt;inlineCapacity())
+        )
+    ) JSObject(exec-&gt;vm(), structure, butterfly);
+    finalObject-&gt;finishCreation(exec-&gt;vm());
+    return finalObject;
+}
+
</ins><span class="cx"> inline JSFinalObject* JSFinalObject::create(
</span><span class="cx">     ExecState* exec, Structure* structure, Butterfly* butterfly)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExp.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExp.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/RegExp.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -262,6 +262,8 @@
</span><span class="cx"> 
</span><span class="cx"> void RegExp::compile(VM* vm, Yarr::YarrCharSize charSize)
</span><span class="cx"> {
</span><ins>+    ConcurrentJITLocker locker(m_lock);
+    
</ins><span class="cx">     Yarr::YarrPattern pattern(m_patternString, m_flags, &amp;m_constructionError);
</span><span class="cx">     if (m_constructionError) {
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -291,7 +293,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     m_state = ByteCode;
</span><del>-    m_regExpBytecode = Yarr::byteCompile(pattern, &amp;vm-&gt;m_regExpAllocator);
</del><ins>+    m_regExpBytecode = Yarr::byteCompile(pattern, &amp;vm-&gt;m_regExpAllocator, &amp;vm-&gt;m_regExpAllocatorLock);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> int RegExp::match(VM&amp; vm, const String&amp; s, unsigned startOffset, Vector&lt;int, 32&gt;&amp; ovector)
</span><span class="lines">@@ -299,8 +301,22 @@
</span><span class="cx">     return matchInline(vm, s, startOffset, ovector);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool RegExp::matchConcurrently(
+    VM&amp; vm, const String&amp; s, unsigned startOffset, int&amp; position, Vector&lt;int, 32&gt;&amp; ovector)
+{
+    ConcurrentJITLocker locker(m_lock);
+
+    if (!hasCodeFor(s.is8Bit() ? Yarr::Char8 : Yarr::Char16))
+        return false;
+
+    position = match(vm, s, startOffset, ovector);
+    return true;
+}
+
</ins><span class="cx"> void RegExp::compileMatchOnly(VM* vm, Yarr::YarrCharSize charSize)
</span><span class="cx"> {
</span><ins>+    ConcurrentJITLocker locker(m_lock);
+    
</ins><span class="cx">     Yarr::YarrPattern pattern(m_patternString, m_flags, &amp;m_constructionError);
</span><span class="cx">     if (m_constructionError) {
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -330,7 +346,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     m_state = ByteCode;
</span><del>-    m_regExpBytecode = Yarr::byteCompile(pattern, &amp;vm-&gt;m_regExpAllocator);
</del><ins>+    m_regExpBytecode = Yarr::byteCompile(pattern, &amp;vm-&gt;m_regExpAllocator, &amp;vm-&gt;m_regExpAllocatorLock);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MatchResult RegExp::match(VM&amp; vm, const String&amp; s, unsigned startOffset)
</span><span class="lines">@@ -338,8 +354,21 @@
</span><span class="cx">     return matchInline(vm, s, startOffset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool RegExp::matchConcurrently(VM&amp; vm, const String&amp; s, unsigned startOffset, MatchResult&amp; result)
+{
+    ConcurrentJITLocker locker(m_lock);
+
+    if (!hasMatchOnlyCodeFor(s.is8Bit() ? Yarr::Char8 : Yarr::Char16))
+        return false;
+
+    result = match(vm, s, startOffset);
+    return true;
+}
+
</ins><span class="cx"> void RegExp::deleteCode()
</span><span class="cx"> {
</span><ins>+    ConcurrentJITLocker locker(m_lock);
+    
</ins><span class="cx">     if (!hasCode())
</span><span class="cx">         return;
</span><span class="cx">     m_state = NotCompiled;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExp.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExp.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/RegExp.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -22,6 +22,7 @@
</span><span class="cx"> #ifndef RegExp_h
</span><span class="cx"> #define RegExp_h
</span><span class="cx"> 
</span><ins>+#include &quot;ConcurrentJITLock.h&quot;
</ins><span class="cx"> #include &quot;ExecutableAllocator.h&quot;
</span><span class="cx"> #include &quot;MatchResult.h&quot;
</span><span class="cx"> #include &quot;RegExpKey.h&quot;
</span><span class="lines">@@ -56,6 +57,7 @@
</span><span class="cx">     bool ignoreCase() const { return m_flags &amp; FlagIgnoreCase; }
</span><span class="cx">     bool multiline() const { return m_flags &amp; FlagMultiline; }
</span><span class="cx">     bool sticky() const { return m_flags &amp; FlagSticky; }
</span><ins>+    bool globalOrSticky() const { return global() || sticky(); }
</ins><span class="cx">     bool unicode() const { return m_flags &amp; FlagUnicode; }
</span><span class="cx"> 
</span><span class="cx">     const String&amp; pattern() const { return m_patternString; }
</span><span class="lines">@@ -64,8 +66,14 @@
</span><span class="cx">     const char* errorMessage() const { return m_constructionError; }
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE int match(VM&amp;, const String&amp;, unsigned startOffset, Vector&lt;int, 32&gt;&amp; ovector);
</span><ins>+
+    // Returns false if we couldn't run the regular expression for any reason.
+    bool matchConcurrently(VM&amp;, const String&amp;, unsigned startOffset, int&amp; position, Vector&lt;int, 32&gt;&amp; ovector);
+    
</ins><span class="cx">     JS_EXPORT_PRIVATE MatchResult match(VM&amp;, const String&amp;, unsigned startOffset);
</span><span class="cx"> 
</span><ins>+    bool matchConcurrently(VM&amp;, const String&amp;, unsigned startOffset, MatchResult&amp;);
+
</ins><span class="cx">     // Call these versions of the match functions if you're desperate for performance.
</span><span class="cx">     int matchInline(VM&amp;, const String&amp;, unsigned startOffset, Vector&lt;int, 32&gt;&amp; ovector);
</span><span class="cx">     MatchResult matchInline(VM&amp;, const String&amp;, unsigned startOffset);
</span><span class="lines">@@ -77,6 +85,9 @@
</span><span class="cx">         return m_state != NotCompiled;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool hasCodeFor(Yarr::YarrCharSize);
+    bool hasMatchOnlyCodeFor(Yarr::YarrCharSize);
+
</ins><span class="cx">     void deleteCode();
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(REGEXP_TRACING)
</span><span class="lines">@@ -132,6 +143,7 @@
</span><span class="cx">     unsigned m_rtMatchCallCount;
</span><span class="cx">     unsigned m_rtMatchFoundCount;
</span><span class="cx"> #endif
</span><ins>+    ConcurrentJITLock m_lock;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(YARR_JIT)
</span><span class="cx">     Yarr::YarrCodeBlock m_regExpJITCode;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpCachedResulth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -75,6 +75,11 @@
</span><span class="cx"> 
</span><span class="cx">     void visitChildren(SlotVisitor&amp;);
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfLastRegExp() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastRegExp); }
+    static ptrdiff_t offsetOfLastInput() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastInput); }
+    static ptrdiff_t offsetOfResult() { return OBJECT_OFFSETOF(RegExpCachedResult, m_result); }
+    static ptrdiff_t offsetOfReified() { return OBJECT_OFFSETOF(RegExpCachedResult, m_reified); }
+
</ins><span class="cx"> private:
</span><span class="cx">     MatchResult m_result;
</span><span class="cx">     bool m_reified;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpConstructorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpConstructor.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpConstructor.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/RegExpConstructor.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -69,6 +69,8 @@
</span><span class="cx"> 
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfCachedResult() { return OBJECT_OFFSETOF(RegExpConstructor, m_cachedResult); }
+
</ins><span class="cx"> protected:
</span><span class="cx">     void finishCreation(VM&amp;, RegExpPrototype*, GetterSetter* species);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpInlines.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpInlines.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/RegExpInlines.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;RegExp.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;Yarr.h&quot;
</span><ins>+#include &quot;YarrInterpreter.h&quot;
</ins><span class="cx"> #include &quot;YarrJIT.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #define REGEXP_FUNC_TEST_DATA_GEN 0
</span><span class="lines">@@ -67,21 +68,28 @@
</span><span class="cx"> };
</span><span class="cx"> #endif // REGEXP_FUNC_TEST_DATA_GEN
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void RegExp::compileIfNecessary(VM&amp; vm, Yarr::YarrCharSize charSize)
</del><ins>+ALWAYS_INLINE bool RegExp::hasCodeFor(Yarr::YarrCharSize charSize)
</ins><span class="cx"> {
</span><span class="cx">     if (hasCode()) {
</span><span class="cx"> #if ENABLE(YARR_JIT)
</span><span class="cx">         if (m_state != JITCode)
</span><del>-            return;
</del><ins>+            return true;
</ins><span class="cx">         if ((charSize == Yarr::Char8) &amp;&amp; (m_regExpJITCode.has8BitCode()))
</span><del>-            return;
</del><ins>+            return true;
</ins><span class="cx">         if ((charSize == Yarr::Char16) &amp;&amp; (m_regExpJITCode.has16BitCode()))
</span><del>-            return;
</del><ins>+            return true;
</ins><span class="cx"> #else
</span><del>-        return;
</del><ins>+        return true;
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><ins>+    return false;
+}
</ins><span class="cx"> 
</span><ins>+ALWAYS_INLINE void RegExp::compileIfNecessary(VM&amp; vm, Yarr::YarrCharSize charSize)
+{
+    if (hasCodeFor(charSize))
+        return;
+
</ins><span class="cx">     compile(&amp;vm, charSize);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -152,21 +160,29 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void RegExp::compileIfNecessaryMatchOnly(VM&amp; vm, Yarr::YarrCharSize charSize)
</del><ins>+ALWAYS_INLINE bool RegExp::hasMatchOnlyCodeFor(Yarr::YarrCharSize charSize)
</ins><span class="cx"> {
</span><span class="cx">     if (hasCode()) {
</span><span class="cx"> #if ENABLE(YARR_JIT)
</span><span class="cx">         if (m_state != JITCode)
</span><del>-            return;
</del><ins>+            return true;
</ins><span class="cx">         if ((charSize == Yarr::Char8) &amp;&amp; (m_regExpJITCode.has8BitCodeMatchOnly()))
</span><del>-            return;
</del><ins>+            return true;
</ins><span class="cx">         if ((charSize == Yarr::Char16) &amp;&amp; (m_regExpJITCode.has16BitCodeMatchOnly()))
</span><del>-            return;
</del><ins>+            return true;
</ins><span class="cx"> #else
</span><del>-        return;
</del><ins>+        return true;
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    return false;
+}
+
+ALWAYS_INLINE void RegExp::compileIfNecessaryMatchOnly(VM&amp; vm, Yarr::YarrCharSize charSize)
+{
+    if (hasMatchOnlyCodeFor(charSize))
+        return;
+
</ins><span class="cx">     compileMatchOnly(&amp;vm, charSize);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpObjectInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx">     String input = string-&gt;value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
</span><span class="cx">     VM&amp; vm = globalObject-&gt;vm();
</span><span class="cx"> 
</span><del>-    bool globalOrSticky = regExp-&gt;global() || regExp-&gt;sticky();
</del><ins>+    bool globalOrSticky = regExp-&gt;globalOrSticky();
</ins><span class="cx"> 
</span><span class="cx">     unsigned lastIndex;
</span><span class="cx">     if (globalOrSticky) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -282,7 +282,7 @@
</span><span class="cx">     return substitutedReplacement.toString();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline String substituteBackreferences(const String&amp; replacement, StringView source, const int* ovector, RegExp* reg)
</del><ins>+inline String substituteBackreferencesInline(const String&amp; replacement, StringView source, const int* ovector, RegExp* reg)
</ins><span class="cx"> {
</span><span class="cx">     size_t i = replacement.find('$');
</span><span class="cx">     if (UNLIKELY(i != notFound))
</span><span class="lines">@@ -291,6 +291,11 @@
</span><span class="cx">     return replacement;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String substituteBackreferences(const String&amp; replacement, StringView source, const int* ovector, RegExp* reg)
+{
+    return substituteBackreferencesInline(replacement, source, ovector, reg);
+}
+
</ins><span class="cx"> struct StringRange {
</span><span class="cx">     StringRange(int pos, int len)
</span><span class="cx">         : position(pos)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class ObjectPrototype;
</span><ins>+class RegExp;
</ins><span class="cx"> class RegExpObject;
</span><span class="cx"> 
</span><span class="cx"> class StringPrototype : public StringObject {
</span><span class="lines">@@ -62,6 +63,8 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationStringProtoFuncReplaceRegExpString(
</span><span class="cx">     ExecState*, JSString* thisValue, RegExpObject* searchValue, JSString* replaceValue);
</span><span class="cx"> 
</span><ins>+String substituteBackreferences(const String&amp; replacement, StringView source, const int* ovector, RegExp* reg);
+
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncRepeatCharacter(ExecState*);
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #ifndef VM_h
</span><span class="cx"> #define VM_h
</span><span class="cx"> 
</span><ins>+#include &quot;ConcurrentJITLock.h&quot;
</ins><span class="cx"> #include &quot;ControlFlowProfiler.h&quot;
</span><span class="cx"> #include &quot;DateInstanceCache.h&quot;
</span><span class="cx"> #include &quot;ExecutableAllocator.h&quot;
</span><span class="lines">@@ -541,6 +542,7 @@
</span><span class="cx">     RefPtr&lt;TypedArrayController&gt; m_typedArrayController;
</span><span class="cx">     RegExpCache* m_regExpCache;
</span><span class="cx">     BumpPointerAllocator m_regExpAllocator;
</span><ins>+    ConcurrentJITLock m_regExpAllocatorLock;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(REGEXP_TRACING)
</span><span class="cx">     typedef ListHashSet&lt;RegExp*&gt; RTTraceList;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssimpleregexpexecfoldingfailjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding-fail.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding-fail.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding-fail.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+function foo() {
+    return /(f)(o)(o)/.exec(&quot;bar&quot;);
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo();
+    if (result !== null)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssimpleregexpexecfoldingjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+function foo() {
+    return /(f)(o)(o)/.exec(&quot;foo&quot;);
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo();
+    if (result.length != 4)
+        throw &quot;Error: bad result: &quot; + result;
+    if (result[0] != &quot;foo&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+    if (result[1] != &quot;f&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+    if (result[2] != &quot;o&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+    if (result[3] != &quot;o&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssimpleregexptestfoldingfailjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding-fail.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding-fail.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding-fail.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+function foo() {
+    return /(f)(o)(o)/.test(&quot;bar&quot;);
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo();
+    if (result != false)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssimpleregexptestfoldingjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding.js (0 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/simple-regexp-test-folding.js        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+function foo() {
+    return /(f)(o)(o)/.test(&quot;foo&quot;);
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo();
+    if (result != true)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrRegularExpressioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-
</del><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
</span><span class="cx">  * Copyright (C) 2008 Collabora Ltd.
</span><span class="lines">@@ -30,6 +29,7 @@
</span><span class="cx"> #include &quot;RegularExpression.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Yarr.h&quot;
</span><ins>+#include &quot;YarrInterpreter.h&quot;
</ins><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><span class="cx"> #include &lt;wtf/BumpPointerAllocator.h&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/Yarr.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/Yarr.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/yarr/Yarr.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -28,7 +28,6 @@
</span><span class="cx"> #ifndef Yarr_h
</span><span class="cx"> #define Yarr_h
</span><span class="cx"> 
</span><del>-#include &quot;YarrInterpreter.h&quot;
</del><span class="cx"> #include &quot;YarrPattern.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Yarr {
</span><span class="lines">@@ -63,6 +62,8 @@
</span><span class="cx">     Char16
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct BytecodePattern;
+
</ins><span class="cx"> } } // namespace JSC::Yarr
</span><span class="cx"> 
</span><span class="cx"> #endif // Yarr_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1522,6 +1522,9 @@
</span><span class="cx">         if (!input.isAvailableInput(0))
</span><span class="cx">             return offsetNoMatch;
</span><span class="cx"> 
</span><ins>+        if (pattern-&gt;m_lock)
+            pattern-&gt;m_lock-&gt;lock();
+        
</ins><span class="cx">         for (unsigned i = 0; i &lt; pattern-&gt;m_body-&gt;m_numSubpatterns + 1; ++i)
</span><span class="cx">             output[i &lt;&lt; 1] = offsetNoMatch;
</span><span class="cx"> 
</span><span class="lines">@@ -1541,6 +1544,10 @@
</span><span class="cx">         pattern-&gt;m_allocator-&gt;stopAllocator();
</span><span class="cx"> 
</span><span class="cx">         ASSERT((result == JSRegExpMatch) == (output[0] != offsetNoMatch));
</span><ins>+
+        if (pattern-&gt;m_lock)
+            pattern-&gt;m_lock-&gt;unlock();
+        
</ins><span class="cx">         return output[0];
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1581,13 +1588,13 @@
</span><span class="cx">         m_currentAlternativeIndex = 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    std::unique_ptr&lt;BytecodePattern&gt; compile(BumpPointerAllocator* allocator)
</del><ins>+    std::unique_ptr&lt;BytecodePattern&gt; compile(BumpPointerAllocator* allocator, ConcurrentJITLock* lock)
</ins><span class="cx">     {
</span><span class="cx">         regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body-&gt;m_callFrameSize, m_pattern.m_body-&gt;m_alternatives[0]-&gt;onceThrough());
</span><span class="cx">         emitDisjunction(m_pattern.m_body);
</span><span class="cx">         regexEnd();
</span><span class="cx"> 
</span><del>-        return std::make_unique&lt;BytecodePattern&gt;(WTFMove(m_bodyDisjunction), m_allParenthesesInfo, m_pattern, allocator);
</del><ins>+        return std::make_unique&lt;BytecodePattern&gt;(WTFMove(m_bodyDisjunction), m_allParenthesesInfo, m_pattern, allocator, lock);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void checkInput(unsigned count)
</span><span class="lines">@@ -2032,9 +2039,9 @@
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;ByteDisjunction&gt;&gt; m_allParenthesesInfo;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;BytecodePattern&gt; byteCompile(YarrPattern&amp; pattern, BumpPointerAllocator* allocator)
</del><ins>+std::unique_ptr&lt;BytecodePattern&gt; byteCompile(YarrPattern&amp; pattern, BumpPointerAllocator* allocator, ConcurrentJITLock* lock)
</ins><span class="cx"> {
</span><del>-    return ByteCompiler(pattern).compile(allocator);
</del><ins>+    return ByteCompiler(pattern).compile(allocator, lock);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> unsigned interpret(BytecodePattern* bytecode, const String&amp; input, unsigned start, unsigned* output)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef YarrInterpreter_h
</span><span class="cx"> #define YarrInterpreter_h
</span><span class="cx"> 
</span><ins>+#include &quot;ConcurrentJITLock.h&quot;
</ins><span class="cx"> #include &quot;YarrPattern.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="lines">@@ -337,10 +338,11 @@
</span><span class="cx"> struct BytecodePattern {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    BytecodePattern(std::unique_ptr&lt;ByteDisjunction&gt; body, Vector&lt;std::unique_ptr&lt;ByteDisjunction&gt;&gt;&amp; parenthesesInfoToAdopt, YarrPattern&amp; pattern, BumpPointerAllocator* allocator)
</del><ins>+    BytecodePattern(std::unique_ptr&lt;ByteDisjunction&gt; body, Vector&lt;std::unique_ptr&lt;ByteDisjunction&gt;&gt;&amp; parenthesesInfoToAdopt, YarrPattern&amp; pattern, BumpPointerAllocator* allocator, ConcurrentJITLock* lock)
</ins><span class="cx">         : m_body(WTFMove(body))
</span><span class="cx">         , m_flags(pattern.m_flags)
</span><span class="cx">         , m_allocator(allocator)
</span><ins>+        , m_lock(lock)
</ins><span class="cx">     {
</span><span class="cx">         m_body-&gt;terms.shrinkToFit();
</span><span class="cx"> 
</span><span class="lines">@@ -366,6 +368,7 @@
</span><span class="cx">     // Each BytecodePattern is associated with a RegExp, each RegExp is associated
</span><span class="cx">     // with a VM.  Cache a pointer to out VM's m_regExpAllocator.
</span><span class="cx">     BumpPointerAllocator* m_allocator;
</span><ins>+    ConcurrentJITLock* m_lock;
</ins><span class="cx"> 
</span><span class="cx">     CharacterClass* newlineCharacterClass;
</span><span class="cx">     CharacterClass* wordcharCharacterClass;
</span><span class="lines">@@ -375,7 +378,7 @@
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;CharacterClass&gt;&gt; m_userCharacterClasses;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-JS_EXPORT_PRIVATE std::unique_ptr&lt;BytecodePattern&gt; byteCompile(YarrPattern&amp;, BumpPointerAllocator*);
</del><ins>+JS_EXPORT_PRIVATE std::unique_ptr&lt;BytecodePattern&gt; byteCompile(YarrPattern&amp;, BumpPointerAllocator*, ConcurrentJITLock* = nullptr);
</ins><span class="cx"> JS_EXPORT_PRIVATE unsigned interpret(BytecodePattern*, const String&amp; input, unsigned start, unsigned* output);
</span><span class="cx"> unsigned interpret(BytecodePattern*, const LChar* input, unsigned length, unsigned start, unsigned* output);
</span><span class="cx"> unsigned interpret(BytecodePattern*, const UChar* input, unsigned length, unsigned start, unsigned* output);
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/WTF/ChangeLog        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-03-19  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG and FTL should constant-fold RegExpExec
+        https://bugs.webkit.org/show_bug.cgi?id=155270
+
+        Reviewed by Saam Barati.
+
+        Make executeInsertions() return the amount by which the vector increased in size. This is a
+        convenient feature that I use in DFG::InsertionSet.
+
+        * wtf/Insertion.h:
+        (WTF::executeInsertions):
+
</ins><span class="cx"> 2016-04-05  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebGL2] Allow enabling WebGL2 with a runtime flag
</span></span></pre></div>
<a id="trunkSourceWTFwtfInsertionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Insertion.h (199074 => 199075)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Insertion.h        2016-04-05 22:12:39 UTC (rev 199074)
+++ trunk/Source/WTF/wtf/Insertion.h        2016-04-05 22:13:16 UTC (rev 199075)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -55,14 +55,15 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename TargetVectorType, typename InsertionVectorType&gt;
</span><del>-void executeInsertions(TargetVectorType&amp; target, InsertionVectorType&amp; insertions)
</del><ins>+size_t executeInsertions(TargetVectorType&amp; target, InsertionVectorType&amp; insertions)
</ins><span class="cx"> {
</span><del>-    if (!insertions.size())
-        return;
-    target.grow(target.size() + insertions.size());
</del><ins>+    size_t numInsertions = insertions.size();
+    if (!numInsertions)
+        return 0;
+    target.grow(target.size() + numInsertions);
</ins><span class="cx">     size_t lastIndex = target.size();
</span><span class="cx">     size_t originalTargetSize = target.size();
</span><del>-    for (size_t indexInInsertions = insertions.size(); indexInInsertions--;) {
</del><ins>+    for (size_t indexInInsertions = numInsertions; indexInInsertions--;) {
</ins><span class="cx">         ASSERT(!indexInInsertions || insertions[indexInInsertions].index() &gt;= insertions[indexInInsertions - 1].index());
</span><span class="cx">         ASSERT_UNUSED(originalTargetSize, insertions[indexInInsertions].index() &lt; originalTargetSize);
</span><span class="cx">         size_t firstIndex = insertions[indexInInsertions].index() + indexInInsertions;
</span><span class="lines">@@ -73,6 +74,7 @@
</span><span class="cx">         lastIndex = firstIndex;
</span><span class="cx">     }
</span><span class="cx">     insertions.resize(0);
</span><ins>+    return numInsertions;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WTF
</span></span></pre>
</div>
</div>

</body>
</html>