<!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>[171362] 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/171362">171362</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-07-22 14:08:50 -0700 (Tue, 22 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/168635">r168635</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/168780">r168780</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/169005">r169005</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/169014">r169014</a>, and <a href="http://trac.webkit.org/projects/webkit/changeset/169143">r169143</a> from ftlopt.

    2014-05-20  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    [ftlopt] DFG bytecode parser should turn GetById with nothing but a Getter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
    https://bugs.webkit.org/show_bug.cgi?id=133105
    
    Reviewed by Michael Saboff.

Source/JavaScriptCore: 
            
    - GetByIdStatus now knows about getters and can report intelligent things about them.
      As is usually the case with how we do these things, GetByIdStatus knows more about
      getters than the DFG can actually handle: it'll report details about polymorphic
      getter calls even though the DFG won't be able to handle those. This is fine; the DFG
      will see those statuses and bail to a generic slow path.
            
    - The DFG::ByteCodeParser now knows how to set up and do handleCall() for a getter call.
      This can, and usually does, result in inlining of getters!
            
    - CodeOrigin and OSR exit know about inlined getter calls. When you OSR out of an
      inlined getter, we set the return PC to a getter return thunk that fixes up the stack.
      We use the usual offset-true-return-PC trick, where OSR exit places the true return PC
      of the getter's caller as a phony argument that only the thunk knows how to find.
            
    - Removed a bunch of dead monomorphic chain support from StructureStubInfo.
            
    - A large chunk of this change is dragging GetGetterSetterByOffset, GetGetter, and
      GetSetter through the DFG and FTL. GetGetterSetterByOffset is like GetByOffset except
      that we know that we're returning a GetterSetter cell. GetGetter and GetSetter extract
      the getter, or setter, from the GetterSetter.
            
    This is a ~2.5x speed-up on the getter microbenchmarks that we already had. So far none
    of the &quot;real&quot; benchmarks exercise getters enough for this to matter. But I noticed that
    some of the variants of the Richards benchmark in other languages - for example
    Wolczko's Java translation of a C++ translation of Deutsch's Smalltalk version - use
    getters and setters extensively. So, I created a getter/setter JavaScript version of
    Richards and put it in regress/script-tests/getter-richards.js. That sees about a 2.4x
    speed-up from this patch, which is very reassuring.
    
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::printGetByIdCacheStatus):
    (JSC::CodeBlock::findStubInfo):
    * bytecode/CodeBlock.h:
    * bytecode/CodeOrigin.cpp:
    (WTF::printInternal):
    * bytecode/CodeOrigin.h:
    (JSC::InlineCallFrame::specializationKindFor):
    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::computeFor):
    (JSC::GetByIdStatus::computeForStubInfo):
    (JSC::GetByIdStatus::makesCalls):
    (JSC::GetByIdStatus::computeForChain): Deleted.
    * bytecode/GetByIdStatus.h:
    (JSC::GetByIdStatus::makesCalls): Deleted.
    * bytecode/GetByIdVariant.cpp:
    (JSC::GetByIdVariant::~GetByIdVariant):
    (JSC::GetByIdVariant::GetByIdVariant):
    (JSC::GetByIdVariant::operator=):
    (JSC::GetByIdVariant::dumpInContext):
    * bytecode/GetByIdVariant.h:
    (JSC::GetByIdVariant::GetByIdVariant):
    (JSC::GetByIdVariant::callLinkStatus):
    * bytecode/PolymorphicGetByIdList.cpp:
    (JSC::GetByIdAccess::fromStructureStubInfo):
    (JSC::PolymorphicGetByIdList::from):
    * bytecode/SpeculatedType.h:
    * bytecode/StructureStubInfo.cpp:
    (JSC::StructureStubInfo::deref):
    (JSC::StructureStubInfo::visitWeakReferences):
    * bytecode/StructureStubInfo.h:
    (JSC::isGetByIdAccess):
    (JSC::StructureStubInfo::initGetByIdChain): Deleted.
    * dfg/DFGAbstractHeap.h:
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::addCall):
    (JSC::DFG::ByteCodeParser::handleCall):
    (JSC::DFG::ByteCodeParser::handleInlining):
    (JSC::DFG::ByteCodeParser::handleGetByOffset):
    (JSC::DFG::ByteCodeParser::handleGetById):
    (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
    (JSC::DFG::ByteCodeParser::parse):
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::CSEPhase::getGetterSetterByOffsetLoadElimination):
    (JSC::DFG::CSEPhase::getInternalFieldLoadElimination):
    (JSC::DFG::CSEPhase::performNodeCSE):
    (JSC::DFG::CSEPhase::getTypedArrayByteOffsetLoadElimination): Deleted.
    * dfg/DFGClobberize.h:
    (JSC::DFG::clobberize):
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::fixupNode):
    * dfg/DFGJITCompiler.cpp:
    (JSC::DFG::JITCompiler::linkFunction):
    * dfg/DFGNode.h:
    (JSC::DFG::Node::hasStorageAccessData):
    * dfg/DFGNodeType.h:
    * dfg/DFGOSRExitCompilerCommon.cpp:
    (JSC::DFG::reifyInlinedCallFrames):
    * dfg/DFGPredictionPropagationPhase.cpp:
    (JSC::DFG::PredictionPropagationPhase::propagate):
    * dfg/DFGSafeToExecute.h:
    (JSC::DFG::safeToExecute):
    * dfg/DFGSpeculativeJIT32_64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * ftl/FTLAbstractHeapRepository.cpp:
    * ftl/FTLAbstractHeapRepository.h:
    * ftl/FTLCapabilities.cpp:
    (JSC::FTL::canCompile):
    * ftl/FTLLink.cpp:
    (JSC::FTL::link):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileNode):
    (JSC::FTL::LowerDFGToLLVM::compileGetGetter):
    (JSC::FTL::LowerDFGToLLVM::compileGetSetter):
    * jit/AccessorCallJITStubRoutine.h:
    * jit/JIT.cpp:
    (JSC::JIT::assertStackPointerOffset):
    (JSC::JIT::privateCompile):
    * jit/JIT.h:
    * jit/JITPropertyAccess.cpp:
    (JSC::JIT::emit_op_get_by_id):
    * jit/ThunkGenerators.cpp:
    (JSC::arityFixupGenerator):
    (JSC::baselineGetterReturnThunkGenerator):
    (JSC::baselineSetterReturnThunkGenerator):
    (JSC::arityFixup): Deleted.
    * jit/ThunkGenerators.h:
    * runtime/CommonSlowPaths.cpp:
    (JSC::setupArityCheckData):
    * tests/stress/exit-from-getter.js: Added.
    * tests/stress/poly-chain-getter.js: Added.
    (Cons):
    (foo):
    (test):
    * tests/stress/poly-chain-then-getter.js: Added.
    (Cons1):
    (Cons2):
    (foo):
    (test):
    * tests/stress/poly-getter-combo.js: Added.
    (Cons1):
    (Cons2):
    (foo):
    (test):
    (.test):
    * tests/stress/poly-getter-then-chain.js: Added.
    (Cons1):
    (Cons2):
    (foo):
    (test):
    * tests/stress/poly-getter-then-self.js: Added.
    (foo):
    (test):
    (.test):
    * tests/stress/poly-self-getter.js: Added.
    (foo):
    (test):
    (getter):
    * tests/stress/poly-self-then-getter.js: Added.
    (foo):
    (test):
    * tests/stress/weird-getter-counter.js: Added.
    (foo):
    (test):
    
    2014-05-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    [ftlopt] Factor out how CallLinkStatus uses exit site data
    https://bugs.webkit.org/show_bug.cgi?id=133042
    
    Reviewed by Anders Carlsson.
            
    This makes it easier to use CallLinkStatus from clients that are calling into after
    already holding some of the relevant locks. This is necessary because we use a &quot;one lock
    at a time&quot; policy for CodeBlock locks: if you hold one then you're not allowed to acquire
    any of the others. So, any code that needs to lock multiple CodeBlock locks needs to sort
    of lock one, do some stuff, release it, then lock another, and then do more stuff. The
    exit site data corresponds to the stuff you do while holding the baseline lock, while the
    CallLinkInfo method corresponds to the stuff you do while holding the CallLinkInfo owner's
    lock.
    
    * bytecode/CallLinkStatus.cpp:
    (JSC::CallLinkStatus::computeFor):
    (JSC::CallLinkStatus::computeExitSiteData):
    (JSC::CallLinkStatus::computeDFGStatuses):
    * bytecode/CallLinkStatus.h:
    (JSC::CallLinkStatus::ExitSiteData::ExitSiteData):
    
    2014-05-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    [ftlopt] InlineCallFrame::isCall should be an enumeration
    https://bugs.webkit.org/show_bug.cgi?id=133034
    
    Reviewed by Sam Weinig.
            
    Once we start inlining getters and setters, we'll want InlineCallFrame to be able to tell
    us that the inlined call was a getter call or a setter call. Initially I thought I would
    have a new field called &quot;kind&quot; that would have components NormalCall, GetterCall, and
    SetterCall. But that doesn't make sense, because for GetterCall and SetterCall, isCall
    would have to be true. Hence, It makes more sense to have one enumeration that is Call,
    Construct, GetterCall, or SetterCall. This patch is a first step towards this.
            
    It's interesting that isClosureCall should probably still be separate, since getter and
    setter inlining could inline closure calls.
    
    * bytecode/CodeBlock.h:
    (JSC::baselineCodeBlockForInlineCallFrame):
    * bytecode/CodeOrigin.cpp:
    (JSC::InlineCallFrame::dumpInContext):
    (WTF::printInternal):
    * bytecode/CodeOrigin.h:
    (JSC::InlineCallFrame::kindFor):
    (JSC::InlineCallFrame::specializationKindFor):
    (JSC::InlineCallFrame::InlineCallFrame):
    (JSC::InlineCallFrame::specializationKind):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
    * dfg/DFGOSRExitPreparation.cpp:
    (JSC::DFG::prepareCodeOriginForOSRExit):
    * runtime/Arguments.h:
    (JSC::Arguments::finishCreation):
    
    2014-05-13  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    [ftlopt] DFG should not exit due to inadequate profiling coverage when it can trivially fill in the profiling coverage due to variable constant inference and the better prediction modeling of typed array GetByVals
    https://bugs.webkit.org/show_bug.cgi?id=132896
    
    Reviewed by Geoffrey Garen.
            
    This is a slight win on SunSpider, but it's meant to ultimately help us on
    embenchen/lua. We already do well on that benchmark but our convergence is slower than
    I'd like.
    
    * dfg/DFGArrayMode.cpp:
    (JSC::DFG::ArrayMode::refine):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::parseBlock):
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::fixupNode):
    * dfg/DFGPredictionPropagationPhase.cpp:
    (JSC::DFG::PredictionPropagationPhase::propagate):
    
    2014-05-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    jsSubstring() should be lazy
    https://bugs.webkit.org/show_bug.cgi?id=132556
    
    Reviewed by Andreas Kling.
            
    jsSubstring() is now lazy by using a special rope that is a substring instead of a
    concatenation. To make this patch super simple, we require that a substring's base is
    never a rope. Hence, when resolving a rope, we either go down a non-recursive substring
    path, or we go down a concatenation path which may see exactly one level of substrings in
    its fibers.
            
    This is up to a 50% speed-up on microbenchmarks and a 10% speed-up on Octane/regexp.
            
    Relanding this with assertion fixes.
    
    * heap/MarkedBlock.cpp:
    (JSC::MarkedBlock::specializedSweep):
    * runtime/JSString.cpp:
    (JSC::JSRopeString::visitFibers):
    (JSC::JSRopeString::resolveRopeInternal8):
    (JSC::JSRopeString::resolveRopeInternal16):
    (JSC::JSRopeString::clearFibers):
    (JSC::JSRopeString::resolveRope):
    (JSC::JSRopeString::resolveRopeSlowCase8):
    (JSC::JSRopeString::resolveRopeSlowCase):
    * runtime/JSString.h:
    (JSC::JSRopeString::finishCreation):
    (JSC::JSRopeString::append):
    (JSC::JSRopeString::create):
    (JSC::JSRopeString::offsetOfFibers):
    (JSC::JSRopeString::fiber):
    (JSC::JSRopeString::substringBase):
    (JSC::JSRopeString::substringOffset):
    (JSC::JSRopeString::notSubstringSentinel):
    (JSC::JSRopeString::substringSentinel):
    (JSC::JSRopeString::isSubstring):
    (JSC::JSRopeString::setIsSubstring):
    (JSC::jsSubstring):
    * runtime/RegExpMatchesArray.cpp:
    (JSC::RegExpMatchesArray::reifyAllProperties):
    * runtime/StringPrototype.cpp:
    (JSC::stringProtoFuncSubstring):

Source/WTF: 
    
    * wtf/Bag.h:
    (WTF::Bag::iterator::operator!=):

LayoutTests: 
    
    * js/regress/getter-no-activation-expected.txt: Added.
    * js/regress/getter-no-activation.html: Added.
    * js/regress/script-tests/getter-no-activation.js: Added.
    * js/regress/getter-richards-expected.txt: Added.
    * js/regress/getter-richards.html: Added.
    * js/regress/script-tests/getter-richards.js: Added.
    
    2014-05-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    jsSubstring() should be lazy
    https://bugs.webkit.org/show_bug.cgi?id=132556
    
    Reviewed by Andreas Kling.
            
    These tests get 35-50% faster.
    
    * js/regress/script-tests/substring-concat-weird.js: Added.
    (foo):
    * js/regress/script-tests/substring-concat.js: Added.
    (foo):
    * js/regress/script-tests/substring.js: Added.
    (foo):
    * js/regress/substring-concat-expected.txt: Added.
    * js/regress/substring-concat-weird-expected.txt: Added.
    * js/regress/substring-concat-weird.html: Added.
    * js/regress/substring-concat.html: Added.
    * js/regress/substring-expected.txt: Added.
    * js/regress/substring.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="#trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp">trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkStatush">trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeOrigincpp">trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeOriginh">trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdStatush">trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdVariantcpp">trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdVarianth">trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicGetByIdListcpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicGetByIdList.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeSpeculatedTypeh">trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfocpp">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfoh">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractHeaph">trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModecpp">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCSEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.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="#trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommoncpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitPreparationcpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.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="#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="#trunkSourceJavaScriptCoreftlFTLLinkcpp">trunk/Source/JavaScriptCore/ftl/FTLLink.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockcpp">trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAccessorCallJITStubRoutineh">trunk/Source/JavaScriptCore/jit/AccessorCallJITStubRoutine.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorsh">trunk/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentsh">trunk/Source/JavaScriptCore/runtime/Arguments.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringcpp">trunk/Source/JavaScriptCore/runtime/JSString.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringh">trunk/Source/JavaScriptCore/runtime/JSString.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpMatchesArraycpp">trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStringPrototypecpp">trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressgetternoactivationexpectedtxt">trunk/LayoutTests/js/regress/getter-no-activation-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressgetternoactivationhtml">trunk/LayoutTests/js/regress/getter-no-activation.html</a></li>
<li><a href="#trunkLayoutTestsjsregressgetterrichardsexpectedtxt">trunk/LayoutTests/js/regress/getter-richards-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressgetterrichardshtml">trunk/LayoutTests/js/regress/getter-richards.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsgetternoactivationjs">trunk/LayoutTests/js/regress/script-tests/getter-no-activation.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsgetterrichardsjs">trunk/LayoutTests/js/regress/script-tests/getter-richards.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssubstringconcatweirdjs">trunk/LayoutTests/js/regress/script-tests/substring-concat-weird.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssubstringconcatjs">trunk/LayoutTests/js/regress/script-tests/substring-concat.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssubstringjs">trunk/LayoutTests/js/regress/script-tests/substring.js</a></li>
<li><a href="#trunkLayoutTestsjsregresssubstringconcatexpectedtxt">trunk/LayoutTests/js/regress/substring-concat-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssubstringconcatweirdexpectedtxt">trunk/LayoutTests/js/regress/substring-concat-weird-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssubstringconcatweirdhtml">trunk/LayoutTests/js/regress/substring-concat-weird.html</a></li>
<li><a href="#trunkLayoutTestsjsregresssubstringconcathtml">trunk/LayoutTests/js/regress/substring-concat.html</a></li>
<li><a href="#trunkLayoutTestsjsregresssubstringexpectedtxt">trunk/LayoutTests/js/regress/substring-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssubstringhtml">trunk/LayoutTests/js/regress/substring.html</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressexitfromgetterjs">trunk/Source/JavaScriptCore/tests/stress/exit-from-getter.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolychaingetterjs">trunk/Source/JavaScriptCore/tests/stress/poly-chain-getter.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolychainthengetterjs">trunk/Source/JavaScriptCore/tests/stress/poly-chain-then-getter.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolygettercombojs">trunk/Source/JavaScriptCore/tests/stress/poly-getter-combo.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolygetterthenchainjs">trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-chain.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolygetterthenselfjs">trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-self.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolyselfgetterjs">trunk/Source/JavaScriptCore/tests/stress/poly-self-getter.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolyselfthengetterjs">trunk/Source/JavaScriptCore/tests/stress/poly-self-then-getter.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressweirdgettercounterjs">trunk/Source/JavaScriptCore/tests/stress/weird-getter-counter.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/LayoutTests/ChangeLog        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2014-07-22  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Merge r168635, r168780, r169005, r169014, and r169143 from ftlopt.
+
+    2014-05-20  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            [ftlopt] DFG bytecode parser should turn GetById with nothing but a Getter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
+            https://bugs.webkit.org/show_bug.cgi?id=133105
+    
+            Reviewed by Michael Saboff.
+    
+            * js/regress/getter-no-activation-expected.txt: Added.
+            * js/regress/getter-no-activation.html: Added.
+            * js/regress/script-tests/getter-no-activation.js: Added.
+            * js/regress/getter-richards-expected.txt: Added.
+            * js/regress/getter-richards.html: Added.
+            * js/regress/script-tests/getter-richards.js: Added.
+    
+    2014-05-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            jsSubstring() should be lazy
+            https://bugs.webkit.org/show_bug.cgi?id=132556
+    
+            Reviewed by Andreas Kling.
+            
+            These tests get 35-50% faster.
+    
+            * js/regress/script-tests/substring-concat-weird.js: Added.
+            (foo):
+            * js/regress/script-tests/substring-concat.js: Added.
+            (foo):
+            * js/regress/script-tests/substring.js: Added.
+            (foo):
+            * js/regress/substring-concat-expected.txt: Added.
+            * js/regress/substring-concat-weird-expected.txt: Added.
+            * js/regress/substring-concat-weird.html: Added.
+            * js/regress/substring-concat.html: Added.
+            * js/regress/substring-expected.txt: Added.
+            * js/regress/substring.html: Added.
+    
</ins><span class="cx"> 2014-07-22  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Mac] Cocoa throws exception when the return type of NSAccessibilityLinkedUIElementsAttribute is not an array
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressgetternoactivationexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/getter-no-activation-expected.txt (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/getter-no-activation-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/getter-no-activation-expected.txt        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/getter-no-activation
+
+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="trunkLayoutTestsjsregressgetternoactivationhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/getter-no-activation.html (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/getter-no-activation.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/getter-no-activation.html        2014-07-22 21:08:50 UTC (rev 171362)
</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/getter-no-activation.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="trunkLayoutTestsjsregressgetterrichardsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/getter-richards-expected.txt (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/getter-richards-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/getter-richards-expected.txt        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/getter-richards
+
+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="trunkLayoutTestsjsregressgetterrichardshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/getter-richards.html (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/getter-richards.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/getter-richards.html        2014-07-22 21:08:50 UTC (rev 171362)
</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/getter-richards.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="trunkLayoutTestsjsregressscripttestsgetternoactivationjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/getter-no-activation.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/getter-no-activation.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/getter-no-activation.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+(function() {
+    var o = {_f:42};
+    o.__defineGetter__(&quot;f&quot;, function() { return this._f; });
+    (function() {
+        var result = 0;
+        var n = 2000000;
+        for (var i = 0; i &lt; n; ++i)
+            result += o.f;
+        if (result != n * 42)
+            throw &quot;Error: bad result: &quot; + result;
+    })();
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsgetterrichardsjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/getter-richards.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/getter-richards.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/getter-richards.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,593 @@
</span><ins>+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2014 Apple Inc.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// &quot;AS IS&quot; 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 THE COPYRIGHT
+// OWNER 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.
+
+
+// This is a JavaScript implementation of the Richards
+// benchmark from:
+//
+//    http://www.cl.cam.ac.uk/~mr10/Bench.html
+//
+// The benchmark was originally implemented in BCPL by
+// Martin Richards. It was then ported to JavaScript by the
+// V8 project authors, and then subsequently it was modified
+// to use getters and setters by WebKit authors.
+
+
+/**
+ * The Richards benchmark simulates the task dispatcher of an
+ * operating system.
+ **/
+function runRichards() {
+  var scheduler = new Scheduler();
+  scheduler.addIdleTask(ID_IDLE, 0, null, COUNT);
+
+  var queue = new Packet(null, ID_WORKER, KIND_WORK);
+  queue = new Packet(queue,  ID_WORKER, KIND_WORK);
+  scheduler.addWorkerTask(ID_WORKER, 1000, queue);
+
+  queue = new Packet(null, ID_DEVICE_A, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_A, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_A, KIND_DEVICE);
+  scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue);
+
+  queue = new Packet(null, ID_DEVICE_B, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_B, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_B, KIND_DEVICE);
+  scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue);
+
+  scheduler.addDeviceTask(ID_DEVICE_A, 4000, null);
+
+  scheduler.addDeviceTask(ID_DEVICE_B, 5000, null);
+
+  scheduler.schedule();
+
+  if (scheduler.queueCount != EXPECTED_QUEUE_COUNT ||
+      scheduler.holdCount != EXPECTED_HOLD_COUNT) {
+    var msg =
+        &quot;Error during execution: queueCount = &quot; + scheduler.queueCount +
+        &quot;, holdCount = &quot; + scheduler.holdCount + &quot;.&quot;;
+    throw new Error(msg);
+  }
+}
+
+var COUNT = 1000;
+
+/**
+ * These two constants specify how many times a packet is queued and
+ * how many times a task is put on hold in a correct run of richards.
+ * They don't have any meaning a such but are characteristic of a
+ * correct run so if the actual queue or hold count is different from
+ * the expected there must be a bug in the implementation.
+ **/
+var EXPECTED_QUEUE_COUNT = 2322;
+var EXPECTED_HOLD_COUNT = 928;
+
+
+/**
+ * A scheduler can be used to schedule a set of tasks based on their relative
+ * priorities.  Scheduling is done by maintaining a list of task control blocks
+ * which holds tasks and the data queue they are processing.
+ * @constructor
+ */
+function Scheduler() {
+  this._queueCount = 0;
+  this._holdCount = 0;
+  this._blocks = new Array(NUMBER_OF_IDS);
+  this._list = null;
+  this._currentTcb = null;
+  this._currentId = null;
+}
+
+var ID_IDLE       = 0;
+var ID_WORKER     = 1;
+var ID_HANDLER_A  = 2;
+var ID_HANDLER_B  = 3;
+var ID_DEVICE_A   = 4;
+var ID_DEVICE_B   = 5;
+var NUMBER_OF_IDS = 6;
+
+var KIND_DEVICE   = 0;
+var KIND_WORK     = 1;
+
+Scheduler.prototype.__defineGetter__(&quot;queueCount&quot;, function() { return this._queueCount; });
+Scheduler.prototype.__defineSetter__(&quot;queueCount&quot;, function(value) { this._queueCount = value; });
+Scheduler.prototype.__defineGetter__(&quot;holdCount&quot;, function() { return this._holdCount; });
+Scheduler.prototype.__defineSetter__(&quot;holdCount&quot;, function(value) { this._holdCount = value; });
+Scheduler.prototype.__defineGetter__(&quot;blocks&quot;, function() { return this._blocks; });
+Scheduler.prototype.__defineSetter__(&quot;blocks&quot;, function(value) { this._blocks = value; });
+Scheduler.prototype.__defineGetter__(&quot;list&quot;, function() { return this._list; });
+Scheduler.prototype.__defineSetter__(&quot;list&quot;, function(value) { this._list = value; });
+Scheduler.prototype.__defineGetter__(&quot;currentTcb&quot;, function() { return this._currentTcb; });
+Scheduler.prototype.__defineSetter__(&quot;currentTcb&quot;, function(value) { this._currentTcb = value; });
+Scheduler.prototype.__defineGetter__(&quot;currentId&quot;, function() { return this._currentId; });
+Scheduler.prototype.__defineSetter__(&quot;currentId&quot;, function(value) { this._currentId = value; });
+
+/**
+ * Add an idle task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {int} count the number of times to schedule the task
+ */
+Scheduler.prototype.addIdleTask = function (id, priority, queue, count) {
+  this.addRunningTask(id, priority, queue, new IdleTask(this, 1, count));
+};
+
+/**
+ * Add a work task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+Scheduler.prototype.addWorkerTask = function (id, priority, queue) {
+  this.addTask(id, priority, queue, new WorkerTask(this, ID_HANDLER_A, 0));
+};
+
+/**
+ * Add a handler task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+Scheduler.prototype.addHandlerTask = function (id, priority, queue) {
+  this.addTask(id, priority, queue, new HandlerTask(this));
+};
+
+/**
+ * Add a handler task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+Scheduler.prototype.addDeviceTask = function (id, priority, queue) {
+  this.addTask(id, priority, queue, new DeviceTask(this))
+};
+
+/**
+ * Add the specified task and mark it as running.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {Task} task the task to add
+ */
+Scheduler.prototype.addRunningTask = function (id, priority, queue, task) {
+  this.addTask(id, priority, queue, task);
+  this.currentTcb.setRunning();
+};
+
+/**
+ * Add the specified task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {Task} task the task to add
+ */
+Scheduler.prototype.addTask = function (id, priority, queue, task) {
+  this.currentTcb = new TaskControlBlock(this.list, id, priority, queue, task);
+  this.list = this.currentTcb;
+  this.blocks[id] = this.currentTcb;
+};
+
+/**
+ * Execute the tasks managed by this scheduler.
+ */
+Scheduler.prototype.schedule = function () {
+  this.currentTcb = this.list;
+  while (this.currentTcb != null) {
+    if (this.currentTcb.isHeldOrSuspended()) {
+      this.currentTcb = this.currentTcb.link;
+    } else {
+      this.currentId = this.currentTcb.id;
+      this.currentTcb = this.currentTcb.run();
+    }
+  }
+};
+
+/**
+ * Release a task that is currently blocked and return the next block to run.
+ * @param {int} id the id of the task to suspend
+ */
+Scheduler.prototype.release = function (id) {
+  var tcb = this.blocks[id];
+  if (tcb == null) return tcb;
+  tcb.markAsNotHeld();
+  if (tcb.priority &gt; this.currentTcb.priority) {
+    return tcb;
+  } else {
+    return this.currentTcb;
+  }
+};
+
+/**
+ * Block the currently executing task and return the next task control block
+ * to run.  The blocked task will not be made runnable until it is explicitly
+ * released, even if new work is added to it.
+ */
+Scheduler.prototype.holdCurrent = function () {
+  this.holdCount++;
+  this.currentTcb.markAsHeld();
+  return this.currentTcb.link;
+};
+
+/**
+ * Suspend the currently executing task and return the next task control block
+ * to run.  If new work is added to the suspended task it will be made runnable.
+ */
+Scheduler.prototype.suspendCurrent = function () {
+  this.currentTcb.markAsSuspended();
+  return this.currentTcb;
+};
+
+/**
+ * Add the specified packet to the end of the worklist used by the task
+ * associated with the packet and make the task runnable if it is currently
+ * suspended.
+ * @param {Packet} packet the packet to add
+ */
+Scheduler.prototype.queue = function (packet) {
+  var t = this.blocks[packet.id];
+  if (t == null) return t;
+  this.queueCount++;
+  packet.link = null;
+  packet.id = this.currentId;
+  return t.checkPriorityAdd(this.currentTcb, packet);
+};
+
+/**
+ * A task control block manages a task and the queue of work packages associated
+ * with it.
+ * @param {TaskControlBlock} link the preceding block in the linked block list
+ * @param {int} id the id of this block
+ * @param {int} priority the priority of this block
+ * @param {Packet} queue the queue of packages to be processed by the task
+ * @param {Task} task the task
+ * @constructor
+ */
+function TaskControlBlock(link, id, priority, queue, task) {
+  this._link = link;
+  this._id = id;
+  this._priority = priority;
+  this._queue = queue;
+  this._task = task;
+  if (queue == null) {
+    this.state = STATE_SUSPENDED;
+  } else {
+    this.state = STATE_SUSPENDED_RUNNABLE;
+  }
+}
+
+/**
+ * The task is running and is currently scheduled.
+ */
+var STATE_RUNNING = 0;
+
+/**
+ * The task has packets left to process.
+ */
+var STATE_RUNNABLE = 1;
+
+/**
+ * The task is not currently running.  The task is not blocked as such and may
+* be started by the scheduler.
+ */
+var STATE_SUSPENDED = 2;
+
+/**
+ * The task is blocked and cannot be run until it is explicitly released.
+ */
+var STATE_HELD = 4;
+
+var STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE;
+var STATE_NOT_HELD = ~STATE_HELD;
+
+TaskControlBlock.prototype.__defineGetter__(&quot;link&quot;, function() { return this._link; });
+TaskControlBlock.prototype.__defineGetter__(&quot;id&quot;, function() { return this._id; });
+TaskControlBlock.prototype.__defineGetter__(&quot;priority&quot;, function() { return this._priority; });
+TaskControlBlock.prototype.__defineGetter__(&quot;queue&quot;, function() { return this._queue; });
+TaskControlBlock.prototype.__defineSetter__(&quot;queue&quot;, function(value) { this._queue = value; });
+TaskControlBlock.prototype.__defineGetter__(&quot;task&quot;, function() { return this._task; });
+TaskControlBlock.prototype.__defineGetter__(&quot;state&quot;, function() { return this._state; });
+TaskControlBlock.prototype.__defineSetter__(&quot;state&quot;, function(value) { this._state = value; });
+
+TaskControlBlock.prototype.setRunning = function () {
+  this.state = STATE_RUNNING;
+};
+
+TaskControlBlock.prototype.markAsNotHeld = function () {
+  this.state = this.state &amp; STATE_NOT_HELD;
+};
+
+TaskControlBlock.prototype.markAsHeld = function () {
+  this.state = this.state | STATE_HELD;
+};
+
+TaskControlBlock.prototype.isHeldOrSuspended = function () {
+  return (this.state &amp; STATE_HELD) != 0 || (this.state == STATE_SUSPENDED);
+};
+
+TaskControlBlock.prototype.markAsSuspended = function () {
+  this.state = this.state | STATE_SUSPENDED;
+};
+
+TaskControlBlock.prototype.markAsRunnable = function () {
+  this.state = this.state | STATE_RUNNABLE;
+};
+
+/**
+ * Runs this task, if it is ready to be run, and returns the next task to run.
+ */
+TaskControlBlock.prototype.run = function () {
+  var packet;
+  if (this.state == STATE_SUSPENDED_RUNNABLE) {
+    packet = this.queue;
+    this.queue = packet.link;
+    if (this.queue == null) {
+      this.state = STATE_RUNNING;
+    } else {
+      this.state = STATE_RUNNABLE;
+    }
+  } else {
+    packet = null;
+  }
+  return this.task.run(packet);
+};
+
+/**
+ * Adds a packet to the worklist of this block's task, marks this as runnable if
+ * necessary, and returns the next runnable object to run (the one
+ * with the highest priority).
+ */
+TaskControlBlock.prototype.checkPriorityAdd = function (task, packet) {
+  if (this.queue == null) {
+    this.queue = packet;
+    this.markAsRunnable();
+    if (this.priority &gt; task.priority) return this;
+  } else {
+    this.queue = packet.addTo(this.queue);
+  }
+  return task;
+};
+
+TaskControlBlock.prototype.toString = function () {
+  return &quot;tcb { &quot; + this.task + &quot;@&quot; + this.state + &quot; }&quot;;
+};
+
+/**
+ * An idle task doesn't do any work itself but cycles control between the two
+ * device tasks.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @param {int} v1 a seed value that controls how the device tasks are scheduled
+ * @param {int} count the number of times this task should be scheduled
+ * @constructor
+ */
+function IdleTask(scheduler, v1, count) {
+  this._scheduler = scheduler;
+  this._v1 = v1;
+  this._count = count;
+}
+
+IdleTask.prototype.__defineGetter__(&quot;scheduler&quot;, function() { return this._scheduler; });
+IdleTask.prototype.__defineGetter__(&quot;v1&quot;, function() { return this._v1; });
+IdleTask.prototype.__defineSetter__(&quot;v1&quot;, function(value) { this._v1 = value; });
+IdleTask.prototype.__defineGetter__(&quot;count&quot;, function() { return this._count; });
+IdleTask.prototype.__defineSetter__(&quot;count&quot;, function(value) { this._count = value; });
+
+IdleTask.prototype.run = function (packet) {
+  this.count--;
+  if (this.count == 0) return this.scheduler.holdCurrent();
+  if ((this.v1 &amp; 1) == 0) {
+    this.v1 = this.v1 &gt;&gt; 1;
+    return this.scheduler.release(ID_DEVICE_A);
+  } else {
+    this.v1 = (this.v1 &gt;&gt; 1) ^ 0xD008;
+    return this.scheduler.release(ID_DEVICE_B);
+  }
+};
+
+IdleTask.prototype.toString = function () {
+  return &quot;IdleTask&quot;
+};
+
+/**
+ * A task that suspends itself after each time it has been run to simulate
+ * waiting for data from an external device.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @constructor
+ */
+function DeviceTask(scheduler) {
+  this._scheduler = scheduler;
+  this._v1 = null;
+}
+
+DeviceTask.prototype.__defineGetter__(&quot;scheduler&quot;, function() { return this._scheduler; });
+DeviceTask.prototype.__defineGetter__(&quot;v1&quot;, function() { return this._v1; });
+DeviceTask.prototype.__defineSetter__(&quot;v1&quot;, function(value) { this._v1 = value; });
+
+DeviceTask.prototype.run = function (packet) {
+  if (packet == null) {
+    if (this.v1 == null) return this.scheduler.suspendCurrent();
+    var v = this.v1;
+    this.v1 = null;
+    return this.scheduler.queue(v);
+  } else {
+    this.v1 = packet;
+    return this.scheduler.holdCurrent();
+  }
+};
+
+DeviceTask.prototype.toString = function () {
+  return &quot;DeviceTask&quot;;
+};
+
+/**
+ * A task that manipulates work packets.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @param {int} v1 a seed used to specify how work packets are manipulated
+ * @param {int} v2 another seed used to specify how work packets are manipulated
+ * @constructor
+ */
+function WorkerTask(scheduler, v1, v2) {
+  this._scheduler = scheduler;
+  this._v1 = v1;
+  this._v2 = v2;
+}
+
+WorkerTask.prototype.__defineGetter__(&quot;scheduler&quot;, function() { return this._scheduler; });
+WorkerTask.prototype.__defineGetter__(&quot;v1&quot;, function() { return this._v1; });
+WorkerTask.prototype.__defineSetter__(&quot;v1&quot;, function(value) { this._v1 = value; });
+WorkerTask.prototype.__defineGetter__(&quot;v2&quot;, function() { return this._v2; });
+WorkerTask.prototype.__defineSetter__(&quot;v2&quot;, function(value) { this._v2 = value; });
+
+WorkerTask.prototype.run = function (packet) {
+  if (packet == null) {
+    return this.scheduler.suspendCurrent();
+  } else {
+    if (this.v1 == ID_HANDLER_A) {
+      this.v1 = ID_HANDLER_B;
+    } else {
+      this.v1 = ID_HANDLER_A;
+    }
+    packet.id = this.v1;
+    packet.a1 = 0;
+    for (var i = 0; i &lt; DATA_SIZE; i++) {
+      this.v2++;
+      if (this.v2 &gt; 26) this.v2 = 1;
+      packet.a2[i] = this.v2;
+    }
+    return this.scheduler.queue(packet);
+  }
+};
+
+WorkerTask.prototype.toString = function () {
+  return &quot;WorkerTask&quot;;
+};
+
+/**
+ * A task that manipulates work packets and then suspends itself.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @constructor
+ */
+function HandlerTask(scheduler) {
+  this._scheduler = scheduler;
+  this._v1 = null;
+  this._v2 = null;
+}
+
+HandlerTask.prototype.__defineGetter__(&quot;scheduler&quot;, function() { return this._scheduler; });
+HandlerTask.prototype.__defineGetter__(&quot;v1&quot;, function() { return this._v1; });
+HandlerTask.prototype.__defineSetter__(&quot;v1&quot;, function(value) { this._v1 = value; });
+HandlerTask.prototype.__defineGetter__(&quot;v2&quot;, function() { return this._v2; });
+HandlerTask.prototype.__defineSetter__(&quot;v2&quot;, function(value) { this._v2 = value; });
+
+HandlerTask.prototype.run = function (packet) {
+  if (packet != null) {
+    if (packet.kind == KIND_WORK) {
+      this.v1 = packet.addTo(this.v1);
+    } else {
+      this.v2 = packet.addTo(this.v2);
+    }
+  }
+  if (this.v1 != null) {
+    var count = this.v1.a1;
+    var v;
+    if (count &lt; DATA_SIZE) {
+      if (this.v2 != null) {
+        v = this.v2;
+        this.v2 = this.v2.link;
+        v.a1 = this.v1.a2[count];
+        this.v1.a1 = count + 1;
+        return this.scheduler.queue(v);
+      }
+    } else {
+      v = this.v1;
+      this.v1 = this.v1.link;
+      return this.scheduler.queue(v);
+    }
+  }
+  return this.scheduler.suspendCurrent();
+};
+
+HandlerTask.prototype.toString = function () {
+  return &quot;HandlerTask&quot;;
+};
+
+/* --- *
+ * P a c k e t
+ * --- */
+
+var DATA_SIZE = 4;
+
+/**
+ * A simple package of data that is manipulated by the tasks.  The exact layout
+ * of the payload data carried by a packet is not importaint, and neither is the
+ * nature of the work performed on packets by the tasks.
+ *
+ * Besides carrying data, packets form linked lists and are hence used both as
+ * data and worklists.
+ * @param {Packet} link the tail of the linked list of packets
+ * @param {int} id an ID for this packet
+ * @param {int} kind the type of this packet
+ * @constructor
+ */
+function Packet(link, id, kind) {
+  this._link = link;
+  this._id = id;
+  this._kind = kind;
+  this._a1 = 0;
+  this._a2 = new Array(DATA_SIZE);
+}
+
+Packet.prototype.__defineGetter__(&quot;link&quot;, function() { return this._link; });
+Packet.prototype.__defineSetter__(&quot;link&quot;, function(value) { this._link = value; });
+Packet.prototype.__defineGetter__(&quot;id&quot;, function() { return this._id; });
+Packet.prototype.__defineSetter__(&quot;id&quot;, function(value) { this._id = value; });
+Packet.prototype.__defineGetter__(&quot;kind&quot;, function() { return this._kind; });
+Packet.prototype.__defineGetter__(&quot;a1&quot;, function() { return this._a1; });
+Packet.prototype.__defineSetter__(&quot;a1&quot;, function(value) { this._a1 = value; });
+Packet.prototype.__defineGetter__(&quot;a2&quot;, function() { return this._a2; });
+
+/**
+ * Add this packet to the end of a worklist, and return the worklist.
+ * @param {Packet} queue the worklist to add this packet to
+ */
+Packet.prototype.addTo = function (queue) {
+  this.link = null;
+  if (queue == null) return this;
+  var peek, next = queue;
+  while ((peek = next.link) != null)
+    next = peek;
+  next.link = this;
+  return queue;
+};
+
+Packet.prototype.toString = function () {
+  return &quot;Packet&quot;;
+};
+
+for (var i = 0; i &lt; 350; ++i)
+  runRichards();
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssubstringconcatweirdjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/substring-concat-weird.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/substring-concat-weird.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/substring-concat-weird.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+function foo() {
+    return a + b;
+}
+
+var array = Array(10007);
+
+var string = foo.toString();
+
+for (var i = 0; i &lt; 500000; ++i) {
+    array[i % array.length] = &quot;foo &quot; + string.substring(i % string.length, (i / string.length) % string.length) + &quot; bar&quot;;
+    array[i % array.length] = &quot;this &quot; + array[i % array.length] + &quot; that&quot;;
+}
+
+for (var i = 0; i &lt; array.length; ++i) {
+    var thing = array[i].substring(9, array[i].length - 9);
+    if (string.indexOf(thing) &lt; 0)
+        throw &quot;Error: bad substring: &quot; + thing;
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssubstringconcatjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/substring-concat.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/substring-concat.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/substring-concat.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+function foo() {
+    return a + b;
+}
+
+var array = Array(10007);
+
+var string = foo.toString();
+
+for (var i = 0; i &lt; 700000; ++i) {
+    array[i % array.length] = &quot;foo &quot; + string.substring(i % string.length, (i / string.length) % string.length) + &quot; bar&quot;;
+}
+
+for (var i = 0; i &lt; array.length; ++i) {
+    var thing = array[i].substring(4, array[i].length - 4);
+    if (string.indexOf(thing) &lt; 0)
+        throw &quot;Error: bad substring: \&quot;&quot; + thing + &quot;\&quot;&quot;;
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssubstringjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/substring.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/substring.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/substring.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function foo() {
+    return a + b;
+}
+
+var array = Array(10007);
+
+var string = foo.toString();
+
+for (var i = 0; i &lt; 1000000; ++i) {
+    array[i % array.length] = string.substring(i % string.length, (i / string.length) % string.length);
+}
+
+for (var i = 0; i &lt; array.length; ++i) {
+    if (string.indexOf(array[i]) &lt; 0)
+        throw &quot;Error: bad substring: &quot; + array[i];
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssubstringconcatexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/substring-concat-expected.txt (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/substring-concat-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/substring-concat-expected.txt        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/substring-concat
+
+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="trunkLayoutTestsjsregresssubstringconcatweirdexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/substring-concat-weird-expected.txt (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/substring-concat-weird-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/substring-concat-weird-expected.txt        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/substring-concat-weird
+
+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="trunkLayoutTestsjsregresssubstringconcatweirdhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/substring-concat-weird.html (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/substring-concat-weird.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/substring-concat-weird.html        2014-07-22 21:08:50 UTC (rev 171362)
</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/substring-concat-weird.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="trunkLayoutTestsjsregresssubstringconcathtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/substring-concat.html (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/substring-concat.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/substring-concat.html        2014-07-22 21:08:50 UTC (rev 171362)
</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/substring-concat.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="trunkLayoutTestsjsregresssubstringexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/substring-expected.txt (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/substring-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/substring-expected.txt        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/substring
+
+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="trunkLayoutTestsjsregresssubstringhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/substring.html (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/substring.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/substring.html        2014-07-22 21:08:50 UTC (rev 171362)
</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/substring.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 (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,3 +1,294 @@
</span><ins>+2014-07-22  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Merge r168635, r168780, r169005, r169014, and r169143 from ftlopt.
+
+    2014-05-20  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            [ftlopt] DFG bytecode parser should turn GetById with nothing but a Getter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
+            https://bugs.webkit.org/show_bug.cgi?id=133105
+    
+            Reviewed by Michael Saboff.
+            
+            - GetByIdStatus now knows about getters and can report intelligent things about them.
+              As is usually the case with how we do these things, GetByIdStatus knows more about
+              getters than the DFG can actually handle: it'll report details about polymorphic
+              getter calls even though the DFG won't be able to handle those. This is fine; the DFG
+              will see those statuses and bail to a generic slow path.
+            
+            - The DFG::ByteCodeParser now knows how to set up and do handleCall() for a getter call.
+              This can, and usually does, result in inlining of getters!
+            
+            - CodeOrigin and OSR exit know about inlined getter calls. When you OSR out of an
+              inlined getter, we set the return PC to a getter return thunk that fixes up the stack.
+              We use the usual offset-true-return-PC trick, where OSR exit places the true return PC
+              of the getter's caller as a phony argument that only the thunk knows how to find.
+            
+            - Removed a bunch of dead monomorphic chain support from StructureStubInfo.
+            
+            - A large chunk of this change is dragging GetGetterSetterByOffset, GetGetter, and
+              GetSetter through the DFG and FTL. GetGetterSetterByOffset is like GetByOffset except
+              that we know that we're returning a GetterSetter cell. GetGetter and GetSetter extract
+              the getter, or setter, from the GetterSetter.
+            
+            This is a ~2.5x speed-up on the getter microbenchmarks that we already had. So far none
+            of the &quot;real&quot; benchmarks exercise getters enough for this to matter. But I noticed that
+            some of the variants of the Richards benchmark in other languages - for example
+            Wolczko's Java translation of a C++ translation of Deutsch's Smalltalk version - use
+            getters and setters extensively. So, I created a getter/setter JavaScript version of
+            Richards and put it in regress/script-tests/getter-richards.js. That sees about a 2.4x
+            speed-up from this patch, which is very reassuring.
+    
+            * bytecode/CodeBlock.cpp:
+            (JSC::CodeBlock::printGetByIdCacheStatus):
+            (JSC::CodeBlock::findStubInfo):
+            * bytecode/CodeBlock.h:
+            * bytecode/CodeOrigin.cpp:
+            (WTF::printInternal):
+            * bytecode/CodeOrigin.h:
+            (JSC::InlineCallFrame::specializationKindFor):
+            * bytecode/GetByIdStatus.cpp:
+            (JSC::GetByIdStatus::computeFor):
+            (JSC::GetByIdStatus::computeForStubInfo):
+            (JSC::GetByIdStatus::makesCalls):
+            (JSC::GetByIdStatus::computeForChain): Deleted.
+            * bytecode/GetByIdStatus.h:
+            (JSC::GetByIdStatus::makesCalls): Deleted.
+            * bytecode/GetByIdVariant.cpp:
+            (JSC::GetByIdVariant::~GetByIdVariant):
+            (JSC::GetByIdVariant::GetByIdVariant):
+            (JSC::GetByIdVariant::operator=):
+            (JSC::GetByIdVariant::dumpInContext):
+            * bytecode/GetByIdVariant.h:
+            (JSC::GetByIdVariant::GetByIdVariant):
+            (JSC::GetByIdVariant::callLinkStatus):
+            * bytecode/PolymorphicGetByIdList.cpp:
+            (JSC::GetByIdAccess::fromStructureStubInfo):
+            (JSC::PolymorphicGetByIdList::from):
+            * bytecode/SpeculatedType.h:
+            * bytecode/StructureStubInfo.cpp:
+            (JSC::StructureStubInfo::deref):
+            (JSC::StructureStubInfo::visitWeakReferences):
+            * bytecode/StructureStubInfo.h:
+            (JSC::isGetByIdAccess):
+            (JSC::StructureStubInfo::initGetByIdChain): Deleted.
+            * dfg/DFGAbstractHeap.h:
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::addCall):
+            (JSC::DFG::ByteCodeParser::handleCall):
+            (JSC::DFG::ByteCodeParser::handleInlining):
+            (JSC::DFG::ByteCodeParser::handleGetByOffset):
+            (JSC::DFG::ByteCodeParser::handleGetById):
+            (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+            (JSC::DFG::ByteCodeParser::parse):
+            * dfg/DFGCSEPhase.cpp:
+            (JSC::DFG::CSEPhase::getGetterSetterByOffsetLoadElimination):
+            (JSC::DFG::CSEPhase::getInternalFieldLoadElimination):
+            (JSC::DFG::CSEPhase::performNodeCSE):
+            (JSC::DFG::CSEPhase::getTypedArrayByteOffsetLoadElimination): Deleted.
+            * dfg/DFGClobberize.h:
+            (JSC::DFG::clobberize):
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            * dfg/DFGJITCompiler.cpp:
+            (JSC::DFG::JITCompiler::linkFunction):
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::hasStorageAccessData):
+            * dfg/DFGNodeType.h:
+            * dfg/DFGOSRExitCompilerCommon.cpp:
+            (JSC::DFG::reifyInlinedCallFrames):
+            * dfg/DFGPredictionPropagationPhase.cpp:
+            (JSC::DFG::PredictionPropagationPhase::propagate):
+            * dfg/DFGSafeToExecute.h:
+            (JSC::DFG::safeToExecute):
+            * dfg/DFGSpeculativeJIT32_64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * ftl/FTLAbstractHeapRepository.cpp:
+            * ftl/FTLAbstractHeapRepository.h:
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLLink.cpp:
+            (JSC::FTL::link):
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileNode):
+            (JSC::FTL::LowerDFGToLLVM::compileGetGetter):
+            (JSC::FTL::LowerDFGToLLVM::compileGetSetter):
+            * jit/AccessorCallJITStubRoutine.h:
+            * jit/JIT.cpp:
+            (JSC::JIT::assertStackPointerOffset):
+            (JSC::JIT::privateCompile):
+            * jit/JIT.h:
+            * jit/JITPropertyAccess.cpp:
+            (JSC::JIT::emit_op_get_by_id):
+            * jit/ThunkGenerators.cpp:
+            (JSC::arityFixupGenerator):
+            (JSC::baselineGetterReturnThunkGenerator):
+            (JSC::baselineSetterReturnThunkGenerator):
+            (JSC::arityFixup): Deleted.
+            * jit/ThunkGenerators.h:
+            * runtime/CommonSlowPaths.cpp:
+            (JSC::setupArityCheckData):
+            * tests/stress/exit-from-getter.js: Added.
+            * tests/stress/poly-chain-getter.js: Added.
+            (Cons):
+            (foo):
+            (test):
+            * tests/stress/poly-chain-then-getter.js: Added.
+            (Cons1):
+            (Cons2):
+            (foo):
+            (test):
+            * tests/stress/poly-getter-combo.js: Added.
+            (Cons1):
+            (Cons2):
+            (foo):
+            (test):
+            (.test):
+            * tests/stress/poly-getter-then-chain.js: Added.
+            (Cons1):
+            (Cons2):
+            (foo):
+            (test):
+            * tests/stress/poly-getter-then-self.js: Added.
+            (foo):
+            (test):
+            (.test):
+            * tests/stress/poly-self-getter.js: Added.
+            (foo):
+            (test):
+            (getter):
+            * tests/stress/poly-self-then-getter.js: Added.
+            (foo):
+            (test):
+            * tests/stress/weird-getter-counter.js: Added.
+            (foo):
+            (test):
+    
+    2014-05-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            [ftlopt] Factor out how CallLinkStatus uses exit site data
+            https://bugs.webkit.org/show_bug.cgi?id=133042
+    
+            Reviewed by Anders Carlsson.
+            
+            This makes it easier to use CallLinkStatus from clients that are calling into after
+            already holding some of the relevant locks. This is necessary because we use a &quot;one lock
+            at a time&quot; policy for CodeBlock locks: if you hold one then you're not allowed to acquire
+            any of the others. So, any code that needs to lock multiple CodeBlock locks needs to sort
+            of lock one, do some stuff, release it, then lock another, and then do more stuff. The
+            exit site data corresponds to the stuff you do while holding the baseline lock, while the
+            CallLinkInfo method corresponds to the stuff you do while holding the CallLinkInfo owner's
+            lock.
+    
+            * bytecode/CallLinkStatus.cpp:
+            (JSC::CallLinkStatus::computeFor):
+            (JSC::CallLinkStatus::computeExitSiteData):
+            (JSC::CallLinkStatus::computeDFGStatuses):
+            * bytecode/CallLinkStatus.h:
+            (JSC::CallLinkStatus::ExitSiteData::ExitSiteData):
+    
+    2014-05-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            [ftlopt] InlineCallFrame::isCall should be an enumeration
+            https://bugs.webkit.org/show_bug.cgi?id=133034
+    
+            Reviewed by Sam Weinig.
+            
+            Once we start inlining getters and setters, we'll want InlineCallFrame to be able to tell
+            us that the inlined call was a getter call or a setter call. Initially I thought I would
+            have a new field called &quot;kind&quot; that would have components NormalCall, GetterCall, and
+            SetterCall. But that doesn't make sense, because for GetterCall and SetterCall, isCall
+            would have to be true. Hence, It makes more sense to have one enumeration that is Call,
+            Construct, GetterCall, or SetterCall. This patch is a first step towards this.
+            
+            It's interesting that isClosureCall should probably still be separate, since getter and
+            setter inlining could inline closure calls.
+    
+            * bytecode/CodeBlock.h:
+            (JSC::baselineCodeBlockForInlineCallFrame):
+            * bytecode/CodeOrigin.cpp:
+            (JSC::InlineCallFrame::dumpInContext):
+            (WTF::printInternal):
+            * bytecode/CodeOrigin.h:
+            (JSC::InlineCallFrame::kindFor):
+            (JSC::InlineCallFrame::specializationKindFor):
+            (JSC::InlineCallFrame::InlineCallFrame):
+            (JSC::InlineCallFrame::specializationKind):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+            * dfg/DFGOSRExitPreparation.cpp:
+            (JSC::DFG::prepareCodeOriginForOSRExit):
+            * runtime/Arguments.h:
+            (JSC::Arguments::finishCreation):
+    
+    2014-05-13  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            [ftlopt] DFG should not exit due to inadequate profiling coverage when it can trivially fill in the profiling coverage due to variable constant inference and the better prediction modeling of typed array GetByVals
+            https://bugs.webkit.org/show_bug.cgi?id=132896
+    
+            Reviewed by Geoffrey Garen.
+            
+            This is a slight win on SunSpider, but it's meant to ultimately help us on
+            embenchen/lua. We already do well on that benchmark but our convergence is slower than
+            I'd like.
+    
+            * dfg/DFGArrayMode.cpp:
+            (JSC::DFG::ArrayMode::refine):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::parseBlock):
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            * dfg/DFGPredictionPropagationPhase.cpp:
+            (JSC::DFG::PredictionPropagationPhase::propagate):
+    
+    2014-05-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            jsSubstring() should be lazy
+            https://bugs.webkit.org/show_bug.cgi?id=132556
+    
+            Reviewed by Andreas Kling.
+            
+            jsSubstring() is now lazy by using a special rope that is a substring instead of a
+            concatenation. To make this patch super simple, we require that a substring's base is
+            never a rope. Hence, when resolving a rope, we either go down a non-recursive substring
+            path, or we go down a concatenation path which may see exactly one level of substrings in
+            its fibers.
+            
+            This is up to a 50% speed-up on microbenchmarks and a 10% speed-up on Octane/regexp.
+            
+            Relanding this with assertion fixes.
+    
+            * heap/MarkedBlock.cpp:
+            (JSC::MarkedBlock::specializedSweep):
+            * runtime/JSString.cpp:
+            (JSC::JSRopeString::visitFibers):
+            (JSC::JSRopeString::resolveRopeInternal8):
+            (JSC::JSRopeString::resolveRopeInternal16):
+            (JSC::JSRopeString::clearFibers):
+            (JSC::JSRopeString::resolveRope):
+            (JSC::JSRopeString::resolveRopeSlowCase8):
+            (JSC::JSRopeString::resolveRopeSlowCase):
+            * runtime/JSString.h:
+            (JSC::JSRopeString::finishCreation):
+            (JSC::JSRopeString::append):
+            (JSC::JSRopeString::create):
+            (JSC::JSRopeString::offsetOfFibers):
+            (JSC::JSRopeString::fiber):
+            (JSC::JSRopeString::substringBase):
+            (JSC::JSRopeString::substringOffset):
+            (JSC::JSRopeString::notSubstringSentinel):
+            (JSC::JSRopeString::substringSentinel):
+            (JSC::JSRopeString::isSubstring):
+            (JSC::JSRopeString::setIsSubstring):
+            (JSC::jsSubstring):
+            * runtime/RegExpMatchesArray.cpp:
+            (JSC::RegExpMatchesArray::reifyAllProperties):
+            * runtime/StringPrototype.cpp:
+            (JSC::stringProtoFuncSubstring):
+    
</ins><span class="cx"> 2014-07-21  Sam Weinig  &lt;sam@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [Cocoa] WKScriptMessageHandlers don't seem to function properly after navigating
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -120,28 +120,38 @@
</span><span class="cx">     UNUSED_PARAM(bytecodeIndex);
</span><span class="cx">     UNUSED_PARAM(map);
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    if (profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
-        || profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCacheWatchpoint))
-        || profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable)))
</del><ins>+    ExitSiteData exitSiteData = computeExitSiteData(locker, profiledBlock, bytecodeIndex);
+    if (exitSiteData.m_takesSlowPath)
</ins><span class="cx">         return takesSlowPath();
</span><span class="cx">     
</span><span class="cx">     CallLinkInfo* callLinkInfo = map.get(CodeOrigin(bytecodeIndex));
</span><span class="cx">     if (!callLinkInfo)
</span><span class="cx">         return computeFromLLInt(locker, profiledBlock, bytecodeIndex);
</span><span class="cx">     
</span><del>-    CallLinkStatus result = computeFor(locker, *callLinkInfo);
-    if (!result)
-        return computeFromLLInt(locker, profiledBlock, bytecodeIndex);
-    
-    if (profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction)))
-        result.makeClosureCall();
-    
-    return result;
</del><ins>+    return computeFor(locker, *callLinkInfo, exitSiteData);
</ins><span class="cx"> #else
</span><span class="cx">     return CallLinkStatus();
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CallLinkStatus::ExitSiteData CallLinkStatus::computeExitSiteData(
+    const ConcurrentJITLocker&amp; locker, CodeBlock* profiledBlock, unsigned bytecodeIndex,
+    ExitingJITType exitingJITType)
+{
+    ExitSiteData exitSiteData;
+    
+#if ENABLE(DFG_JIT)
+    exitSiteData.m_takesSlowPath =
+        profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache, exitingJITType))
+        || profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCacheWatchpoint, exitingJITType))
+        || profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable, exitingJITType));
+    exitSiteData.m_badFunction =
+        profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction, exitingJITType));
+#endif
+    
+    return exitSiteData;
+}
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> CallLinkStatus CallLinkStatus::computeFor(const ConcurrentJITLocker&amp;, CallLinkInfo&amp; callLinkInfo)
</span><span class="cx"> {
</span><span class="lines">@@ -173,6 +183,19 @@
</span><span class="cx"> 
</span><span class="cx">     return CallLinkStatus(target);
</span><span class="cx"> }
</span><ins>+
+CallLinkStatus CallLinkStatus::computeFor(
+    const ConcurrentJITLocker&amp; locker, CallLinkInfo&amp; callLinkInfo, ExitSiteData exitSiteData)
+{
+    if (exitSiteData.m_takesSlowPath)
+        return takesSlowPath();
+    
+    CallLinkStatus result = computeFor(locker, callLinkInfo);
+    if (exitSiteData.m_badFunction)
+        result.makeClosureCall();
+    
+    return result;
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> void CallLinkStatus::computeDFGStatuses(
</span><span class="lines">@@ -185,9 +208,6 @@
</span><span class="cx">         CallLinkInfo&amp; info = **iter;
</span><span class="cx">         CodeOrigin codeOrigin = info.codeOrigin;
</span><span class="cx">         
</span><del>-        bool takeSlowPath;
-        bool badFunction;
-        
</del><span class="cx">         // Check if we had already previously made a terrible mistake in the FTL for this
</span><span class="cx">         // code origin. Note that this is approximate because we could have a monovariant
</span><span class="cx">         // inline in the FTL that ended up failing. We should fix that at some point by
</span><span class="lines">@@ -197,28 +217,16 @@
</span><span class="cx">         // InlineCallFrames.
</span><span class="cx">         CodeBlock* currentBaseline =
</span><span class="cx">             baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock);
</span><ins>+        ExitSiteData exitSiteData;
</ins><span class="cx">         {
</span><span class="cx">             ConcurrentJITLocker locker(currentBaseline-&gt;m_lock);
</span><del>-            takeSlowPath =
-                currentBaseline-&gt;hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadCache, ExitFromFTL))
-                || currentBaseline-&gt;hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadCacheWatchpoint, ExitFromFTL))
-                || currentBaseline-&gt;hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadExecutable, ExitFromFTL));
-            badFunction =
-                currentBaseline-&gt;hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadFunction, ExitFromFTL));
</del><ins>+            exitSiteData = computeExitSiteData(
+                locker, currentBaseline, codeOrigin.bytecodeIndex, ExitFromFTL);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         {
</span><span class="cx">             ConcurrentJITLocker locker(dfgCodeBlock-&gt;m_lock);
</span><del>-            if (takeSlowPath)
-                map.add(info.codeOrigin, takesSlowPath());
-            else {
-                CallLinkStatus status = computeFor(locker, info);
-                if (status.isSet()) {
-                    if (badFunction)
-                        status.makeClosureCall();
-                    map.add(info.codeOrigin, status);
-                }
-            }
</del><ins>+            map.add(info.codeOrigin, computeFor(locker, info, exitSiteData));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> #else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatush"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;CodeSpecializationKind.h&quot;
</span><span class="cx"> #include &quot;ConcurrentJITLock.h&quot;
</span><ins>+#include &quot;ExitingJITType.h&quot;
</ins><span class="cx"> #include &quot;Intrinsic.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -79,10 +80,23 @@
</span><span class="cx">     static CallLinkStatus computeFor(
</span><span class="cx">         CodeBlock*, unsigned bytecodeIndex, const CallLinkInfoMap&amp;);
</span><span class="cx"> 
</span><ins>+    struct ExitSiteData {
+        ExitSiteData()
+            : m_takesSlowPath(false)
+            , m_badFunction(false)
+        {
+        }
+        
+        bool m_takesSlowPath;
+        bool m_badFunction;
+    };
+    static ExitSiteData computeExitSiteData(const ConcurrentJITLocker&amp;, CodeBlock*, unsigned bytecodeIndex, ExitingJITType = ExitFromAnything);
+    
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     // Computes the status assuming that we never took slow path and never previously
</span><span class="cx">     // exited.
</span><span class="cx">     static CallLinkStatus computeFor(const ConcurrentJITLocker&amp;, CallLinkInfo&amp;);
</span><ins>+    static CallLinkStatus computeFor(const ConcurrentJITLocker&amp;, CallLinkInfo&amp;, ExitSiteData);
</ins><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     typedef HashMap&lt;CodeOrigin, CallLinkStatus, CodeOriginApproximateHash&gt; ContextMap;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -348,11 +348,6 @@
</span><span class="cx">                 out.printf(&quot;self&quot;);
</span><span class="cx">                 baseStructure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
</span><span class="cx">                 break;
</span><del>-            case access_get_by_id_chain:
-                out.printf(&quot;chain&quot;);
-                baseStructure = stubInfo.u.getByIdChain.baseObjectStructure.get();
-                chain = stubInfo.u.getByIdChain.chain.get();
-                break;
</del><span class="cx">             case access_get_by_id_list:
</span><span class="cx">                 out.printf(&quot;list&quot;);
</span><span class="cx">                 list = stubInfo.u.getByIdList.list;
</span><span class="lines">@@ -2325,6 +2320,15 @@
</span><span class="cx">     return m_stubInfos.add();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
+{
+    for (StructureStubInfo* stubInfo : m_stubInfos) {
+        if (stubInfo-&gt;codeOrigin == codeOrigin)
+            return stubInfo;
+    }
+    return nullptr;
+}
+
</ins><span class="cx"> CallLinkInfo* CodeBlock::addCallLinkInfo()
</span><span class="cx"> {
</span><span class="cx">     ConcurrentJITLocker locker(m_lock);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -201,6 +201,10 @@
</span><span class="cx">     StructureStubInfo* addStubInfo();
</span><span class="cx">     Bag&lt;StructureStubInfo&gt;::iterator stubInfoBegin() { return m_stubInfos.begin(); }
</span><span class="cx">     Bag&lt;StructureStubInfo&gt;::iterator stubInfoEnd() { return m_stubInfos.end(); }
</span><ins>+    
+    // O(n) operation. Use getStubInfoMap() unless you really only intend to get one
+    // stub info.
+    StructureStubInfo* findStubInfo(CodeOrigin);
</ins><span class="cx"> 
</span><span class="cx">     void resetStub(StructureStubInfo&amp;);
</span><span class="cx">     
</span><span class="lines">@@ -1191,7 +1195,7 @@
</span><span class="cx">     RELEASE_ASSERT(inlineCallFrame);
</span><span class="cx">     ExecutableBase* executable = inlineCallFrame-&gt;executable.get();
</span><span class="cx">     RELEASE_ASSERT(executable-&gt;structure()-&gt;classInfo() == FunctionExecutable::info());
</span><del>-    return static_cast&lt;FunctionExecutable*&gt;(executable)-&gt;baselineCodeBlockFor(inlineCallFrame-&gt;isCall ? CodeForCall : CodeForConstruct);
</del><ins>+    return static_cast&lt;FunctionExecutable*&gt;(executable)-&gt;baselineCodeBlockFor(inlineCallFrame-&gt;specializationKind());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin&amp; codeOrigin, CodeBlock* baselineCodeBlock)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeOrigincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013, 2014 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">@@ -178,7 +178,7 @@
</span><span class="cx">     out.print(briefFunctionInformation(), &quot;:&lt;&quot;, RawPointer(executable.get()));
</span><span class="cx">     if (executable-&gt;isStrictMode())
</span><span class="cx">         out.print(&quot; (StrictMode)&quot;);
</span><del>-    out.print(&quot;, bc#&quot;, caller.bytecodeIndex, &quot;, &quot;, specializationKind());
</del><ins>+    out.print(&quot;, bc#&quot;, caller.bytecodeIndex, &quot;, &quot;, kind);
</ins><span class="cx">     if (isClosureCall)
</span><span class="cx">         out.print(&quot;, closure call&quot;);
</span><span class="cx">     else
</span><span class="lines">@@ -195,3 +195,26 @@
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><ins>+namespace WTF {
+
+void printInternal(PrintStream&amp; out, JSC::InlineCallFrame::Kind kind)
+{
+    switch (kind) {
+    case JSC::InlineCallFrame::Call:
+        out.print(&quot;Call&quot;);
+        return;
+    case JSC::InlineCallFrame::Construct:
+        out.print(&quot;Construct&quot;);
+        return;
+    case JSC::InlineCallFrame::GetterCall:
+        out.print(&quot;GetterCall&quot;);
+        return;
+    case JSC::InlineCallFrame::SetterCall:
+        out.print(&quot;SetterCall&quot;);
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeOriginh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2012, 2013, 2014 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">@@ -118,13 +118,49 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct InlineCallFrame {
</span><ins>+    enum Kind {
+        Call,
+        Construct,
+        
+        // For these, the stackOffset incorporates the argument count plus the true return PC
+        // slot.
+        GetterCall,
+        SetterCall
+    };
+    
+    static Kind kindFor(CodeSpecializationKind kind)
+    {
+        switch (kind) {
+        case CodeForCall:
+            return Call;
+        case CodeForConstruct:
+            return Construct;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return Call;
+    }
+    
+    static CodeSpecializationKind specializationKindFor(Kind kind)
+    {
+        switch (kind) {
+        case Call:
+        case GetterCall:
+        case SetterCall:
+            return CodeForCall;
+        case Construct:
+            return CodeForConstruct;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return CodeForCall;
+    }
+    
</ins><span class="cx">     Vector&lt;ValueRecovery&gt; arguments; // Includes 'this'.
</span><span class="cx">     WriteBarrier&lt;ScriptExecutable&gt; executable;
</span><span class="cx">     ValueRecovery calleeRecovery;
</span><span class="cx">     CodeOrigin caller;
</span><span class="cx">     BitVector capturedVars; // Indexed by the machine call frame's variable numbering.
</span><span class="cx">     signed stackOffset : 30;
</span><del>-    bool isCall : 1;
</del><ins>+    Kind kind : 2;
</ins><span class="cx">     bool isClosureCall : 1; // If false then we know that callee/scope are constants and the DFG won't treat them as variables, i.e. they have to be recovered manually.
</span><span class="cx">     VirtualRegister argumentsRegister; // This is only set if the code uses arguments. The unmodified arguments register follows the unmodifiedArgumentsRegister() convention (see CodeBlock.h).
</span><span class="cx">     
</span><span class="lines">@@ -133,12 +169,12 @@
</span><span class="cx">     // we forgot to initialize explicitly.
</span><span class="cx">     InlineCallFrame()
</span><span class="cx">         : stackOffset(0)
</span><del>-        , isCall(false)
</del><ins>+        , kind(Call)
</ins><span class="cx">         , isClosureCall(false)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    CodeSpecializationKind specializationKind() const { return specializationFromIsCall(isCall); }
</del><ins>+    CodeSpecializationKind specializationKind() const { return specializationKindFor(kind); }
</ins><span class="cx"> 
</span><span class="cx">     JSFunction* calleeConstant() const
</span><span class="cx">     {
</span><span class="lines">@@ -209,6 +245,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><ins>+void printInternal(PrintStream&amp;, JSC::InlineCallFrame::Kind);
+
</ins><span class="cx"> template&lt;typename T&gt; struct DefaultHash;
</span><span class="cx"> template&lt;&gt; struct DefaultHash&lt;JSC::CodeOrigin&gt; {
</span><span class="cx">     typedef JSC::CodeOriginHash Hash;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;GetByIdStatus.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;AccessorCallJITStubRoutine.h&quot;
</ins><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSScope.h&quot;
</span><span class="lines">@@ -85,57 +86,6 @@
</span><span class="cx">     return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool GetByIdStatus::computeForChain(CodeBlock* profiledBlock, StringImpl* uid, PassRefPtr&lt;IntendedStructureChain&gt; passedChain)
-{
-#if ENABLE(JIT)
-    RefPtr&lt;IntendedStructureChain&gt; chain = passedChain;
-    
-    // Validate the chain. If the chain is invalid, then currently the best thing
-    // we can do is to assume that TakesSlow is true. In the future, it might be
-    // worth exploring reifying the structure chain from the structure we've got
-    // instead of using the one from the cache, since that will do the right things
-    // if the structure chain has changed. But that may be harder, because we may
-    // then end up having a different type of access altogether. And it currently
-    // does not appear to be worth it to do so -- effectively, the heuristic we
-    // have now is that if the structure chain has changed between when it was
-    // cached on in the baseline JIT and when the DFG tried to inline the access,
-    // then we fall back on a polymorphic access.
-    if (!chain-&gt;isStillValid())
-        return false;
-
-    if (chain-&gt;head()-&gt;takesSlowPathInDFGForImpureProperty())
-        return false;
-    size_t chainSize = chain-&gt;size();
-    for (size_t i = 0; i &lt; chainSize; i++) {
-        if (chain-&gt;at(i)-&gt;takesSlowPathInDFGForImpureProperty())
-            return false;
-    }
-
-    JSObject* currentObject = chain-&gt;terminalPrototype();
-    Structure* currentStructure = chain-&gt;last();
-    
-    ASSERT_UNUSED(currentObject, currentObject);
-    
-    unsigned attributesIgnored;
-    JSCell* specificValue;
-    
-    PropertyOffset offset = currentStructure-&gt;getConcurrently(
-        *profiledBlock-&gt;vm(), uid, attributesIgnored, specificValue);
-    if (currentStructure-&gt;isDictionary())
-        specificValue = 0;
-    if (!isValidOffset(offset))
-        return false;
-    
-    return appendVariant(GetByIdVariant(StructureSet(chain-&gt;head()), offset, specificValue, chain));
-#else // ENABLE(JIT)
-    UNUSED_PARAM(profiledBlock);
-    UNUSED_PARAM(uid);
-    UNUSED_PARAM(passedChain);
-    UNREACHABLE_FOR_PLATFORM();
-    return false;
-#endif // ENABLE(JIT)
-}
-
</del><span class="cx"> GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap&amp; map, unsigned bytecodeIndex, StringImpl* uid)
</span><span class="cx"> {
</span><span class="cx">     ConcurrentJITLocker locker(profiledBlock-&gt;m_lock);
</span><span class="lines">@@ -144,12 +94,13 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     result = computeForStubInfo(
</span><del>-        locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)), uid);
</del><ins>+        locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)), uid,
+        CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
</ins><span class="cx">     
</span><span class="cx">     if (!result.takesSlowPath()
</span><span class="cx">         &amp;&amp; (hasExitSite(locker, profiledBlock, bytecodeIndex)
</span><span class="cx">             || profiledBlock-&gt;likelyToTakeSlowCase(bytecodeIndex)))
</span><del>-        return GetByIdStatus(TakesSlowPath, true);
</del><ins>+        return GetByIdStatus(result.makesCalls() ? MakesCalls : TakesSlowPath, true);
</ins><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(map);
</span><span class="cx"> #endif
</span><span class="lines">@@ -162,37 +113,26 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> GetByIdStatus GetByIdStatus::computeForStubInfo(
</span><del>-    const ConcurrentJITLocker&amp;, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
-    StringImpl* uid)
</del><ins>+    const ConcurrentJITLocker&amp; locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, StringImpl* uid,
+    CallLinkStatus::ExitSiteData callExitSiteData)
</ins><span class="cx"> {
</span><span class="cx">     if (!stubInfo || !stubInfo-&gt;seen)
</span><span class="cx">         return GetByIdStatus(NoInformation);
</span><span class="cx">     
</span><del>-    if (stubInfo-&gt;resetByGC)
-        return GetByIdStatus(TakesSlowPath, true);
-
</del><span class="cx">     PolymorphicGetByIdList* list = 0;
</span><ins>+    State slowPathState = TakesSlowPath;
</ins><span class="cx">     if (stubInfo-&gt;accessType == access_get_by_id_list) {
</span><span class="cx">         list = stubInfo-&gt;u.getByIdList.list;
</span><del>-        bool makesCalls = false;
-        bool isWatched = false;
</del><span class="cx">         for (unsigned i = 0; i &lt; list-&gt;size(); ++i) {
</span><span class="cx">             const GetByIdAccess&amp; access = list-&gt;at(i);
</span><del>-            if (access.doesCalls()) {
-                makesCalls = true;
-                break;
-            }
-            if (access.isWatched()) {
-                isWatched = true;
-                continue;
-            }
</del><ins>+            if (access.doesCalls())
+                slowPathState = MakesCalls;
</ins><span class="cx">         }
</span><del>-        if (makesCalls)
-            return GetByIdStatus(MakesCalls, true);
-        if (isWatched)
-            return GetByIdStatus(TakesSlowPath, true);
</del><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (stubInfo-&gt;resetByGC)
+        return GetByIdStatus(TakesSlowPath, true);
+
</ins><span class="cx">     // Finally figure out if we can derive an access strategy.
</span><span class="cx">     GetByIdStatus result;
</span><span class="cx">     result.m_state = Simple;
</span><span class="lines">@@ -204,14 +144,14 @@
</span><span class="cx">     case access_get_by_id_self: {
</span><span class="cx">         Structure* structure = stubInfo-&gt;u.getByIdSelf.baseObjectStructure.get();
</span><span class="cx">         if (structure-&gt;takesSlowPathInDFGForImpureProperty())
</span><del>-            return GetByIdStatus(TakesSlowPath, true);
</del><ins>+            return GetByIdStatus(slowPathState, true);
</ins><span class="cx">         unsigned attributesIgnored;
</span><span class="cx">         JSCell* specificValue;
</span><span class="cx">         GetByIdVariant variant;
</span><span class="cx">         variant.m_offset = structure-&gt;getConcurrently(
</span><span class="cx">             *profiledBlock-&gt;vm(), uid, attributesIgnored, specificValue);
</span><span class="cx">         if (!isValidOffset(variant.m_offset))
</span><del>-            return GetByIdStatus(TakesSlowPath, true);
</del><ins>+            return GetByIdStatus(slowPathState, true);
</ins><span class="cx">         
</span><span class="cx">         if (structure-&gt;isDictionary())
</span><span class="cx">             specificValue = 0;
</span><span class="lines">@@ -224,8 +164,6 @@
</span><span class="cx">         
</span><span class="cx">     case access_get_by_id_list: {
</span><span class="cx">         for (unsigned listIndex = 0; listIndex &lt; list-&gt;size(); ++listIndex) {
</span><del>-            ASSERT(list-&gt;at(listIndex).isSimple());
-            
</del><span class="cx">             Structure* structure = list-&gt;at(listIndex).structure();
</span><span class="cx">             
</span><span class="cx">             // FIXME: We should assert that we never see a structure that
</span><span class="lines">@@ -235,72 +173,114 @@
</span><span class="cx">             // https://bugs.webkit.org/show_bug.cgi?id=131810
</span><span class="cx">             
</span><span class="cx">             if (structure-&gt;takesSlowPathInDFGForImpureProperty())
</span><del>-                return GetByIdStatus(TakesSlowPath, true);
</del><ins>+                return GetByIdStatus(slowPathState, true);
</ins><span class="cx">             
</span><ins>+            unsigned attributesIgnored;
+            JSCell* specificValue;
+            PropertyOffset myOffset;
+            RefPtr&lt;IntendedStructureChain&gt; chain;
+
</ins><span class="cx">             if (list-&gt;at(listIndex).chain()) {
</span><del>-                RefPtr&lt;IntendedStructureChain&gt; chain = adoptRef(new IntendedStructureChain(
</del><ins>+                chain = adoptRef(new IntendedStructureChain(
</ins><span class="cx">                     profiledBlock, structure, list-&gt;at(listIndex).chain(),
</span><span class="cx">                     list-&gt;at(listIndex).chainCount()));
</span><del>-                if (!result.computeForChain(profiledBlock, uid, chain))
-                    return GetByIdStatus(TakesSlowPath, true);
-                continue;
</del><ins>+                
+                if (!chain-&gt;isStillValid())
+                    return GetByIdStatus(slowPathState, true);
+                
+                if (chain-&gt;head()-&gt;takesSlowPathInDFGForImpureProperty())
+                    return GetByIdStatus(slowPathState, true);
+                
+                size_t chainSize = chain-&gt;size();
+                for (size_t i = 0; i &lt; chainSize; i++) {
+                    if (chain-&gt;at(i)-&gt;takesSlowPathInDFGForImpureProperty())
+                        return GetByIdStatus(slowPathState, true);
+                }
+                
+                JSObject* currentObject = chain-&gt;terminalPrototype();
+                Structure* currentStructure = chain-&gt;last();
+                
+                ASSERT_UNUSED(currentObject, currentObject);
+                
+                myOffset = currentStructure-&gt;getConcurrently(
+                    *profiledBlock-&gt;vm(), uid, attributesIgnored, specificValue);
+                if (currentStructure-&gt;isDictionary())
+                    specificValue = 0;
+            } else {
+                myOffset = structure-&gt;getConcurrently(
+                    *profiledBlock-&gt;vm(), uid, attributesIgnored, specificValue);
+                if (structure-&gt;isDictionary())
+                    specificValue = 0;
</ins><span class="cx">             }
</span><span class="cx">             
</span><del>-            unsigned attributesIgnored;
-            JSCell* specificValue;
-            PropertyOffset myOffset = structure-&gt;getConcurrently(
-                *profiledBlock-&gt;vm(), uid, attributesIgnored, specificValue);
-            if (structure-&gt;isDictionary())
-                specificValue = 0;
-            
</del><span class="cx">             if (!isValidOffset(myOffset))
</span><del>-                return GetByIdStatus(TakesSlowPath, true);
</del><ins>+                return GetByIdStatus(slowPathState, true);
</ins><span class="cx"> 
</span><del>-            bool found = false;
-            for (unsigned variantIndex = 0; variantIndex &lt; result.m_variants.size(); ++variantIndex) {
-                GetByIdVariant&amp; variant = result.m_variants[variantIndex];
-                if (variant.m_chain)
-                    continue;
</del><ins>+            if (!chain &amp;&amp; !list-&gt;at(listIndex).doesCalls()) {
+                // For non-chain, non-getter accesses, we try to do some coalescing.
+                bool found = false;
+                for (unsigned variantIndex = 0; variantIndex &lt; result.m_variants.size(); ++variantIndex) {
+                    GetByIdVariant&amp; variant = result.m_variants[variantIndex];
+                    if (variant.m_chain)
+                        continue;
</ins><span class="cx">                 
</span><del>-                if (variant.m_offset != myOffset)
-                    continue;
-
-                found = true;
-                if (variant.m_structureSet.contains(structure))
-                    break;
</del><ins>+                    if (variant.m_offset != myOffset)
+                        continue;
</ins><span class="cx">                 
</span><del>-                if (variant.m_specificValue != JSValue(specificValue))
-                    variant.m_specificValue = JSValue();
</del><ins>+                    if (variant.callLinkStatus())
+                        continue;
</ins><span class="cx">                 
</span><del>-                variant.m_structureSet.add(structure);
</del><ins>+                    found = true;
+                    if (variant.m_structureSet.contains(structure))
+                        break;
+                
+                    if (variant.m_specificValue != JSValue(specificValue))
+                        variant.m_specificValue = JSValue();
+                
+                    variant.m_structureSet.add(structure);
+                    break;
+                }
+            
+                if (found)
+                    continue;
+            }
+            
+            std::unique_ptr&lt;CallLinkStatus&gt; callLinkStatus;
+            switch (list-&gt;at(listIndex).type()) {
+            case GetByIdAccess::SimpleInline:
+            case GetByIdAccess::SimpleStub: {
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+            case GetByIdAccess::Getter: {
+                AccessorCallJITStubRoutine* stub = static_cast&lt;AccessorCallJITStubRoutine*&gt;(
+                    list-&gt;at(listIndex).stubRoutine());
+                callLinkStatus = std::make_unique&lt;CallLinkStatus&gt;(
+                    CallLinkStatus::computeFor(locker, *stub-&gt;m_callLinkInfo, callExitSiteData));
+                break;
+            }
+            case GetByIdAccess::CustomGetter:
+            case GetByIdAccess::WatchedStub: {
+                // FIXME: It would be totally sweet to support these at some point in the future.
+                // https://bugs.webkit.org/show_bug.cgi?id=133052
+                // https://bugs.webkit.org/show_bug.cgi?id=135172
+                return GetByIdStatus(slowPathState, true);
+            }
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
</ins><span class="cx">             
</span><del>-            if (found)
-                continue;
-            
-            if (!result.appendVariant(GetByIdVariant(StructureSet(structure), myOffset, specificValue)))
-                return GetByIdStatus(TakesSlowPath, true);
</del><ins>+            GetByIdVariant variant(
+                StructureSet(structure), myOffset, specificValue, chain,
+                std::move(callLinkStatus));
+            if (!result.appendVariant(variant))
+                return GetByIdStatus(slowPathState, true);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case access_get_by_id_chain: {
-        if (!stubInfo-&gt;u.getByIdChain.isDirect)
-            return GetByIdStatus(MakesCalls, true);
-        RefPtr&lt;IntendedStructureChain&gt; chain = adoptRef(new IntendedStructureChain(
-            profiledBlock,
-            stubInfo-&gt;u.getByIdChain.baseObjectStructure.get(),
-            stubInfo-&gt;u.getByIdChain.chain.get(),
-            stubInfo-&gt;u.getByIdChain.count));
-        if (result.computeForChain(profiledBlock, uid, chain))
-            return result;
-        return GetByIdStatus(TakesSlowPath, true);
-    }
-        
</del><span class="cx">     default:
</span><del>-        return GetByIdStatus(TakesSlowPath, true);
</del><ins>+        return GetByIdStatus(slowPathState, true);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -314,10 +294,18 @@
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     if (dfgBlock) {
</span><ins>+        CallLinkStatus::ExitSiteData exitSiteData;
+        {
+            ConcurrentJITLocker locker(profiledBlock-&gt;m_lock);
+            exitSiteData = CallLinkStatus::computeExitSiteData(
+                locker, profiledBlock, codeOrigin.bytecodeIndex, ExitFromFTL);
+        }
+        
</ins><span class="cx">         GetByIdStatus result;
</span><span class="cx">         {
</span><span class="cx">             ConcurrentJITLocker locker(dfgBlock-&gt;m_lock);
</span><del>-            result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid);
</del><ins>+            result = computeForStubInfo(
+                locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (result.takesSlowPath())
</span><span class="lines">@@ -370,6 +358,24 @@
</span><span class="cx">         Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool GetByIdStatus::makesCalls() const
+{
+    switch (m_state) {
+    case NoInformation:
+    case TakesSlowPath:
+        return false;
+    case Simple:
+        for (unsigned i = m_variants.size(); i--;) {
+            if (m_variants[i].callLinkStatus())
+                return true;
+        }
+        return false;
+    case MakesCalls:
+        return true;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
</ins><span class="cx"> void GetByIdStatus::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     out.print(&quot;(&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdStatush"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef GetByIdStatus_h
</span><span class="cx"> #define GetByIdStatus_h
</span><span class="cx"> 
</span><ins>+#include &quot;CallLinkStatus.h&quot;
</ins><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;ConcurrentJITLock.h&quot;
</span><span class="cx"> #include &quot;ExitingJITType.h&quot;
</span><span class="lines">@@ -83,7 +84,7 @@
</span><span class="cx">     const GetByIdVariant&amp; operator[](size_t index) const { return at(index); }
</span><span class="cx"> 
</span><span class="cx">     bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
</span><del>-    bool makesCalls() const { return m_state == MakesCalls; }
</del><ins>+    bool makesCalls() const;
</ins><span class="cx">     
</span><span class="cx">     bool wasSeenInJIT() const { return m_wasSeenInJIT; }
</span><span class="cx">     
</span><span class="lines">@@ -94,9 +95,10 @@
</span><span class="cx">     static bool hasExitSite(const ConcurrentJITLocker&amp;, CodeBlock*, unsigned bytecodeIndex, ExitingJITType = ExitFromAnything);
</span><span class="cx"> #endif
</span><span class="cx"> #if ENABLE(JIT)
</span><del>-    static GetByIdStatus computeForStubInfo(const ConcurrentJITLocker&amp;, CodeBlock*, StructureStubInfo*, StringImpl* uid);
</del><ins>+    static GetByIdStatus computeForStubInfo(
+        const ConcurrentJITLocker&amp;, CodeBlock* profiledBlock, StructureStubInfo*,
+        StringImpl* uid, CallLinkStatus::ExitSiteData);
</ins><span class="cx"> #endif
</span><del>-    bool computeForChain(CodeBlock*, StringImpl* uid, PassRefPtr&lt;IntendedStructureChain&gt;);
</del><span class="cx">     static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
</span><span class="cx">     
</span><span class="cx">     bool appendVariant(const GetByIdVariant&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdVariantcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -26,10 +26,31 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;GetByIdVariant.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CallLinkStatus.h&quot;
</ins><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+GetByIdVariant::~GetByIdVariant() { }
+
+GetByIdVariant::GetByIdVariant(const GetByIdVariant&amp; other)
+{
+    *this = other;
+}
+
+GetByIdVariant&amp; GetByIdVariant::operator=(const GetByIdVariant&amp; other)
+{
+    m_structureSet = other.m_structureSet;
+    m_chain = other.m_chain;
+    m_specificValue = other.m_specificValue;
+    m_offset = other.m_offset;
+    if (other.m_callLinkStatus)
+        m_callLinkStatus = std::make_unique&lt;CallLinkStatus&gt;(*other.m_callLinkStatus);
+    else
+        m_callLinkStatus = nullptr;
+    return *this;
+}
+
</ins><span class="cx"> void GetByIdVariant::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     dumpInContext(out, 0);
</span><span class="lines">@@ -45,7 +66,10 @@
</span><span class="cx">     out.print(
</span><span class="cx">         &quot;&lt;&quot;, inContext(structureSet(), context), &quot;, &quot;,
</span><span class="cx">         pointerDumpInContext(chain(), context), &quot;, &quot;,
</span><del>-        inContext(specificValue(), context), &quot;, &quot;, offset(), &quot;&gt;&quot;);
</del><ins>+        inContext(specificValue(), context), &quot;, &quot;, offset());
+    if (m_callLinkStatus)
+        out.print(&quot;call: &quot;, *m_callLinkStatus);
+    out.print(&quot;&gt;&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdVarianth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef GetByIdVariant_h
</span><span class="cx"> #define GetByIdVariant_h
</span><span class="cx"> 
</span><ins>+#include &quot;CallLinkStatus.h&quot;
</ins><span class="cx"> #include &quot;IntendedStructureChain.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;PropertyOffset.h&quot;
</span><span class="lines">@@ -33,6 +34,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class CallLinkStatus;
</ins><span class="cx"> class GetByIdStatus;
</span><span class="cx"> struct DumpContext;
</span><span class="cx"> 
</span><span class="lines">@@ -41,11 +43,13 @@
</span><span class="cx">     GetByIdVariant(
</span><span class="cx">         const StructureSet&amp; structureSet = StructureSet(),
</span><span class="cx">         PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(),
</span><del>-        PassRefPtr&lt;IntendedStructureChain&gt; chain = nullptr)
</del><ins>+        PassRefPtr&lt;IntendedStructureChain&gt; chain = nullptr,
+        std::unique_ptr&lt;CallLinkStatus&gt; callLinkStatus = nullptr)
</ins><span class="cx">         : m_structureSet(structureSet)
</span><span class="cx">         , m_chain(chain)
</span><span class="cx">         , m_specificValue(specificValue)
</span><span class="cx">         , m_offset(offset)
</span><ins>+        , m_callLinkStatus(std::move(callLinkStatus))
</ins><span class="cx">     {
</span><span class="cx">         if (!structureSet.size()) {
</span><span class="cx">             ASSERT(offset == invalidOffset);
</span><span class="lines">@@ -54,12 +58,18 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    ~GetByIdVariant();
+    
+    GetByIdVariant(const GetByIdVariant&amp;);
+    GetByIdVariant&amp; operator=(const GetByIdVariant&amp;);
+    
</ins><span class="cx">     bool isSet() const { return !!m_structureSet.size(); }
</span><span class="cx">     bool operator!() const { return !isSet(); }
</span><span class="cx">     const StructureSet&amp; structureSet() const { return m_structureSet; }
</span><span class="cx">     IntendedStructureChain* chain() const { return const_cast&lt;IntendedStructureChain*&gt;(m_chain.get()); }
</span><span class="cx">     JSValue specificValue() const { return m_specificValue; }
</span><span class="cx">     PropertyOffset offset() const { return m_offset; }
</span><ins>+    CallLinkStatus* callLinkStatus() const { return m_callLinkStatus.get(); }
</ins><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     void dumpInContext(PrintStream&amp;, DumpContext*) const;
</span><span class="lines">@@ -71,6 +81,7 @@
</span><span class="cx">     RefPtr&lt;IntendedStructureChain&gt; m_chain;
</span><span class="cx">     JSValue m_specificValue;
</span><span class="cx">     PropertyOffset m_offset;
</span><ins>+    std::unique_ptr&lt;CallLinkStatus&gt; m_callLinkStatus;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicGetByIdListcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicGetByIdList.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicGetByIdList.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicGetByIdList.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -58,28 +58,12 @@
</span><span class="cx">     
</span><span class="cx">     GetByIdAccess result;
</span><span class="cx">     
</span><del>-    switch (stubInfo.accessType) {
-    case access_get_by_id_self:
-        result.m_type = SimpleInline;
-        result.m_structure.copyFrom(stubInfo.u.getByIdSelf.baseObjectStructure);
-        result.m_stubRoutine = JITStubRoutine::createSelfManagedRoutine(initialSlowPath);
-        break;
-        
-    case access_get_by_id_chain:
-        result.m_structure.copyFrom(stubInfo.u.getByIdChain.baseObjectStructure);
-        result.m_chain.copyFrom(stubInfo.u.getByIdChain.chain);
-        result.m_chainCount = stubInfo.u.getByIdChain.count;
-        result.m_stubRoutine = stubInfo.stubRoutine;
-        if (stubInfo.u.getByIdChain.isDirect)
-            result.m_type = SimpleStub;
-        else
-            result.m_type = Getter;
-        break;
-        
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-    }
</del><ins>+    RELEASE_ASSERT(stubInfo.accessType == access_get_by_id_self);
</ins><span class="cx">     
</span><ins>+    result.m_type = SimpleInline;
+    result.m_structure.copyFrom(stubInfo.u.getByIdSelf.baseObjectStructure);
+    result.m_stubRoutine = JITStubRoutine::createSelfManagedRoutine(initialSlowPath);
+    
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -109,7 +93,6 @@
</span><span class="cx">     
</span><span class="cx">     ASSERT(
</span><span class="cx">         stubInfo.accessType == access_get_by_id_self
</span><del>-        || stubInfo.accessType == access_get_by_id_chain
</del><span class="cx">         || stubInfo.accessType == access_unset);
</span><span class="cx">     
</span><span class="cx">     PolymorphicGetByIdList* result = new PolymorphicGetByIdList(stubInfo);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeSpeculatedTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx"> static const SpeculatedType SpecStringIdent        = 0x00010000; // It's definitely a JSString, and it's an identifier.
</span><span class="cx"> static const SpeculatedType SpecStringVar          = 0x00020000; // It's definitely a JSString, and it's not an identifier.
</span><span class="cx"> static const SpeculatedType SpecString             = 0x00030000; // It's definitely a JSString.
</span><del>-static const SpeculatedType SpecCellOther          = 0x00040000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
</del><ins>+static const SpeculatedType SpecCellOther          = 0x00040000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078
</ins><span class="cx"> static const SpeculatedType SpecCell               = 0x0007ffff; // It's definitely a JSCell.
</span><span class="cx"> static const SpeculatedType SpecInt32              = 0x00200000; // It's definitely an Int32.
</span><span class="cx"> static const SpeculatedType SpecInt52              = 0x00400000; // It's definitely an Int52 and we intend it to unbox it.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -49,7 +49,6 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     case access_get_by_id_self:
</span><del>-    case access_get_by_id_chain:
</del><span class="cx">     case access_put_by_id_transition_normal:
</span><span class="cx">     case access_put_by_id_transition_direct:
</span><span class="cx">     case access_put_by_id_replace:
</span><span class="lines">@@ -68,11 +67,6 @@
</span><span class="cx">         if (!Heap::isMarked(u.getByIdSelf.baseObjectStructure.get()))
</span><span class="cx">             return false;
</span><span class="cx">         break;
</span><del>-    case access_get_by_id_chain:
-        if (!Heap::isMarked(u.getByIdChain.baseObjectStructure.get())
-            || !Heap::isMarked(u.getByIdChain.chain.get()))
-            return false;
-        break;
</del><span class="cx">     case access_get_by_id_list: {
</span><span class="cx">         if (!u.getByIdList.list-&gt;visitWeak(repatchBuffer))
</span><span class="cx">             return false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -47,7 +47,6 @@
</span><span class="cx"> 
</span><span class="cx"> enum AccessType {
</span><span class="cx">     access_get_by_id_self,
</span><del>-    access_get_by_id_chain,
</del><span class="cx">     access_get_by_id_list,
</span><span class="cx">     access_put_by_id_transition_normal,
</span><span class="cx">     access_put_by_id_transition_direct,
</span><span class="lines">@@ -61,7 +60,6 @@
</span><span class="cx"> {
</span><span class="cx">     switch (accessType) {
</span><span class="cx">     case access_get_by_id_self:
</span><del>-    case access_get_by_id_chain:
</del><span class="cx">     case access_get_by_id_list:
</span><span class="cx">         return true;
</span><span class="cx">     default:
</span><span class="lines">@@ -107,16 +105,6 @@
</span><span class="cx">         u.getByIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void initGetByIdChain(VM&amp; vm, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain, unsigned count, bool isDirect)
-    {
-        accessType = access_get_by_id_chain;
-
-        u.getByIdChain.baseObjectStructure.set(vm, owner, baseObjectStructure);
-        u.getByIdChain.chain.set(vm, owner, chain);
-        u.getByIdChain.count = count;
-        u.getByIdChain.isDirect = isDirect;
-    }
-
</del><span class="cx">     void initGetByIdList(PolymorphicGetByIdList* list)
</span><span class="cx">     {
</span><span class="cx">         accessType = access_get_by_id_list;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -50,6 +50,8 @@
</span><span class="cx">     macro(Butterfly_arrayBuffer) \
</span><span class="cx">     macro(Butterfly_publicLength) \
</span><span class="cx">     macro(Butterfly_vectorLength) \
</span><ins>+    macro(GetterSetter_getter) \
+    macro(GetterSetter_setter) \
</ins><span class="cx">     macro(JSArrayBufferView_length) \
</span><span class="cx">     macro(JSArrayBufferView_mode) \
</span><span class="cx">     macro(JSArrayBufferView_vector) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1433,6 +1433,8 @@
</span><span class="cx">         break;
</span><span class="cx">         
</span><span class="cx">     case GetCallee:
</span><ins>+    case GetGetter:
+    case GetSetter:
</ins><span class="cx">         forNode(node).setType(SpecFunction);
</span><span class="cx">         break;
</span><span class="cx">         
</span><span class="lines">@@ -1658,6 +1660,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><ins>+    case GetGetterSetterByOffset: {
+        forNode(node).set(m_graph, m_graph.m_vm.getterSetterStructure.get());
+        break;
+    }
+        
</ins><span class="cx">     case MultiGetByOffset: {
</span><span class="cx">         AbstractValue&amp; value = forNode(node-&gt;child1());
</span><span class="cx">         ASSERT(!(value.m_type &amp; ~SpecCell)); // Edge filtering should have already ensured this.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -158,9 +158,6 @@
</span><span class="cx">     // should just trust the array profile.
</span><span class="cx">     
</span><span class="cx">     switch (type()) {
</span><del>-    case Array::Unprofiled:
-        return ArrayMode(Array::ForceExit);
-        
</del><span class="cx">     case Array::Undecided:
</span><span class="cx">         if (!value)
</span><span class="cx">             return withType(Array::ForceExit);
</span><span class="lines">@@ -189,6 +186,7 @@
</span><span class="cx">             return withConversion(Array::RageConvert);
</span><span class="cx">         return *this;
</span><span class="cx">         
</span><ins>+    case Array::Unprofiled:
</ins><span class="cx">     case Array::SelectUsingPredictions: {
</span><span class="cx">         base &amp;= ~SpecOther;
</span><span class="cx">         
</span><span class="lines">@@ -239,6 +237,8 @@
</span><span class="cx">         if (isFloat64ArraySpeculation(base))
</span><span class="cx">             return result.withType(Array::Float64Array);
</span><span class="cx"> 
</span><ins>+        if (type() == Array::Unprofiled)
+            return ArrayMode(Array::ForceExit);
</ins><span class="cx">         return ArrayMode(Array::Generic);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -171,21 +171,21 @@
</span><span class="cx">     bool handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis);
</span><span class="cx">     
</span><span class="cx">     // Handle calls. This resolves issues surrounding inlining and intrinsics.
</span><ins>+    void handleCall(
+        int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize,
+        Node* callTarget, int argCount, int registerOffset, CallLinkStatus);
</ins><span class="cx">     void handleCall(int result, NodeType op, CodeSpecializationKind, unsigned instructionSize, int callee, int argCount, int registerOffset);
</span><span class="cx">     void handleCall(Instruction* pc, NodeType op, CodeSpecializationKind);
</span><span class="cx">     void emitFunctionChecks(const CallLinkStatus&amp;, Node* callTarget, int registerOffset, CodeSpecializationKind);
</span><span class="cx">     void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind);
</span><span class="cx">     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
</span><del>-    bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp;, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind);
</del><ins>+    bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp;, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind);
</ins><span class="cx">     // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
</span><span class="cx">     bool handleIntrinsic(int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction);
</span><span class="cx">     bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType);
</span><span class="cx">     bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind);
</span><span class="cx">     Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
</span><del>-    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset);
-    void handleGetByOffset(
-        int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
-        PropertyOffset);
</del><ins>+    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType op = GetByOffset);
</ins><span class="cx">     void handleGetById(
</span><span class="cx">         int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
</span><span class="cx">         const GetByIdStatus&amp;);
</span><span class="lines">@@ -811,11 +811,11 @@
</span><span class="cx">         m_numPassedVarArgs++;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Node* addCall(int result, NodeType op, int callee, int argCount, int registerOffset)
</del><ins>+    Node* addCall(int result, NodeType op, Node* callee, int argCount, int registerOffset)
</ins><span class="cx">     {
</span><span class="cx">         SpeculatedType prediction = getPrediction();
</span><span class="cx">         
</span><del>-        addVarArgChild(get(VirtualRegister(callee)));
</del><ins>+        addVarArgChild(callee);
</ins><span class="cx">         size_t parameterSlots = JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + argCount;
</span><span class="cx">         if (parameterSlots &gt; m_parameterSlots)
</span><span class="cx">             m_parameterSlots = parameterSlots;
</span><span class="lines">@@ -1122,7 +1122,7 @@
</span><span class="cx">             VirtualRegister returnValueVR,
</span><span class="cx">             VirtualRegister inlineCallFrameStart,
</span><span class="cx">             int argumentCountIncludingThis,
</span><del>-            CodeSpecializationKind);
</del><ins>+            InlineCallFrame::Kind);
</ins><span class="cx">         
</span><span class="cx">         ~InlineStackEntry()
</span><span class="cx">         {
</span><span class="lines">@@ -1205,26 +1205,35 @@
</span><span class="cx">     int result, NodeType op, CodeSpecializationKind kind, unsigned instructionSize,
</span><span class="cx">     int callee, int argumentCountIncludingThis, int registerOffset)
</span><span class="cx"> {
</span><ins>+    Node* callTarget = get(VirtualRegister(callee));
+    
+    CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
+        m_inlineStackTop-&gt;m_profiledBlock, currentCodeOrigin(),
+        m_inlineStackTop-&gt;m_callLinkInfos, m_callContextMap);
+    
+    handleCall(
+        result, op, InlineCallFrame::kindFor(kind), instructionSize, callTarget,
+        argumentCountIncludingThis, registerOffset, callLinkStatus);
+}
+    
+void ByteCodeParser::handleCall(
+    int result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize,
+    Node* callTarget, int argumentCountIncludingThis, int registerOffset,
+    CallLinkStatus callLinkStatus)
+{
</ins><span class="cx">     ASSERT(registerOffset &lt;= 0);
</span><ins>+    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
</ins><span class="cx">     
</span><del>-    Node* callTarget = get(VirtualRegister(callee));
-    
-    CallLinkStatus callLinkStatus;
-
</del><span class="cx">     if (m_graph.isConstant(callTarget)) {
</span><span class="cx">         callLinkStatus = CallLinkStatus(
</span><span class="cx">             m_graph.valueOfJSConstant(callTarget)).setIsProved(true);
</span><del>-    } else {
-        callLinkStatus = CallLinkStatus::computeFor(
-            m_inlineStackTop-&gt;m_profiledBlock, currentCodeOrigin(),
-            m_inlineStackTop-&gt;m_callLinkInfos, m_callContextMap);
</del><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (!callLinkStatus.canOptimize()) {
</span><span class="cx">         // Oddly, this conflates calls that haven't executed with calls that behaved sufficiently polymorphically
</span><span class="cx">         // that we cannot optimize them.
</span><span class="cx">         
</span><del>-        addCall(result, op, callee, argumentCountIncludingThis, registerOffset);
</del><ins>+        addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -1232,28 +1241,28 @@
</span><span class="cx">     SpeculatedType prediction = getPrediction();
</span><span class="cx"> 
</span><span class="cx">     if (InternalFunction* function = callLinkStatus.internalFunction()) {
</span><del>-        if (handleConstantInternalFunction(result, function, registerOffset, argumentCountIncludingThis, prediction, kind)) {
</del><ins>+        if (handleConstantInternalFunction(result, function, registerOffset, argumentCountIncludingThis, prediction, specializationKind)) {
</ins><span class="cx">             // This phantoming has to be *after* the code for the intrinsic, to signify that
</span><span class="cx">             // the inputs must be kept alive whatever exits the intrinsic may do.
</span><span class="cx">             addToGraph(Phantom, callTarget);
</span><del>-            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, kind);
</del><ins>+            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, specializationKind);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         // Can only handle this using the generic call handler.
</span><del>-        addCall(result, op, callee, argumentCountIncludingThis, registerOffset);
</del><ins>+        addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    Intrinsic intrinsic = callLinkStatus.intrinsicFor(kind);
</del><ins>+    Intrinsic intrinsic = callLinkStatus.intrinsicFor(specializationKind);
</ins><span class="cx">     if (intrinsic != NoIntrinsic) {
</span><del>-        emitFunctionChecks(callLinkStatus, callTarget, registerOffset, kind);
</del><ins>+        emitFunctionChecks(callLinkStatus, callTarget, registerOffset, specializationKind);
</ins><span class="cx">             
</span><span class="cx">         if (handleIntrinsic(result, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) {
</span><span class="cx">             // This phantoming has to be *after* the code for the intrinsic, to signify that
</span><span class="cx">             // the inputs must be kept alive whatever exits the intrinsic may do.
</span><span class="cx">             addToGraph(Phantom, callTarget);
</span><del>-            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, kind);
</del><ins>+            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, specializationKind);
</ins><span class="cx">             if (m_graph.compilation())
</span><span class="cx">                 m_graph.compilation()-&gt;noticeInlinedCall();
</span><span class="cx">             return;
</span><span class="lines">@@ -1264,7 +1273,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    addCall(result, op, callee, argumentCountIncludingThis, registerOffset);
</del><ins>+    addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ByteCodeParser::emitFunctionChecks(const CallLinkStatus&amp; callLinkStatus, Node* callTarget, int registerOffset, CodeSpecializationKind kind)
</span><span class="lines">@@ -1299,10 +1308,12 @@
</span><span class="cx">         addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp; callLinkStatus, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind)
</del><ins>+bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp; callLinkStatus, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind)
</ins><span class="cx"> {
</span><span class="cx">     static const bool verbose = false;
</span><span class="cx">     
</span><ins>+    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
+    
</ins><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Considering inlining &quot;, callLinkStatus, &quot; into &quot;, currentCodeOrigin(), &quot;\n&quot;);
</span><span class="cx">     
</span><span class="lines">@@ -1335,14 +1346,14 @@
</span><span class="cx">     // if we had a static proof of what was being called; this might happen for example if you call a
</span><span class="cx">     // global function, where watchpointing gives us static information. Overall, it's a rare case
</span><span class="cx">     // because we expect that any hot callees would have already been compiled.
</span><del>-    CodeBlock* codeBlock = executable-&gt;baselineCodeBlockFor(kind);
</del><ins>+    CodeBlock* codeBlock = executable-&gt;baselineCodeBlockFor(specializationKind);
</ins><span class="cx">     if (!codeBlock) {
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;    Failing because no code block available.\n&quot;);
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx">     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
</span><del>-        codeBlock, kind, callLinkStatus.isClosureCall());
</del><ins>+        codeBlock, specializationKind, callLinkStatus.isClosureCall());
</ins><span class="cx">     if (!canInline(capabilityLevel)) {
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;    Failing because the function is not inlineable.\n&quot;);
</span><span class="lines">@@ -1394,7 +1405,7 @@
</span><span class="cx">     // Now we know without a doubt that we are committed to inlining. So begin the process
</span><span class="cx">     // by checking the callee (if necessary) and making sure that arguments and the callee
</span><span class="cx">     // are flushed.
</span><del>-    emitFunctionChecks(callLinkStatus, callTargetNode, registerOffset, kind);
</del><ins>+    emitFunctionChecks(callLinkStatus, callTargetNode, registerOffset, specializationKind);
</ins><span class="cx">     
</span><span class="cx">     // FIXME: Don't flush constants!
</span><span class="cx">     
</span><span class="lines">@@ -1873,14 +1884,14 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset)
</del><ins>+Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
</ins><span class="cx"> {
</span><span class="cx">     Node* propertyStorage;
</span><span class="cx">     if (isInlineOffset(offset))
</span><span class="cx">         propertyStorage = base;
</span><span class="cx">     else
</span><span class="cx">         propertyStorage = addToGraph(GetButterfly, base);
</span><del>-    Node* getByOffset = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), propertyStorage, base);
</del><ins>+    Node* getByOffset = addToGraph(op, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), propertyStorage, base);
</ins><span class="cx"> 
</span><span class="cx">     StorageAccessData storageAccessData;
</span><span class="cx">     storageAccessData.offset = offset;
</span><span class="lines">@@ -1890,13 +1901,6 @@
</span><span class="cx">     return getByOffset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ByteCodeParser::handleGetByOffset(
-    int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber,
-    PropertyOffset offset)
-{
-    set(VirtualRegister(destinationOperand), handleGetByOffset(prediction, base, identifierNumber, offset));
-}
-
</del><span class="cx"> Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
</span><span class="cx"> {
</span><span class="cx">     Node* propertyStorage;
</span><span class="lines">@@ -1933,18 +1937,19 @@
</span><span class="cx">     int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber,
</span><span class="cx">     const GetByIdStatus&amp; getByIdStatus)
</span><span class="cx"> {
</span><ins>+    NodeType getById = getByIdStatus.makesCalls() ? GetByIdFlush : GetById;
+    
</ins><span class="cx">     if (!getByIdStatus.isSimple() || !Options::enableAccessInlining()) {
</span><span class="cx">         set(VirtualRegister(destinationOperand),
</span><del>-            addToGraph(
-                getByIdStatus.makesCalls() ? GetByIdFlush : GetById,
-                OpInfo(identifierNumber), OpInfo(prediction), base));
</del><ins>+            addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (getByIdStatus.numVariants() &gt; 1) {
</span><del>-        if (!isFTL(m_graph.m_plan.mode) || !Options::enablePolymorphicAccessInlining()) {
</del><ins>+        if (getByIdStatus.makesCalls() || !isFTL(m_graph.m_plan.mode)
+            || !Options::enablePolymorphicAccessInlining()) {
</ins><span class="cx">             set(VirtualRegister(destinationOperand),
</span><del>-                addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
</del><ins>+                addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -1977,7 +1982,7 @@
</span><span class="cx">     if (m_graph.compilation())
</span><span class="cx">         m_graph.compilation()-&gt;noticeInlinedGetById();
</span><span class="cx">     
</span><del>-    Node* originalBaseForBaselineJIT = base;
</del><ins>+    Node* originalBase = base;
</ins><span class="cx">                 
</span><span class="cx">     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
</span><span class="cx">     
</span><span class="lines">@@ -1992,18 +1997,59 @@
</span><span class="cx">     // on something other than the base following the CheckStructure on base, or if the
</span><span class="cx">     // access was compiled to a WeakJSConstant specific value, in which case we might not
</span><span class="cx">     // have any explicit use of the base at all.
</span><del>-    if (variant.specificValue() || originalBaseForBaselineJIT != base)
-        addToGraph(Phantom, originalBaseForBaselineJIT);
</del><ins>+    if (variant.specificValue() || originalBase != base)
+        addToGraph(Phantom, originalBase);
</ins><span class="cx">     
</span><del>-    if (variant.specificValue()) {
-        ASSERT(variant.specificValue().isCell());
-        
-        set(VirtualRegister(destinationOperand), cellConstant(variant.specificValue().asCell()));
</del><ins>+    Node* loadedValue;
+    if (variant.specificValue())
+        loadedValue = cellConstant(variant.specificValue().asCell());
+    else {
+        loadedValue = handleGetByOffset(
+            prediction, base, identifierNumber, variant.offset(),
+            variant.callLinkStatus() ? GetGetterSetterByOffset : GetByOffset);
+    }
+    
+    if (!variant.callLinkStatus()) {
+        set(VirtualRegister(destinationOperand), loadedValue);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    handleGetByOffset(
-        destinationOperand, prediction, base, identifierNumber, variant.offset());
</del><ins>+    Node* getter = addToGraph(GetGetter, loadedValue);
+    
+    // Make a call. We don't try to get fancy with using the smallest operand number because
+    // the stack layout phase should compress the stack anyway.
+    
+    unsigned numberOfParameters = 0;
+    numberOfParameters++; // The 'this' argument.
+    numberOfParameters++; // True return PC.
+    
+    // Start with a register offset that corresponds to the last in-use register.
+    int registerOffset = virtualRegisterForLocal(
+        m_inlineStackTop-&gt;m_profiledBlock-&gt;m_numCalleeRegisters - 1).offset();
+    registerOffset -= numberOfParameters;
+    registerOffset -= JSStack::CallFrameHeaderSize;
+    
+    // Get the alignment right.
+    registerOffset = -WTF::roundUpToMultipleOf(
+        stackAlignmentRegisters(),
+        -registerOffset);
+    
+    ensureLocals(
+        m_inlineStackTop-&gt;remapOperand(
+            VirtualRegister(registerOffset)).toLocal());
+    
+    // Issue SetLocals. This has two effects:
+    // 1) That's how handleCall() sees the arguments.
+    // 2) If we inline then this ensures that the arguments are flushed so that if you use
+    //    the dreaded arguments object on the getter, the right things happen. Well, sort of -
+    //    since we only really care about 'this' in this case. But we're not going to take that
+    //    shortcut.
+    int nextRegister = registerOffset + JSStack::CallFrameHeaderSize;
+    set(VirtualRegister(nextRegister++), originalBase, ImmediateNakedSet);
+    
+    handleCall(
+        destinationOperand, Call, InlineCallFrame::GetterCall, OPCODE_LENGTH(op_get_by_id),
+        getter, numberOfParameters - 1, registerOffset, *variant.callLinkStatus());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ByteCodeParser::emitPutById(
</span><span class="lines">@@ -2655,7 +2701,7 @@
</span><span class="cx">         // === Property access operations ===
</span><span class="cx"> 
</span><span class="cx">         case op_get_by_val: {
</span><del>-            SpeculatedType prediction = getPrediction();
</del><ins>+            SpeculatedType prediction = getPredictionWithoutOSRExit();
</ins><span class="cx">             
</span><span class="cx">             Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             ArrayMode arrayMode = getArrayModeConsideringSlowPath(currentInstruction[4].u.arrayProfile, Array::Read);
</span><span class="lines">@@ -3074,12 +3120,12 @@
</span><span class="cx"> 
</span><span class="cx">             UNUSED_PARAM(watchpoints); // We will use this in the future. For now we set it as a way of documenting the fact that that's what index 5 is in GlobalVar mode.
</span><span class="cx"> 
</span><del>-            SpeculatedType prediction = getPrediction();
</del><span class="cx">             JSGlobalObject* globalObject = m_inlineStackTop-&gt;m_codeBlock-&gt;globalObject();
</span><span class="cx"> 
</span><span class="cx">             switch (resolveType) {
</span><span class="cx">             case GlobalProperty:
</span><span class="cx">             case GlobalPropertyWithVarInjectionChecks: {
</span><ins>+                SpeculatedType prediction = getPrediction();
</ins><span class="cx">                 GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid);
</span><span class="cx">                 if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) {
</span><span class="cx">                     set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope))));
</span><span class="lines">@@ -3101,6 +3147,7 @@
</span><span class="cx">                 JSValue specificValue =
</span><span class="cx">                     watchpointSet ? watchpointSet-&gt;inferredValue() : JSValue();
</span><span class="cx">                 if (!specificValue) {
</span><ins>+                    SpeculatedType prediction = getPrediction();
</ins><span class="cx">                     set(VirtualRegister(dst), addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction)));
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="lines">@@ -3127,6 +3174,7 @@
</span><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><ins>+                SpeculatedType prediction = getPrediction();
</ins><span class="cx">                 set(VirtualRegister(dst),
</span><span class="cx">                     addToGraph(GetClosureVar, OpInfo(operand), OpInfo(prediction), 
</span><span class="cx">                         addToGraph(GetClosureRegisters, scopeNode)));
</span><span class="lines">@@ -3397,7 +3445,7 @@
</span><span class="cx">     VirtualRegister returnValueVR,
</span><span class="cx">     VirtualRegister inlineCallFrameStart,
</span><span class="cx">     int argumentCountIncludingThis,
</span><del>-    CodeSpecializationKind kind)
</del><ins>+    InlineCallFrame::Kind kind)
</ins><span class="cx">     : m_byteCodeParser(byteCodeParser)
</span><span class="cx">     , m_codeBlock(codeBlock)
</span><span class="cx">     , m_profiledBlock(profiledBlock)
</span><span class="lines">@@ -3456,7 +3504,7 @@
</span><span class="cx">             m_inlineCallFrame-&gt;isClosureCall = true;
</span><span class="cx">         m_inlineCallFrame-&gt;caller = byteCodeParser-&gt;currentCodeOrigin();
</span><span class="cx">         m_inlineCallFrame-&gt;arguments.resize(argumentCountIncludingThis); // Set the number of arguments including this, but don't configure the value recoveries, yet.
</span><del>-        m_inlineCallFrame-&gt;isCall = isCall(kind);
</del><ins>+        m_inlineCallFrame-&gt;kind = kind;
</ins><span class="cx">         
</span><span class="cx">         if (m_inlineCallFrame-&gt;caller.inlineCallFrame)
</span><span class="cx">             m_inlineCallFrame-&gt;capturedVars = m_inlineCallFrame-&gt;caller.inlineCallFrame-&gt;capturedVars;
</span><span class="lines">@@ -3695,7 +3743,7 @@
</span><span class="cx">     
</span><span class="cx">     InlineStackEntry inlineStackEntry(
</span><span class="cx">         this, m_codeBlock, m_profiledBlock, 0, 0, VirtualRegister(), VirtualRegister(),
</span><del>-        m_codeBlock-&gt;numParameters(), CodeForCall);
</del><ins>+        m_codeBlock-&gt;numParameters(), InlineCallFrame::Call);
</ins><span class="cx">     
</span><span class="cx">     parseCodeBlock();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCSEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -690,6 +690,40 @@
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    Node* getGetterSetterByOffsetLoadElimination(unsigned identifierNumber, Node* base)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            Node* node = m_currentBlock-&gt;at(i);
+            if (node == base)
+                break;
+
+            switch (node-&gt;op()) {
+            case GetGetterSetterByOffset:
+                if (node-&gt;child2() == base
+                    &amp;&amp; m_graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber == identifierNumber)
+                    return node;
+                break;
+                    
+            case PutByValDirect:
+            case PutByVal:
+            case PutByValAlias:
+                if (m_graph.byValIsPure(node)) {
+                    // If PutByVal speculates that it's accessing an array with an
+                    // integer index, then it's impossible for it to cause a structure
+                    // change.
+                    break;
+                }
+                return 0;
+                
+            default:
+                if (m_graph.clobbersWorld(node))
+                    return 0;
+                break;
+            }
+        }
+        return 0;
+    }
+    
</ins><span class="cx">     Node* putByOffsetStoreElimination(unsigned identifierNumber, Node* child1)
</span><span class="cx">     {
</span><span class="cx">         for (unsigned i = m_indexInBlock; i--;) {
</span><span class="lines">@@ -845,25 +879,18 @@
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Node* getTypedArrayByteOffsetLoadElimination(Node* child1)
</del><ins>+    Node* getInternalFieldLoadElimination(NodeType op, Node* child1)
</ins><span class="cx">     {
</span><span class="cx">         for (unsigned i = m_indexInBlock; i--;) {
</span><span class="cx">             Node* node = m_currentBlock-&gt;at(i);
</span><span class="cx">             if (node == child1) 
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><del>-            switch (node-&gt;op()) {
-            case GetTypedArrayByteOffset: {
-                if (node-&gt;child1() == child1)
-                    return node;
-                break;
-            }
</del><ins>+            if (node-&gt;op() == op &amp;&amp; node-&gt;child1() == child1)
+                return node;
</ins><span class="cx"> 
</span><del>-            default:
-                if (m_graph.clobbersWorld(node))
-                    return 0;
-                break;
-            }
</del><ins>+            if (m_graph.clobbersWorld(node))
+                return 0;
</ins><span class="cx">         }
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="lines">@@ -1437,10 +1464,12 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><del>-        case GetTypedArrayByteOffset: {
</del><ins>+        case GetTypedArrayByteOffset:
+        case GetGetter:
+        case GetSetter: {
</ins><span class="cx">             if (cseMode == StoreElimination)
</span><span class="cx">                 break;
</span><del>-            setReplacement(getTypedArrayByteOffsetLoadElimination(node-&gt;child1().node()));
</del><ins>+            setReplacement(getInternalFieldLoadElimination(node-&gt;op(), node-&gt;child1().node()));
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1456,6 +1485,12 @@
</span><span class="cx">             setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber, node-&gt;child2().node()));
</span><span class="cx">             break;
</span><span class="cx">             
</span><ins>+        case GetGetterSetterByOffset:
+            if (cseMode == StoreElimination)
+                break;
+            setReplacement(getGetterSetterByOffsetLoadElimination(m_graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber, node-&gt;child2().node()));
+            break;
+            
</ins><span class="cx">         case MultiGetByOffset:
</span><span class="cx">             if (cseMode == StoreElimination)
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -215,6 +215,14 @@
</span><span class="cx">         write(World);
</span><span class="cx">         return;
</span><span class="cx">         
</span><ins>+    case GetGetter:
+        read(GetterSetter_getter);
+        return;
+        
+    case GetSetter:
+        read(GetterSetter_setter);
+        return;
+        
</ins><span class="cx">     case GetCallee:
</span><span class="cx">         read(AbstractHeap(Variables, JSStack::Callee));
</span><span class="cx">         return;
</span><span class="lines">@@ -484,6 +492,7 @@
</span><span class="cx">         return;
</span><span class="cx">         
</span><span class="cx">     case GetByOffset:
</span><ins>+    case GetGetterSetterByOffset:
</ins><span class="cx">         read(AbstractHeap(NamedProperties, graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber));
</span><span class="cx">         return;
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -494,6 +494,11 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case GetByVal: {
</span><ins>+            if (!node-&gt;prediction()) {
+                m_insertionSet.insertNode(
+                    m_indexInBlock, SpecNone, ForceOSRExit, node-&gt;origin);
+            }
+            
</ins><span class="cx">             node-&gt;setArrayMode(
</span><span class="cx">                 node-&gt;arrayMode().refine(
</span><span class="cx">                     m_graph, node,
</span><span class="lines">@@ -877,7 +882,9 @@
</span><span class="cx">         case GetClosureRegisters:
</span><span class="cx">         case SkipTopScope:
</span><span class="cx">         case SkipScope:
</span><del>-        case GetScope: {
</del><ins>+        case GetScope:
+        case GetGetter:
+        case GetSetter: {
</ins><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -937,7 +944,8 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><del>-        case GetByOffset: {
</del><ins>+        case GetByOffset:
+        case GetGetterSetterByOffset: {
</ins><span class="cx">             if (!node-&gt;child1()-&gt;hasStorageResult())
</span><span class="cx">                 fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child2());
</span><span class="lines">@@ -1035,6 +1043,8 @@
</span><span class="cx">             Node* globalObjectNode = m_insertionSet.insertNode(
</span><span class="cx">                 m_indexInBlock, SpecNone, WeakJSConstant, node-&gt;origin, 
</span><span class="cx">                 OpInfo(m_graph.globalObjectFor(node-&gt;origin.semantic)));
</span><ins>+            // FIXME: This probably shouldn't have an unconditional barrier.
+            // https://bugs.webkit.org/show_bug.cgi?id=133104
</ins><span class="cx">             Node* barrierNode = m_graph.addNode(
</span><span class="cx">                 SpecNone, StoreBarrier, m_currentNode-&gt;origin, 
</span><span class="cx">                 Edge(globalObjectNode, KnownCellUse));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -417,7 +417,7 @@
</span><span class="cx">     m_jitCode-&gt;shrinkToFit();
</span><span class="cx">     codeBlock()-&gt;shrinkToFit(CodeBlock::LateShrink);
</span><span class="cx">     
</span><del>-    linkBuffer-&gt;link(m_callArityFixup, FunctionPtr((m_vm-&gt;getCTIStub(arityFixup)).code().executableAddress()));
</del><ins>+    linkBuffer-&gt;link(m_callArityFixup, FunctionPtr((m_vm-&gt;getCTIStub(arityFixupGenerator)).code().executableAddress()));
</ins><span class="cx">     
</span><span class="cx">     disassemble(*linkBuffer);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1157,7 +1157,7 @@
</span><span class="cx">     
</span><span class="cx">     bool hasStorageAccessData()
</span><span class="cx">     {
</span><del>-        return op() == GetByOffset || op() == PutByOffset;
</del><ins>+        return op() == GetByOffset || op() == GetGetterSetterByOffset || op() == PutByOffset;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     unsigned storageAccessDataIndex()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -181,7 +181,10 @@
</span><span class="cx">     macro(GetIndexedPropertyStorage, NodeResultStorage) \
</span><span class="cx">     macro(ConstantStoragePointer, NodeResultStorage) \
</span><span class="cx">     macro(TypedArrayWatchpoint, NodeMustGenerate) \
</span><ins>+    macro(GetGetter, NodeResultJS) \
+    macro(GetSetter, NodeResultJS) \
</ins><span class="cx">     macro(GetByOffset, NodeResultJS) \
</span><ins>+    macro(GetGetterSetterByOffset, NodeResultJS) \
</ins><span class="cx">     macro(MultiGetByOffset, NodeResultJS) \
</span><span class="cx">     macro(PutByOffset, NodeMustGenerate) \
</span><span class="cx">     macro(MultiPutByOffset, NodeMustGenerate) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommoncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -108,12 +108,44 @@
</span><span class="cx">         InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
</span><span class="cx">         CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(codeOrigin);
</span><span class="cx">         CodeBlock* baselineCodeBlockForCaller = jit.baselineCodeBlockFor(inlineCallFrame-&gt;caller);
</span><ins>+        void* jumpTarget;
+        void* trueReturnPC = nullptr;
+        
</ins><span class="cx">         unsigned callBytecodeIndex = inlineCallFrame-&gt;caller.bytecodeIndex;
</span><del>-        CallLinkInfo* callLinkInfo =
-            baselineCodeBlockForCaller-&gt;getCallLinkInfoForBytecodeIndex(callBytecodeIndex);
-        RELEASE_ASSERT(callLinkInfo);
</del><span class="cx">         
</span><del>-        void* jumpTarget = callLinkInfo-&gt;callReturnLocation.executableAddress();
</del><ins>+        switch (inlineCallFrame-&gt;kind) {
+        case InlineCallFrame::Call:
+        case InlineCallFrame::Construct: {
+            CallLinkInfo* callLinkInfo =
+                baselineCodeBlockForCaller-&gt;getCallLinkInfoForBytecodeIndex(callBytecodeIndex);
+            RELEASE_ASSERT(callLinkInfo);
+            
+            jumpTarget = callLinkInfo-&gt;callReturnLocation.executableAddress();
+            break;
+        }
+            
+        case InlineCallFrame::GetterCall:
+        case InlineCallFrame::SetterCall: {
+            StructureStubInfo* stubInfo =
+                baselineCodeBlockForCaller-&gt;findStubInfo(CodeOrigin(callBytecodeIndex));
+            RELEASE_ASSERT(stubInfo);
+            
+            switch (inlineCallFrame-&gt;kind) {
+            case InlineCallFrame::GetterCall:
+                jumpTarget = jit.vm()-&gt;getCTIStub(baselineGetterReturnThunkGenerator).code().executableAddress();
+                break;
+            case InlineCallFrame::SetterCall:
+                jumpTarget = jit.vm()-&gt;getCTIStub(baselineSetterReturnThunkGenerator).code().executableAddress();
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+                break;
+            }
+            
+            trueReturnPC = stubInfo-&gt;callReturnLocation.labelAtOffset(
+                stubInfo-&gt;patch.deltaCallToDone).executableAddress();
+            break;
+        } }
</ins><span class="cx"> 
</span><span class="cx">         GPRReg callerFrameGPR;
</span><span class="cx">         if (inlineCallFrame-&gt;caller.inlineCallFrame) {
</span><span class="lines">@@ -122,12 +154,15 @@
</span><span class="cx">         } else
</span><span class="cx">             callerFrameGPR = GPRInfo::callFrameRegister;
</span><span class="cx">         
</span><ins>+        jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame-&gt;returnPCOffset()));
+        if (trueReturnPC)
+            jit.storePtr(AssemblyHelpers::TrustedImmPtr(trueReturnPC), AssemblyHelpers::addressFor(inlineCallFrame-&gt;stackOffset + virtualRegisterForArgument(inlineCallFrame-&gt;arguments.size()).offset()));
+                         
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame-&gt;stackOffset + JSStack::CodeBlock)));
</span><span class="cx">         if (!inlineCallFrame-&gt;isClosureCall)
</span><span class="cx">             jit.store64(AssemblyHelpers::TrustedImm64(JSValue::encode(JSValue(inlineCallFrame-&gt;calleeConstant()-&gt;scope()))), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame-&gt;stackOffset + JSStack::ScopeChain)));
</span><span class="cx">         jit.store64(callerFrameGPR, AssemblyHelpers::addressForByteOffset(inlineCallFrame-&gt;callerFrameOffset()));
</span><del>-        jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame-&gt;returnPCOffset()));
</del><span class="cx">         uint32_t locationBits = CallFrame::Location::encodeAsBytecodeOffset(codeOrigin.bytecodeIndex);
</span><span class="cx">         jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame-&gt;stackOffset + JSStack::ArgumentCount)));
</span><span class="cx">         jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame-&gt;arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame-&gt;stackOffset + JSStack::ArgumentCount)));
</span><span class="lines">@@ -143,7 +178,6 @@
</span><span class="cx">         if (!inlineCallFrame-&gt;isClosureCall)
</span><span class="cx">             jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame-&gt;calleeConstant()-&gt;scope()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame-&gt;stackOffset + JSStack::ScopeChain)));
</span><span class="cx">         jit.storePtr(callerFrameGPR, AssemblyHelpers::addressForByteOffset(inlineCallFrame-&gt;callerFrameOffset()));
</span><del>-        jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame-&gt;returnPCOffset()));
</del><span class="cx">         Instruction* instruction = baselineCodeBlock-&gt;instructions().begin() + codeOrigin.bytecodeIndex;
</span><span class="cx">         uint32_t locationBits = CallFrame::Location::encodeAsBytecodeInstruction(instruction);
</span><span class="cx">         jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame-&gt;stackOffset + JSStack::ArgumentCount)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitPreparationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 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">@@ -45,7 +45,7 @@
</span><span class="cx">         FunctionExecutable* executable =
</span><span class="cx">             static_cast&lt;FunctionExecutable*&gt;(codeOrigin.inlineCallFrame-&gt;executable.get());
</span><span class="cx">         CodeBlock* codeBlock = executable-&gt;baselineCodeBlockFor(
</span><del>-            codeOrigin.inlineCallFrame-&gt;isCall ? CodeForCall : CodeForConstruct);
</del><ins>+            codeOrigin.inlineCallFrame-&gt;specializationKind());
</ins><span class="cx">         
</span><span class="cx">         if (codeBlock-&gt;jitType() == JSC::JITCode::BaselineJIT)
</span><span class="cx">             continue;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -193,7 +193,21 @@
</span><span class="cx">             changed |= setPrediction(node-&gt;getHeapPrediction());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+            
+        case GetGetterSetterByOffset: {
+            changed |= setPrediction(SpecCellOther);
+            break;
+        }
</ins><span class="cx"> 
</span><ins>+        case GetGetter:
+        case GetSetter:
+        case GetCallee:
+        case NewFunctionNoCheck:
+        case NewFunctionExpression: {
+            changed |= setPrediction(SpecFunction);
+            break;
+        }
+
</ins><span class="cx">         case StringCharCodeAt: {
</span><span class="cx">             changed |= setPrediction(SpecInt32);
</span><span class="cx">             break;
</span><span class="lines">@@ -396,13 +410,20 @@
</span><span class="cx">                 changed |= mergePrediction(SpecFullDouble);
</span><span class="cx">                 break;
</span><span class="cx">             case Array::Uint32Array:
</span><del>-                if (isInt32Speculation(node-&gt;getHeapPrediction()))
</del><ins>+                if (isInt32SpeculationForArithmetic(node-&gt;getHeapPrediction()))
</ins><span class="cx">                     changed |= mergePrediction(SpecInt32);
</span><span class="cx">                 else if (enableInt52())
</span><span class="cx">                     changed |= mergePrediction(SpecMachineInt);
</span><span class="cx">                 else
</span><span class="cx">                     changed |= mergePrediction(SpecInt32 | SpecInt52AsDouble);
</span><span class="cx">                 break;
</span><ins>+            case Array::Int8Array:
+            case Array::Uint8Array:
+            case Array::Int16Array:
+            case Array::Uint16Array:
+            case Array::Int32Array:
+                changed |= mergePrediction(SpecInt32);
+                break;
</ins><span class="cx">             default:
</span><span class="cx">                 changed |= mergePrediction(node-&gt;getHeapPrediction());
</span><span class="cx">                 break;
</span><span class="lines">@@ -443,11 +464,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><del>-        case GetCallee: {
-            changed |= setPrediction(SpecFunction);
-            break;
-        }
-            
</del><span class="cx">         case CreateThis:
</span><span class="cx">         case NewObject: {
</span><span class="cx">             changed |= setPrediction(SpecFinalObject);
</span><span class="lines">@@ -510,12 +526,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><del>-        case NewFunctionNoCheck:
-        case NewFunctionExpression: {
-            changed |= setPrediction(SpecFunction);
-            break;
-        }
-            
</del><span class="cx">         case FiatInt52: {
</span><span class="cx">             RELEASE_ASSERT(enableInt52());
</span><span class="cx">             changed |= setPrediction(SpecMachineInt);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -257,6 +257,8 @@
</span><span class="cx">     case Int52Rep:
</span><span class="cx">     case BooleanToNumber:
</span><span class="cx">     case FiatInt52:
</span><ins>+    case GetGetter:
+    case GetSetter:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case GetByVal:
</span><span class="lines">@@ -289,6 +291,7 @@
</span><span class="cx">             StructureSet(node-&gt;structureTransitionData().previousStructure));
</span><span class="cx">         
</span><span class="cx">     case GetByOffset:
</span><ins>+    case GetGetterSetterByOffset:
</ins><span class="cx">     case PutByOffset:
</span><span class="cx">         return state.forNode(node-&gt;child1()).m_currentKnownStructure.isValidOffset(
</span><span class="cx">             graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].offset);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> #include &quot;DFGOperations.h&quot;
</span><span class="cx"> #include &quot;DFGSlowPathGenerator.h&quot;
</span><span class="cx"> #include &quot;Debugger.h&quot;
</span><ins>+#include &quot;GetterSetter.h&quot;
</ins><span class="cx"> #include &quot;JSActivation.h&quot;
</span><span class="cx"> #include &quot;ObjectPrototype.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="lines">@@ -3834,6 +3835,47 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><ins>+    case GetGetterSetterByOffset: {
+        StorageOperand storage(this, node-&gt;child1());
+        GPRTemporary resultPayload(this);
+        
+        GPRReg storageGPR = storage.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        
+        StorageAccessData&amp; storageAccessData = m_jit.graph().m_storageAccessData[node-&gt;storageAccessDataIndex()];
+        
+        m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
+        
+        cellResult(resultPayloadGPR, node);
+        break;
+    }
+        
+    case GetGetter: {
+        SpeculateCellOperand op1(this, node-&gt;child1());
+        GPRTemporary result(this, Reuse, op1);
+        
+        GPRReg op1GPR = op1.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.loadPtr(JITCompiler::Address(op1GPR, GetterSetter::offsetOfGetter()), resultGPR);
+        
+        cellResult(resultGPR, node);
+        break;
+    }
+        
+    case GetSetter: {
+        SpeculateCellOperand op1(this, node-&gt;child1());
+        GPRTemporary result(this, Reuse, op1);
+        
+        GPRReg op1GPR = op1.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.loadPtr(JITCompiler::Address(op1GPR, GetterSetter::offsetOfSetter()), resultGPR);
+        
+        cellResult(resultGPR, node);
+        break;
+    }
+        
</ins><span class="cx">     case PutByOffset: {
</span><span class="cx">         StorageOperand storage(this, node-&gt;child1());
</span><span class="cx">         JSValueOperand value(this, node-&gt;child3());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> #include &quot;DFGOperations.h&quot;
</span><span class="cx"> #include &quot;DFGSlowPathGenerator.h&quot;
</span><span class="cx"> #include &quot;Debugger.h&quot;
</span><ins>+#include &quot;GetterSetter.h&quot;
</ins><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;ObjectPrototype.h&quot;
</span><span class="cx"> #include &quot;SpillRegistersMode.h&quot;
</span><span class="lines">@@ -3938,7 +3939,8 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case GetByOffset: {
</del><ins>+    case GetByOffset:
+    case GetGetterSetterByOffset: {
</ins><span class="cx">         StorageOperand storage(this, node-&gt;child1());
</span><span class="cx">         GPRTemporary result(this, Reuse, storage);
</span><span class="cx">         
</span><span class="lines">@@ -3953,6 +3955,32 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><ins>+    case GetGetter: {
+        SpeculateCellOperand op1(this, node-&gt;child1());
+        GPRTemporary result(this, Reuse, op1);
+        
+        GPRReg op1GPR = op1.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.loadPtr(JITCompiler::Address(op1GPR, GetterSetter::offsetOfGetter()), resultGPR);
+        
+        cellResult(resultGPR, node);
+        break;
+    }
+        
+    case GetSetter: {
+        SpeculateCellOperand op1(this, node-&gt;child1());
+        GPRTemporary result(this, Reuse, op1);
+        
+        GPRReg op1GPR = op1.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.loadPtr(JITCompiler::Address(op1GPR, GetterSetter::offsetOfSetter()), resultGPR);
+        
+        cellResult(resultGPR, node);
+        break;
+    }
+        
</ins><span class="cx">     case PutByOffset: {
</span><span class="cx">         StorageOperand storage(this, node-&gt;child1());
</span><span class="cx">         JSValueOperand value(this, node-&gt;child3());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 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(FTL_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;GetterSetter.h&quot;
</ins><span class="cx"> #include &quot;JSScope.h&quot;
</span><span class="cx"> #include &quot;JSVariableObject.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 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">@@ -46,6 +46,8 @@
</span><span class="cx">     macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
</span><span class="cx">     macro(Butterfly_vectorLength, Butterfly::offsetOfVectorLength()) \
</span><span class="cx">     macro(CallFrame_callerFrame, CallFrame::callerFrameOffset()) \
</span><ins>+    macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \
+    macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
</ins><span class="cx">     macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
</span><span class="cx">     macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
</span><span class="cx">     macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -72,6 +72,9 @@
</span><span class="cx">     case NewArray:
</span><span class="cx">     case NewArrayBuffer:
</span><span class="cx">     case GetByOffset:
</span><ins>+    case GetGetterSetterByOffset:
+    case GetGetter:
+    case GetSetter:
</ins><span class="cx">     case PutByOffset:
</span><span class="cx">     case GetGlobalVar:
</span><span class="cx">     case PutGlobalVar:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLinkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLink.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -177,7 +177,7 @@
</span><span class="cx"> 
</span><span class="cx">         linkBuffer = adoptPtr(new LinkBuffer(vm, jit, codeBlock, JITCompilationMustSucceed));
</span><span class="cx">         linkBuffer-&gt;link(callArityCheck, codeBlock-&gt;m_isConstructor ? operationConstructArityCheck : operationCallArityCheck);
</span><del>-        linkBuffer-&gt;link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixup)).code().executableAddress()));
</del><ins>+        linkBuffer-&gt;link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixupGenerator)).code().executableAddress()));
</ins><span class="cx">         linkBuffer-&gt;link(mainPathJumps, CodeLocationLabel(bitwise_cast&lt;void*&gt;(state.generatedFunction)));
</span><span class="cx"> 
</span><span class="cx">         state.jitCode-&gt;initializeAddressForCall(MacroAssemblerCodePtr(bitwise_cast&lt;void*&gt;(state.generatedFunction)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -495,8 +495,15 @@
</span><span class="cx">             compileStringCharCodeAt();
</span><span class="cx">             break;
</span><span class="cx">         case GetByOffset:
</span><ins>+        case GetGetterSetterByOffset:
</ins><span class="cx">             compileGetByOffset();
</span><span class="cx">             break;
</span><ins>+        case GetGetter:
+            compileGetGetter();
+            break;
+        case GetSetter:
+            compileGetSetter();
+            break;
</ins><span class="cx">         case MultiGetByOffset:
</span><span class="cx">             compileMultiGetByOffset();
</span><span class="cx">             break;
</span><span class="lines">@@ -3187,6 +3194,16 @@
</span><span class="cx">             lowStorage(m_node-&gt;child1()), data.identifierNumber, data.offset));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileGetGetter()
+    {
+        setJSValue(m_out.loadPtr(lowCell(m_node-&gt;child1()), m_heaps.GetterSetter_getter));
+    }
+    
+    void compileGetSetter()
+    {
+        setJSValue(m_out.loadPtr(lowCell(m_node-&gt;child1()), m_heaps.GetterSetter_setter));
+    }
+    
</ins><span class="cx">     void compileMultiGetByOffset()
</span><span class="cx">     {
</span><span class="cx">         LValue base = lowCell(m_node-&gt;child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -74,6 +74,8 @@
</span><span class="cx">     ASSERT(blockState != Allocated &amp;&amp; blockState != FreeListed);
</span><span class="cx">     ASSERT(!(dtorType == MarkedBlock::None &amp;&amp; sweepMode == SweepOnly));
</span><span class="cx"> 
</span><ins>+    SamplingRegion samplingRegion((dtorType != MarkedBlock::None &amp;&amp; blockState != New) ? &quot;Calling destructors&quot; : &quot;sweeping&quot;);
+    
</ins><span class="cx">     // This produces a free list that is ordered in reverse through the block.
</span><span class="cx">     // This is fine, since the allocation code makes no assumptions about the
</span><span class="cx">     // order of the free list.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAccessorCallJITStubRoutineh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AccessorCallJITStubRoutine.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AccessorCallJITStubRoutine.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/jit/AccessorCallJITStubRoutine.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -46,7 +46,6 @@
</span><span class="cx">     
</span><span class="cx">     virtual bool visitWeak(RepatchBuffer&amp;) override;
</span><span class="cx">     
</span><del>-private:
</del><span class="cx">     std::unique_ptr&lt;CallLinkInfo&gt; m_callLinkInfo;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -109,6 +109,17 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+void JIT::assertStackPointerOffset()
+{
+    if (ASSERT_DISABLED)
+        return;
+    
+    addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, regT0);
+    Jump ok = branchPtr(Equal, regT0, stackPointerRegister);
+    breakpoint();
+    ok.link(this);
+}
+
</ins><span class="cx"> #define NEXT_OPCODE(name) \
</span><span class="cx">     m_bytecodeOffset += OPCODE_LENGTH(name); \
</span><span class="cx">     break;
</span><span class="lines">@@ -574,7 +585,7 @@
</span><span class="cx"> #endif
</span><span class="cx">         move(TrustedImmPtr(m_vm-&gt;arityCheckFailReturnThunks-&gt;returnPCsFor(*m_vm, m_codeBlock-&gt;numParameters())), thunkReg);
</span><span class="cx">         loadPtr(BaseIndex(thunkReg, regT0, timesPtr()), thunkReg);
</span><del>-        emitNakedCall(m_vm-&gt;getCTIStub(arityFixup).code());
</del><ins>+        emitNakedCall(m_vm-&gt;getCTIStub(arityFixupGenerator).code());
</ins><span class="cx"> 
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">         m_bytecodeOffset = (unsigned)-1; // Reset this, in order to guard its use with ASSERTs.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -447,6 +447,8 @@
</span><span class="cx"> 
</span><span class="cx">         void emit_compareAndJump(OpcodeID, int op1, int op2, unsigned target, RelationalCondition);
</span><span class="cx">         void emit_compareAndJumpSlow(int op1, int op2, unsigned target, DoubleCondition, size_t (JIT_OPERATION *operation)(ExecState*, EncodedJSValue, EncodedJSValue), bool invert, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><ins>+        
+        void assertStackPointerOffset();
</ins><span class="cx"> 
</span><span class="cx">         void emit_op_touch_entry(Instruction*);
</span><span class="cx">         void emit_op_add(Instruction*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -528,6 +528,7 @@
</span><span class="cx"> 
</span><span class="cx">     emitValueProfilingSite();
</span><span class="cx">     emitPutVirtualRegister(resultVReg);
</span><ins>+    assertStackPointerOffset();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -434,7 +434,7 @@
</span><span class="cx">     return nativeForGenerator(vm, CodeForConstruct);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef arityFixup(VM* vm)
</del><ins>+MacroAssemblerCodeRef arityFixupGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     JSInterfaceJIT jit(vm);
</span><span class="cx"> 
</span><span class="lines">@@ -537,6 +537,83 @@
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;fixup arity&quot;));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MacroAssemblerCodeRef baselineGetterReturnThunkGenerator(VM* vm)
+{
+    JSInterfaceJIT jit(vm);
+    
+#if USE(JSVALUE64)
+    jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0);
+#else
+    jit.setupResults(GPRInfo::regT0, GPRInfo::regT1);
+#endif
+    
+    unsigned numberOfParameters = 0;
+    numberOfParameters++; // The 'this' argument.
+    numberOfParameters++; // The true return PC.
+    
+    unsigned numberOfRegsForCall =
+        JSStack::CallFrameHeaderSize + numberOfParameters;
+    
+    unsigned numberOfBytesForCall =
+        numberOfRegsForCall * sizeof(Register) - sizeof(CallerFrameAndPC);
+    
+    unsigned alignedNumberOfBytesForCall =
+        WTF::roundUpToMultipleOf(stackAlignmentBytes(), numberOfBytesForCall);
+            
+    // The real return address is stored above the arguments. We passed one argument, which is
+    // 'this'. So argument at index 1 is the return address.
+    jit.loadPtr(
+        AssemblyHelpers::Address(
+            AssemblyHelpers::stackPointerRegister,
+            (virtualRegisterForArgument(1).offset() - JSStack::CallerFrameAndPCSize) * sizeof(Register)),
+        GPRInfo::regT2);
+    
+    jit.addPtr(
+        AssemblyHelpers::TrustedImm32(alignedNumberOfBytesForCall),
+        AssemblyHelpers::stackPointerRegister);
+    
+    jit.jump(GPRInfo::regT2);
+
+    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
+    return FINALIZE_CODE(patchBuffer, (&quot;baseline getter return thunk&quot;));
+}
+
+MacroAssemblerCodeRef baselineSetterReturnThunkGenerator(VM* vm)
+{
+    JSInterfaceJIT jit(vm);
+    
+    unsigned numberOfParameters = 0;
+    numberOfParameters++; // The 'this' argument.
+    numberOfParameters++; // The value to set.
+    numberOfParameters++; // The true return PC.
+    
+    unsigned numberOfRegsForCall =
+        JSStack::CallFrameHeaderSize + numberOfParameters;
+    
+    unsigned numberOfBytesForCall =
+        numberOfRegsForCall * sizeof(Register) - sizeof(CallerFrameAndPC);
+    
+    unsigned alignedNumberOfBytesForCall =
+        WTF::roundUpToMultipleOf(stackAlignmentBytes(), numberOfBytesForCall);
+            
+    // The real return address is stored above the arguments. We passed two arguments, so
+    // the argument at index 2 is the return address.
+    jit.loadPtr(
+        AssemblyHelpers::Address(
+            AssemblyHelpers::stackPointerRegister,
+            (virtualRegisterForArgument(2).offset() - JSStack::CallerFrameAndPCSize) * sizeof(Register)),
+        GPRInfo::regT2);
+    
+    jit.addPtr(
+        AssemblyHelpers::TrustedImm32(alignedNumberOfBytesForCall),
+        AssemblyHelpers::stackPointerRegister);
+    
+    jit.jump(GPRInfo::regT2);
+
+    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
+    return FINALIZE_CODE(patchBuffer, (&quot;baseline setter return thunk&quot;));
+}
+
</ins><span class="cx"> static void stringCharLoad(SpecializedThunkJIT&amp; jit, VM* vm)
</span><span class="cx"> {
</span><span class="cx">     // load string
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -113,8 +113,11 @@
</span><span class="cx"> MacroAssemblerCodeRef nativeCallGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeConstructGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
</span><del>-MacroAssemblerCodeRef arityFixup(VM*);
</del><ins>+MacroAssemblerCodeRef arityFixupGenerator(VM*);
</ins><span class="cx"> 
</span><ins>+MacroAssemblerCodeRef baselineGetterReturnThunkGenerator(VM* vm);
+MacroAssemblerCodeRef baselineSetterReturnThunkGenerator(VM* vm);
+
</ins><span class="cx"> MacroAssemblerCodeRef charCodeAtThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef charAtThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef fromCharCodeThunkGenerator(VM*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><del>- *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
</span><span class="cx">  *  Copyright (C) 2007 Maks Orlovich
</span><span class="cx">  *
</span><span class="lines">@@ -321,7 +321,7 @@
</span><span class="cx">     m_overrodeCallee = false;
</span><span class="cx">     m_overrodeCaller = false;
</span><span class="cx">     m_isStrictMode = jsCast&lt;FunctionExecutable*&gt;(inlineCallFrame-&gt;executable.get())-&gt;isStrictMode();
</span><del>-    ASSERT(!jsCast&lt;FunctionExecutable*&gt;(inlineCallFrame-&gt;executable.get())-&gt;symbolTable(inlineCallFrame-&gt;isCall ? CodeForCall : CodeForConstruct)-&gt;slowArguments());
</del><ins>+    ASSERT(!jsCast&lt;FunctionExecutable*&gt;(inlineCallFrame-&gt;executable.get())-&gt;symbolTable(inlineCallFrame-&gt;specializationKind())-&gt;slowArguments());
</ins><span class="cx"> 
</span><span class="cx">     // The bytecode generator omits op_tear_off_activation in cases of no
</span><span class="cx">     // declared parameters, so we need to tear off immediately.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -165,7 +165,7 @@
</span><span class="cx">     result-&gt;paddedStackSpace = slotsToAdd;
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     if (vm.canUseJIT()) {
</span><del>-        result-&gt;thunkToCall = vm.getCTIStub(arityFixup).code().executableAddress();
</del><ins>+        result-&gt;thunkToCall = vm.getCTIStub(arityFixupGenerator).code().executableAddress();
</ins><span class="cx">         result-&gt;returnPC = vm.arityCheckFailReturnThunks-&gt;returnPCFor(vm, slotsToAdd * stackAlignmentRegisters()).executableAddress();
</span><span class="cx">     } else
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSString.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSString.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/runtime/JSString.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -83,24 +83,39 @@
</span><span class="cx"> 
</span><span class="cx"> void JSRopeString::visitFibers(SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i)
-        visitor.append(&amp;m_fibers[i]);
</del><ins>+    if (isSubstring()) {
+        visitor.append(&amp;substringBase());
+        return;
+    }
+    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; fiber(i); ++i)
+        visitor.append(&amp;fiber(i));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static const unsigned maxLengthForOnStackResolve = 2048;
</span><span class="cx"> 
</span><span class="cx"> void JSRopeString::resolveRopeInternal8(LChar* buffer) const
</span><span class="cx"> {
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i) {
-        if (m_fibers[i]-&gt;isRope()) {
</del><ins>+    if (isSubstring()) {
+        StringImpl::copyChars(
+            buffer, substringBase()-&gt;m_value.characters8() + substringOffset(), m_length);
+        return;
+    }
+    
+    resolveRopeInternal8NoSubstring(buffer);
+}
+
+void JSRopeString::resolveRopeInternal8NoSubstring(LChar* buffer) const
+{
+    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; fiber(i); ++i) {
+        if (fiber(i)-&gt;isRope()) {
</ins><span class="cx">             resolveRopeSlowCase8(buffer);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     LChar* position = buffer;
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i) {
-        const StringImpl&amp; fiberString = *m_fibers[i]-&gt;m_value.impl();
</del><ins>+    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; fiber(i); ++i) {
+        const StringImpl&amp; fiberString = *fiber(i)-&gt;m_value.impl();
</ins><span class="cx">         unsigned length = fiberString.length();
</span><span class="cx">         StringImpl::copyChars(position, fiberString.characters8(), length);
</span><span class="cx">         position += length;
</span><span class="lines">@@ -110,16 +125,27 @@
</span><span class="cx"> 
</span><span class="cx"> void JSRopeString::resolveRopeInternal16(UChar* buffer) const
</span><span class="cx"> {
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i) {
-        if (m_fibers[i]-&gt;isRope()) {
</del><ins>+    if (isSubstring()) {
+        StringImpl::copyChars(
+            buffer, substringBase()-&gt;m_value.characters16() + substringOffset(), m_length);
+        return;
+    }
+    
+    resolveRopeInternal16NoSubstring(buffer);
+}
+
+void JSRopeString::resolveRopeInternal16NoSubstring(UChar* buffer) const
+{
+    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; fiber(i); ++i) {
+        if (fiber(i)-&gt;isRope()) {
</ins><span class="cx">             resolveRopeSlowCase(buffer);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     UChar* position = buffer;
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i) {
-        const StringImpl&amp; fiberString = *m_fibers[i]-&gt;m_value.impl();
</del><ins>+    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; fiber(i); ++i) {
+        const StringImpl&amp; fiberString = *fiber(i)-&gt;m_value.impl();
</ins><span class="cx">         unsigned length = fiberString.length();
</span><span class="cx">         if (fiberString.is8Bit())
</span><span class="cx">             StringImpl::copyChars(position, fiberString.characters8(), length);
</span><span class="lines">@@ -157,8 +183,8 @@
</span><span class="cx"> 
</span><span class="cx"> void JSRopeString::clearFibers() const
</span><span class="cx"> {
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i)
-        m_fibers[i].clear();
</del><ins>+    for (size_t i = 0; i &lt; s_maxInternalRopeLength; ++i)
+        u[i].number = 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> AtomicStringImpl* JSRopeString::resolveRopeToExistingAtomicString(ExecState* exec) const
</span><span class="lines">@@ -172,7 +198,7 @@
</span><span class="cx">         }
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><del>-
</del><ins>+    
</ins><span class="cx">     if (is8Bit()) {
</span><span class="cx">         LChar buffer[maxLengthForOnStackResolve];
</span><span class="cx">         resolveRopeInternal8(buffer);
</span><span class="lines">@@ -197,7 +223,14 @@
</span><span class="cx"> void JSRopeString::resolveRope(ExecState* exec) const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isRope());
</span><del>-
</del><ins>+    
+    if (isSubstring()) {
+        ASSERT(!substringBase()-&gt;isRope());
+        m_value = substringBase()-&gt;m_value.substring(substringOffset(), m_length);
+        substringBase().clear();
+        return;
+    }
+    
</ins><span class="cx">     if (is8Bit()) {
</span><span class="cx">         LChar* buffer;
</span><span class="cx">         if (RefPtr&lt;StringImpl&gt; newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) {
</span><span class="lines">@@ -207,7 +240,7 @@
</span><span class="cx">             outOfMemory(exec);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-        resolveRopeInternal8(buffer);
</del><ins>+        resolveRopeInternal8NoSubstring(buffer);
</ins><span class="cx">         clearFibers();
</span><span class="cx">         ASSERT(!isRope());
</span><span class="cx">         return;
</span><span class="lines">@@ -222,7 +255,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    resolveRopeInternal16(buffer);
</del><ins>+    resolveRopeInternal16NoSubstring(buffer);
</ins><span class="cx">     clearFibers();
</span><span class="cx">     ASSERT(!isRope());
</span><span class="cx"> }
</span><span class="lines">@@ -242,24 +275,32 @@
</span><span class="cx">     LChar* position = buffer + m_length; // We will be working backwards over the rope.
</span><span class="cx">     Vector&lt;JSString*, 32, UnsafeVectorOverflow&gt; workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
</span><span class="cx">     
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i)
-        workQueue.append(m_fibers[i].get());
</del><ins>+    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; fiber(i); ++i)
+        workQueue.append(fiber(i).get());
</ins><span class="cx"> 
</span><span class="cx">     while (!workQueue.isEmpty()) {
</span><span class="cx">         JSString* currentFiber = workQueue.last();
</span><span class="cx">         workQueue.removeLast();
</span><span class="cx"> 
</span><ins>+        const LChar* characters;
+        
</ins><span class="cx">         if (currentFiber-&gt;isRope()) {
</span><span class="cx">             JSRopeString* currentFiberAsRope = static_cast&lt;JSRopeString*&gt;(currentFiber);
</span><del>-            for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; currentFiberAsRope-&gt;m_fibers[i]; ++i)
-                workQueue.append(currentFiberAsRope-&gt;m_fibers[i].get());
-            continue;
-        }
-
-        StringImpl* string = static_cast&lt;StringImpl*&gt;(currentFiber-&gt;m_value.impl());
-        unsigned length = string-&gt;length();
</del><ins>+            if (!currentFiberAsRope-&gt;isSubstring()) {
+                for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; currentFiberAsRope-&gt;fiber(i); ++i)
+                    workQueue.append(currentFiberAsRope-&gt;fiber(i).get());
+                continue;
+            }
+            ASSERT(!currentFiberAsRope-&gt;substringBase()-&gt;isRope());
+            characters =
+                currentFiberAsRope-&gt;substringBase()-&gt;m_value.characters8() +
+                currentFiberAsRope-&gt;substringOffset();
+        } else
+            characters = currentFiber-&gt;m_value.characters8();
+        
+        unsigned length = currentFiber-&gt;length();
</ins><span class="cx">         position -= length;
</span><del>-        StringImpl::copyChars(position, string-&gt;characters8(), length);
</del><ins>+        StringImpl::copyChars(position, characters, length);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT(buffer == position);
</span><span class="lines">@@ -270,8 +311,8 @@
</span><span class="cx">     UChar* position = buffer + m_length; // We will be working backwards over the rope.
</span><span class="cx">     Vector&lt;JSString*, 32, UnsafeVectorOverflow&gt; workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
</span><span class="cx"> 
</span><del>-    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; m_fibers[i]; ++i)
-        workQueue.append(m_fibers[i].get());
</del><ins>+    for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; fiber(i); ++i)
+        workQueue.append(fiber(i).get());
</ins><span class="cx"> 
</span><span class="cx">     while (!workQueue.isEmpty()) {
</span><span class="cx">         JSString* currentFiber = workQueue.last();
</span><span class="lines">@@ -279,8 +320,21 @@
</span><span class="cx"> 
</span><span class="cx">         if (currentFiber-&gt;isRope()) {
</span><span class="cx">             JSRopeString* currentFiberAsRope = static_cast&lt;JSRopeString*&gt;(currentFiber);
</span><del>-            for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; currentFiberAsRope-&gt;m_fibers[i]; ++i)
-                workQueue.append(currentFiberAsRope-&gt;m_fibers[i].get());
</del><ins>+            if (currentFiberAsRope-&gt;isSubstring()) {
+                ASSERT(!currentFiberAsRope-&gt;substringBase()-&gt;isRope());
+                StringImpl* string = static_cast&lt;StringImpl*&gt;(
+                    currentFiberAsRope-&gt;substringBase()-&gt;m_value.impl());
+                unsigned offset = currentFiberAsRope-&gt;substringOffset();
+                unsigned length = currentFiberAsRope-&gt;length();
+                position -= length;
+                if (string-&gt;is8Bit())
+                    StringImpl::copyChars(position, string-&gt;characters8() + offset, length);
+                else
+                    StringImpl::copyChars(position, string-&gt;characters16() + offset, length);
+                continue;
+            }
+            for (size_t i = 0; i &lt; s_maxInternalRopeLength &amp;&amp; currentFiberAsRope-&gt;fiber(i); ++i)
+                workQueue.append(currentFiberAsRope-&gt;fiber(i).get());
</ins><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSString.h (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSString.h        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/runtime/JSString.h        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -273,8 +273,10 @@
</span><span class="cx">             Base::finishCreation(vm);
</span><span class="cx">             m_length = s1-&gt;length() + s2-&gt;length();
</span><span class="cx">             setIs8Bit(s1-&gt;is8Bit() &amp;&amp; s2-&gt;is8Bit());
</span><del>-            m_fibers[0].set(vm, this, s1);
-            m_fibers[1].set(vm, this, s2);
</del><ins>+            setIsSubstring(false);
+            fiber(0).set(vm, this, s1);
+            fiber(1).set(vm, this, s2);
+            fiber(2).clear();
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         void finishCreation(VM&amp; vm, JSString* s1, JSString* s2, JSString* s3)
</span><span class="lines">@@ -282,19 +284,37 @@
</span><span class="cx">             Base::finishCreation(vm);
</span><span class="cx">             m_length = s1-&gt;length() + s2-&gt;length() + s3-&gt;length();
</span><span class="cx">             setIs8Bit(s1-&gt;is8Bit() &amp;&amp; s2-&gt;is8Bit() &amp;&amp;  s3-&gt;is8Bit());
</span><del>-            m_fibers[0].set(vm, this, s1);
-            m_fibers[1].set(vm, this, s2);
-            m_fibers[2].set(vm, this, s3);
</del><ins>+            setIsSubstring(false);
+            fiber(0).set(vm, this, s1);
+            fiber(1).set(vm, this, s2);
+            fiber(2).set(vm, this, s3);
</ins><span class="cx">         }
</span><ins>+        
+        void finishCreation(VM&amp; vm, JSString* base, unsigned offset, unsigned length)
+        {
+            Base::finishCreation(vm);
+            ASSERT(!base-&gt;isRope());
+            ASSERT(!sumOverflows&lt;int32_t&gt;(offset, length));
+            ASSERT(offset + length &lt;= base-&gt;length());
+            m_length = length;
+            setIs8Bit(base-&gt;is8Bit());
+            setIsSubstring(true);
+            substringBase().set(vm, this, base);
+            substringOffset() = offset;
+        }
</ins><span class="cx"> 
</span><span class="cx">         void finishCreation(VM&amp; vm)
</span><span class="cx">         {
</span><span class="cx">             JSString::finishCreation(vm);
</span><ins>+            setIsSubstring(false);
+            fiber(0).clear();
+            fiber(1).clear();
+            fiber(2).clear();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         void append(VM&amp; vm, size_t index, JSString* jsString)
</span><span class="cx">         {
</span><del>-            m_fibers[index].set(vm, this, jsString);
</del><ins>+            fiber(index).set(vm, this, jsString);
</ins><span class="cx">             m_length += jsString-&gt;m_length;
</span><span class="cx">             RELEASE_ASSERT(static_cast&lt;int32_t&gt;(m_length) &gt;= 0);
</span><span class="cx">             setIs8Bit(is8Bit() &amp;&amp; jsString-&gt;is8Bit());
</span><span class="lines">@@ -320,10 +340,17 @@
</span><span class="cx">             newString-&gt;finishCreation(vm, s1, s2, s3);
</span><span class="cx">             return newString;
</span><span class="cx">         }
</span><ins>+        
+        static JSString* create(VM&amp; vm, JSString* base, unsigned offset, unsigned length)
+        {
+            JSRopeString* newString = new (NotNull, allocateCell&lt;JSRopeString&gt;(vm.heap)) JSRopeString(vm);
+            newString-&gt;finishCreation(vm, base, offset, length);
+            return newString;
+        }
</ins><span class="cx"> 
</span><span class="cx">         void visitFibers(SlotVisitor&amp;);
</span><span class="cx">             
</span><del>-        static ptrdiff_t offsetOfFibers() { return OBJECT_OFFSETOF(JSRopeString, m_fibers); }
</del><ins>+        static ptrdiff_t offsetOfFibers() { return OBJECT_OFFSETOF(JSRopeString, u); }
</ins><span class="cx"> 
</span><span class="cx">         static const unsigned s_maxInternalRopeLength = 3;
</span><span class="cx">             
</span><span class="lines">@@ -338,12 +365,54 @@
</span><span class="cx">         void resolveRopeSlowCase(UChar*) const;
</span><span class="cx">         void outOfMemory(ExecState*) const;
</span><span class="cx">         void resolveRopeInternal8(LChar*) const;
</span><ins>+        void resolveRopeInternal8NoSubstring(LChar*) const;
</ins><span class="cx">         void resolveRopeInternal16(UChar*) const;
</span><ins>+        void resolveRopeInternal16NoSubstring(UChar*) const;
</ins><span class="cx">         void clearFibers() const;
</span><span class="cx">             
</span><span class="cx">         JS_EXPORT_PRIVATE JSString* getIndexSlowCase(ExecState*, unsigned);
</span><ins>+        
+        WriteBarrierBase&lt;JSString&gt;&amp; fiber(unsigned i) const
+        {
+            ASSERT(!isSubstring());
+            ASSERT(i &lt; s_maxInternalRopeLength);
+            return u[i].string;
+        }
+        
+        WriteBarrierBase&lt;JSString&gt;&amp; substringBase() const
+        {
+            return u[1].string;
+        }
+        
+        uintptr_t&amp; substringOffset() const
+        {
+            return u[2].number;
+        }
+        
+        static uintptr_t notSubstringSentinel()
+        {
+            return 0;
+        }
+        
+        static uintptr_t substringSentinel()
+        {
+            return 1;
+        }
+        
+        bool isSubstring() const
+        {
+            return u[0].number == substringSentinel();
+        }
+        
+        void setIsSubstring(bool isSubstring)
+        {
+            u[0].number = isSubstring ? substringSentinel() : notSubstringSentinel();
+        }
</ins><span class="cx"> 
</span><del>-        mutable std::array&lt;WriteBarrier&lt;JSString&gt;, s_maxInternalRopeLength&gt; m_fibers;
</del><ins>+        mutable union {
+            uintptr_t number;
+            WriteBarrierBase&lt;JSString&gt; string;
+        } u[s_maxInternalRopeLength];
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -454,10 +523,11 @@
</span><span class="cx">         ASSERT(offset &lt;= static_cast&lt;unsigned&gt;(s-&gt;length()));
</span><span class="cx">         ASSERT(length &lt;= static_cast&lt;unsigned&gt;(s-&gt;length()));
</span><span class="cx">         ASSERT(offset + length &lt;= static_cast&lt;unsigned&gt;(s-&gt;length()));
</span><del>-        VM* vm = &amp;exec-&gt;vm();
</del><ins>+        VM&amp; vm = exec-&gt;vm();
</ins><span class="cx">         if (!length)
</span><del>-            return vm-&gt;smallStrings.emptyString();
-        return jsSubstring(vm, s-&gt;value(exec), offset, length);
</del><ins>+            return vm.smallStrings.emptyString();
+        s-&gt;value(exec); // For effect. We need to ensure that any string that is used as a substring base is not a rope.
+        return JSRopeString::create(vm, s, offset, length);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline JSString* jsSubstring8(VM* vm, const String&amp; s, unsigned offset, unsigned length)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpMatchesArraycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -74,6 +74,8 @@
</span><span class="cx">     ASSERT(m_state != ReifiedAll);
</span><span class="cx">     ASSERT(m_result);
</span><span class="cx">  
</span><ins>+    SamplingRegion samplingRegion(&quot;Reifying substring properties&quot;);
+    
</ins><span class="cx">     reifyMatchPropertyIfNecessary(exec);
</span><span class="cx"> 
</span><span class="cx">     if (unsigned numSubpatterns = m_regExp-&gt;numSubpatterns()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1218,6 +1218,7 @@
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
</span><span class="cx"> {
</span><ins>+    SamplingRegion samplingRegion(&quot;Doing substringing&quot;);
</ins><span class="cx">     JSValue thisValue = exec-&gt;thisValue();
</span><span class="cx">     if (!checkObjectCoercible(thisValue))
</span><span class="cx">         return throwVMTypeError(exec);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressexitfromgetterjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/exit-from-getter.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/exit-from-getter.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/exit-from-getter.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+(function() {
+    var o = {_f:42};
+    o.__defineGetter__(&quot;f&quot;, function() { return this._f * 100; });
+    var result = 0;
+    var n = 50000;
+    function foo(o) {
+        return o.f + 11;
+    }
+    noInline(foo);
+    for (var i = 0; i &lt; n; ++i) {
+        result += foo(o);
+    }
+    if (result != n * (42 * 100 + 11))
+        throw &quot;Error: bad result: &quot; + result;
+    o._f = 1000000000;
+    result = 0;
+    for (var i = 0; i &lt; n; ++i) {
+        result += foo(o);
+    }
+    if (result != n * (1000000000 * 100 + 11))
+        throw &quot;Error: bad result (2): &quot; + result;
+})();
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolychaingetterjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-chain-getter.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-chain-getter.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-chain-getter.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+function Cons() {
+}
+Cons.prototype.__defineGetter__(&quot;f&quot;, function() {
+    counter++;
+    return 84;
+});
+
+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    test(new Cons(), 84, counter + 1);
+    
+    var o = new Cons();
+    o.g = 54;
+    test(o, 84, counter + 1);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolychainthengetterjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-chain-then-getter.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-chain-then-getter.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-chain-then-getter.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+function Cons1() {
+}
+Cons1.prototype.f = 42;
+
+function Cons2() {
+}
+Cons2.prototype.__defineGetter__(&quot;f&quot;, function() {
+    counter++;
+    return 84;
+});
+
+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    test(new Cons1(), 42, counter);
+    test(new Cons2(), 84, counter + 1);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolygettercombojs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-getter-combo.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-getter-combo.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-getter-combo.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+function Cons1() {
+}
+Cons1.prototype.f = 42;
+
+function Cons2() {
+}
+Cons2.prototype.__defineGetter__(&quot;f&quot;, function() {
+    counter++;
+    return 84;
+});
+
+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    test(new Cons1(), 42, counter);
+    test(new Cons2(), 84, counter + 1);
+    
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        counter++;
+        return 84;
+    });
+    test(o, 84, counter + 1);
+
+    test({f: 42}, 42, counter);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolygetterthenchainjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-chain.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-chain.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-chain.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+function Cons1() {
+}
+Cons1.prototype.f = 42;
+
+function Cons2() {
+}
+Cons2.prototype.__defineGetter__(&quot;f&quot;, function() {
+    counter++;
+    return 84;
+});
+
+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    test(new Cons2(), 84, counter + 1);
+    test(new Cons1(), 42, counter);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolygetterthenselfjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-self.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-self.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-getter-then-self.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        counter++;
+        return 84;
+    });
+    test(o, 84, counter + 1);
+
+    test({f: 42}, 42, counter);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolyselfgetterjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-self-getter.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-self-getter.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-self-getter.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+function getter() {
+    counter++;
+    return 84;
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, getter);
+    test(o, 84, counter + 1);
+
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, getter);
+    o.g = 54;
+    test(o, 84, counter + 1);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolyselfthengetterjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-self-then-getter.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-self-then-getter.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-self-then-getter.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    test({f: 42}, 42, counter);
+
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        counter++;
+        return 84;
+    });
+    test(o, 84, counter + 1);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressweirdgettercounterjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/weird-getter-counter.js (0 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/weird-getter-counter.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/weird-getter-counter.js        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+var counter = 0;
+
+function test(o, expected, expectedCount) {
+    var result = foo(o);
+    if (result != expected)
+        throw new Error(&quot;Bad result: &quot; + result);
+    if (counter != expectedCount)
+        throw new Error(&quot;Bad counter value: &quot; + counter);
+}
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        counter++;
+        return 84;
+    });
+    test(o, 84, counter + 1);
+}
</ins></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (171361 => 171362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2014-07-22 20:57:54 UTC (rev 171361)
+++ trunk/Source/WTF/ChangeLog        2014-07-22 21:08:50 UTC (rev 171362)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2014-07-22  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Merge r168635, r168780, r169005, r169014, and r169143 from ftlopt.
+
+    2014-05-20  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            [ftlopt] DFG bytecode parser should turn GetById with nothing but a Getter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
+            https://bugs.webkit.org/show_bug.cgi?id=133105
+    
+            Reviewed by Michael Saboff.
+    
+            * wtf/Bag.h:
+            (WTF::Bag::iterator::operator!=):
+    
</ins><span class="cx"> 2014-07-19  Zan Dobersek  &lt;zdobersek@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WTF] Add the move constructor, move assignment operator for HashTable
</span></span></pre>
</div>
</div>

</body>
</html>