<!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>[203537] trunk/Source</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/203537">203537</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-07-21 16:41:44 -0700 (Thu, 21 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>op_add/ValueAdd should be an IC in all JIT tiers
https://bugs.webkit.org/show_bug.cgi?id=159649

Reviewed by Benjamin Poulain.

Source/JavaScriptCore:

This patch makes Add an IC inside all JIT tiers. It does so in a
simple, but effective, way. We will try to generate an int+int add
that will repatch itself if its type checks fail. Sometimes though,
we have runtime type data saying that the add won't be int+int.
In those cases, we will just generate a full snippet that doesn't patch itself.
Other times, we may generate no inline code and defer to making a C call. A lot
of this patch is just refactoring ResultProfile into what we're now calling ArithProfile.
ArithProfile does everything ResultProfile used to do, and more. It records simple type
data about the LHS/RHS operands it sees. This allows us to determine if an op_add
has only seen int+int operands, etc. ArithProfile will also contain the ResultType
for the LHS/RHS that the parser feeds into op_add. ArithProfile now fits into 32-bits.
This means instead of having a side table like we did for ResultProfile, we just
inject the ArithProfile into the bytecode instruction stream. This makes asking
for ArithProfile faster; we no longer need to lock around this operation.

The size of an Add has gone down on average, but we can still do better.
We still generate a lot of code because we generate calls to the slow path.
I think we can make this better by moving the slow path to a shared thunk
system. This patch mostly lays the foundation for future improvements to Add,
and a framework to move all other arithmetic operations to be typed-based ICs.

Here is some data I took on the average op_add/ValueAdd size on various benchmarks:
           |   JetStream  |  Speedometer |  Unity 3D  |
     ------| -------------|-----------------------------
      Old  |  189 bytes   |  169 bytes   |  192 bytes |
     ------| -------------|-----------------------------
      New  |  148 bytes   |  124 bytes   |  143 bytes |
     ---------------------------------------------------

Making an arithmetic IC is now easy. The JITMathIC class will hold a snippet
generator as a member variable. To make a snippet an IC, you need to implement
a generateInline(.) method, which generates the inline IC. Then, you need to
generate the IC where you used to generate the snippet. When generating the
IC, we need to inform JITMathIC of various data like we do with StructureStubInfo.
We need to tell it about where the slow path starts, where the slow path call is, etc.
When generating a JITMathIC, it may tell you that it didn't generate any code inline.
This is a request to the user of JITMathIC to just generate a C call along the
fast path. JITMathIC may also have the snippet tell it to just generate the full
snippet instead of the int+int path along the fast path.

In subsequent patches, we can improve upon how we decide to generate int+int or
the full snippet. I tried to get clever by having double+double, double+int, int+double,
fast paths, but they didn't work out nearly as well as the int+int fast path. I ended up
generating a lot of code when I did this and ended up using more memory than just generating
the full snippet. There is probably some way we can be clever and generate specialized fast
paths that are more successful than what I tried implementing, but I think that's worth deferring
this to follow up patches once the JITMathIC foundation has landed.

This patch also fixes a bug inside the slow path lambdas in the DFG.
Before, it was not legal to emit an exception check inside them. Now,
it is. So it's now easy to define arbitrary late paths using the DFG
slow path lambda API.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/ArithProfile.cpp: Added.
(JSC::ArithProfile::emitObserveResult):
(JSC::ArithProfile::shouldEmitSetDouble):
(JSC::ArithProfile::emitSetDouble):
(JSC::ArithProfile::shouldEmitSetNonNumber):
(JSC::ArithProfile::emitSetNonNumber):
(WTF::printInternal):
* bytecode/ArithProfile.h: Added.
(JSC::ObservedType::ObservedType):
(JSC::ObservedType::sawInt32):
(JSC::ObservedType::isOnlyInt32):
(JSC::ObservedType::sawNumber):
(JSC::ObservedType::isOnlyNumber):
(JSC::ObservedType::sawNonNumber):
(JSC::ObservedType::isOnlyNonNumber):
(JSC::ObservedType::isEmpty):
(JSC::ObservedType::bits):
(JSC::ObservedType::withInt32):
(JSC::ObservedType::withNumber):
(JSC::ObservedType::withNonNumber):
(JSC::ObservedType::withoutNonNumber):
(JSC::ObservedType::operator==):
(JSC::ArithProfile::ArithProfile):
(JSC::ArithProfile::fromInt):
(JSC::ArithProfile::lhsResultType):
(JSC::ArithProfile::rhsResultType):
(JSC::ArithProfile::lhsObservedType):
(JSC::ArithProfile::rhsObservedType):
(JSC::ArithProfile::setLhsObservedType):
(JSC::ArithProfile::setRhsObservedType):
(JSC::ArithProfile::tookSpecialFastPath):
(JSC::ArithProfile::didObserveNonInt32):
(JSC::ArithProfile::didObserveDouble):
(JSC::ArithProfile::didObserveNonNegZeroDouble):
(JSC::ArithProfile::didObserveNegZeroDouble):
(JSC::ArithProfile::didObserveNonNumber):
(JSC::ArithProfile::didObserveInt32Overflow):
(JSC::ArithProfile::didObserveInt52Overflow):
(JSC::ArithProfile::setObservedNonNegZeroDouble):
(JSC::ArithProfile::setObservedNegZeroDouble):
(JSC::ArithProfile::setObservedNonNumber):
(JSC::ArithProfile::setObservedInt32Overflow):
(JSC::ArithProfile::setObservedInt52Overflow):
(JSC::ArithProfile::addressOfBits):
(JSC::ArithProfile::observeResult):
(JSC::ArithProfile::lhsSawInt32):
(JSC::ArithProfile::lhsSawNumber):
(JSC::ArithProfile::lhsSawNonNumber):
(JSC::ArithProfile::rhsSawInt32):
(JSC::ArithProfile::rhsSawNumber):
(JSC::ArithProfile::rhsSawNonNumber):
(JSC::ArithProfile::observeLHSAndRHS):
(JSC::ArithProfile::bits):
(JSC::ArithProfile::hasBits):
(JSC::ArithProfile::setBit):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpRareCaseProfile):
(JSC::CodeBlock::dumpArithProfile):
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::addStubInfo):
(JSC::CodeBlock::addJITAddIC):
(JSC::CodeBlock::findStubInfo):
(JSC::CodeBlock::resetJITData):
(JSC::CodeBlock::shrinkToFit):
(JSC::CodeBlock::dumpValueProfiles):
(JSC::CodeBlock::rareCaseProfileCountForBytecodeOffset):
(JSC::CodeBlock::arithProfileForBytecodeOffset):
(JSC::CodeBlock::arithProfileForPC):
(JSC::CodeBlock::couldTakeSpecialFastCase):
(JSC::CodeBlock::dumpResultProfile): Deleted.
(JSC::CodeBlock::resultProfileForBytecodeOffset): Deleted.
(JSC::CodeBlock::specialFastCaseProfileCountForBytecodeOffset): Deleted.
(JSC::CodeBlock::ensureResultProfile): Deleted.
* bytecode/CodeBlock.h:
(JSC::CodeBlock::stubInfoBegin):
(JSC::CodeBlock::stubInfoEnd):
(JSC::CodeBlock::couldTakeSlowCase):
(JSC::CodeBlock::numberOfResultProfiles): Deleted.
* bytecode/MethodOfGettingAValueProfile.cpp:
(JSC::MethodOfGettingAValueProfile::emitReportValue):
* bytecode/MethodOfGettingAValueProfile.h:
(JSC::MethodOfGettingAValueProfile::MethodOfGettingAValueProfile):
* bytecode/ValueProfile.cpp:
(JSC::ResultProfile::emitDetectNumericness): Deleted.
(JSC::ResultProfile::emitSetDouble): Deleted.
(JSC::ResultProfile::emitSetNonNumber): Deleted.
(WTF::printInternal): Deleted.
* bytecode/ValueProfile.h:
(JSC::getRareCaseProfileBytecodeOffset):
(JSC::ResultProfile::ResultProfile): Deleted.
(JSC::ResultProfile::bytecodeOffset): Deleted.
(JSC::ResultProfile::specialFastPathCount): Deleted.
(JSC::ResultProfile::didObserveNonInt32): Deleted.
(JSC::ResultProfile::didObserveDouble): Deleted.
(JSC::ResultProfile::didObserveNonNegZeroDouble): Deleted.
(JSC::ResultProfile::didObserveNegZeroDouble): Deleted.
(JSC::ResultProfile::didObserveNonNumber): Deleted.
(JSC::ResultProfile::didObserveInt32Overflow): Deleted.
(JSC::ResultProfile::didObserveInt52Overflow): Deleted.
(JSC::ResultProfile::setObservedNonNegZeroDouble): Deleted.
(JSC::ResultProfile::setObservedNegZeroDouble): Deleted.
(JSC::ResultProfile::setObservedNonNumber): Deleted.
(JSC::ResultProfile::setObservedInt32Overflow): Deleted.
(JSC::ResultProfile::setObservedInt52Overflow): Deleted.
(JSC::ResultProfile::addressOfFlags): Deleted.
(JSC::ResultProfile::addressOfSpecialFastPathCount): Deleted.
(JSC::ResultProfile::detectNumericness): Deleted.
(JSC::ResultProfile::hasBits): Deleted.
(JSC::ResultProfile::setBit): Deleted.
(JSC::getResultProfileBytecodeOffset): Deleted.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitBinaryOp):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::makeSafe):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::methodOfGettingAValueProfileFor):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::exceptionCheck):
* dfg/DFGSlowPathGenerator.h:
(JSC::DFG::SlowPathGenerator::generate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::addSlowPathGenerator):
(JSC::DFG::SpeculativeJIT::runSlowPathGenerators):
(JSC::DFG::SpeculativeJIT::compileValueAdd):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::silentSpillAllRegistersImpl):
(JSC::DFG::SpeculativeJIT::silentSpillAllRegisters):
(JSC::DFG::SpeculativeJIT::callOperation):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
(JSC::FTL::DFG::LowerDFGToB3::compileStrCat):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::setupArgumentsWithExecState):
(JSC::CCallHelpers::setupArguments):
* jit/JIT.h:
* jit/JITAddGenerator.cpp:
(JSC::JITAddGenerator::generateInline):
(JSC::JITAddGenerator::generateFastPath):
* jit/JITAddGenerator.h:
(JSC::JITAddGenerator::JITAddGenerator):
(JSC::JITAddGenerator::didEmitFastPath): Deleted.
(JSC::JITAddGenerator::endJumpList): Deleted.
(JSC::JITAddGenerator::slowPathJumpList): Deleted.
* jit/JITArithmetic.cpp:
(JSC::JIT::emit_op_jless):
(JSC::JIT::emitSlow_op_urshift):
(JSC::getOperandTypes):
(JSC::JIT::emit_op_add):
(JSC::JIT::emitSlow_op_add):
(JSC::JIT::emit_op_div):
(JSC::JIT::emit_op_mul):
(JSC::JIT::emitSlow_op_mul):
(JSC::JIT::emit_op_sub):
(JSC::JIT::emitSlow_op_sub):
* jit/JITDivGenerator.cpp:
(JSC::JITDivGenerator::generateFastPath):
* jit/JITDivGenerator.h:
(JSC::JITDivGenerator::JITDivGenerator):
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITMathIC.h: Added.
(JSC::JITMathIC::doneLocation):
(JSC::JITMathIC::slowPathStartLocation):
(JSC::JITMathIC::slowPathCallLocation):
(JSC::JITMathIC::generateInline):
(JSC::JITMathIC::generateOutOfLine):
(JSC::JITMathIC::finalizeInlineCode):
* jit/JITMathICForwards.h: Added.
* jit/JITMathICInlineResult.h: Added.
* jit/JITMulGenerator.cpp:
(JSC::JITMulGenerator::generateFastPath):
* jit/JITMulGenerator.h:
(JSC::JITMulGenerator::JITMulGenerator):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITSubGenerator.cpp:
(JSC::JITSubGenerator::generateFastPath):
* jit/JITSubGenerator.h:
(JSC::JITSubGenerator::JITSubGenerator):
* jit/Repatch.cpp:
(JSC::readCallTarget):
(JSC::ftlThunkAwareRepatchCall):
(JSC::tryCacheGetByID):
(JSC::repatchGetByID):
(JSC::appropriateGenericPutByIdFunction):
(JSC::tryCachePutByID):
(JSC::repatchPutByID):
(JSC::tryRepatchIn):
(JSC::repatchIn):
(JSC::linkSlowFor):
(JSC::resetGetByID):
(JSC::resetPutByID):
(JSC::repatchCall): Deleted.
* jit/Repatch.h:
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* parser/ResultType.h:
(JSC::ResultType::ResultType):
(JSC::ResultType::isInt32):
(JSC::ResultType::definitelyIsNumber):
(JSC::ResultType::definitelyIsString):
(JSC::ResultType::definitelyIsBoolean):
(JSC::ResultType::mightBeNumber):
(JSC::ResultType::isNotNumber):
(JSC::ResultType::forBitOp):
(JSC::ResultType::bits):
(JSC::OperandTypes::OperandTypes):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
(JSC::updateArithProfileForBinaryArithOp):
(JSC::updateResultProfileForBinaryArithOp): Deleted.
* tests/stress/op-add-exceptions.js: Added.
(assert):
(f1):
(f2):
(f3):
(let.oException.valueOf):
(foo):
(ident):
(bar):

Source/WebCore:

* ForwardingHeaders/jit/JITMathICForwards.h: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeMethodOfGettingAValueProfilecpp">trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeMethodOfGettingAValueProfileh">trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeValueProfilecpp">trunk/Source/JavaScriptCore/bytecode/ValueProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeValueProfileh">trunk/Source/JavaScriptCore/bytecode/ValueProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSlowPathGeneratorh">trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCCallHelpersh">trunk/Source/JavaScriptCore/jit/CCallHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITAddGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITAddGeneratorh">trunk/Source/JavaScriptCore/jit/JITAddGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITArithmeticcpp">trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITDivGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITDivGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITDivGeneratorh">trunk/Source/JavaScriptCore/jit/JITDivGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMulGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMulGeneratorh">trunk/Source/JavaScriptCore/jit/JITMulGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITSubGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITSubGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITSubGeneratorh">trunk/Source/JavaScriptCore/jit/JITSubGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchh">trunk/Source/JavaScriptCore/jit/Repatch.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntDatacpp">trunk/Source/JavaScriptCore/llint/LLIntData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserResultTypeh">trunk/Source/JavaScriptCore/parser/ResultType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorebytecodeArithProfilecpp">trunk/Source/JavaScriptCore/bytecode/ArithProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeArithProfileh">trunk/Source/JavaScriptCore/bytecode/ArithProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMathICh">trunk/Source/JavaScriptCore/jit/JITMathIC.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMathICForwardsh">trunk/Source/JavaScriptCore/jit/JITMathICForwards.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMathICInlineResulth">trunk/Source/JavaScriptCore/jit/JITMathICInlineResult.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressopaddexceptionsjs">trunk/Source/JavaScriptCore/tests/stress/op-add-exceptions.js</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersjitJITMathICForwardsh">trunk/Source/WebCore/ForwardingHeaders/jit/JITMathICForwards.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -176,6 +176,7 @@
</span><span class="cx">     builtins/BuiltinExecutableCreator.cpp
</span><span class="cx"> 
</span><span class="cx">     bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp
</span><ins>+    bytecode/ArithProfile.cpp
</ins><span class="cx">     bytecode/ArrayAllocationProfile.cpp
</span><span class="cx">     bytecode/ArrayProfile.cpp
</span><span class="cx">     bytecode/BytecodeBasicBlock.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -1,3 +1,289 @@
</span><ins>+2016-07-21  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        op_add/ValueAdd should be an IC in all JIT tiers
+        https://bugs.webkit.org/show_bug.cgi?id=159649
+
+        Reviewed by Benjamin Poulain.
+
+        This patch makes Add an IC inside all JIT tiers. It does so in a
+        simple, but effective, way. We will try to generate an int+int add
+        that will repatch itself if its type checks fail. Sometimes though,
+        we have runtime type data saying that the add won't be int+int.
+        In those cases, we will just generate a full snippet that doesn't patch itself.
+        Other times, we may generate no inline code and defer to making a C call. A lot
+        of this patch is just refactoring ResultProfile into what we're now calling ArithProfile.
+        ArithProfile does everything ResultProfile used to do, and more. It records simple type
+        data about the LHS/RHS operands it sees. This allows us to determine if an op_add
+        has only seen int+int operands, etc. ArithProfile will also contain the ResultType
+        for the LHS/RHS that the parser feeds into op_add. ArithProfile now fits into 32-bits.
+        This means instead of having a side table like we did for ResultProfile, we just
+        inject the ArithProfile into the bytecode instruction stream. This makes asking
+        for ArithProfile faster; we no longer need to lock around this operation.
+
+        The size of an Add has gone down on average, but we can still do better.
+        We still generate a lot of code because we generate calls to the slow path.
+        I think we can make this better by moving the slow path to a shared thunk
+        system. This patch mostly lays the foundation for future improvements to Add,
+        and a framework to move all other arithmetic operations to be typed-based ICs.
+
+        Here is some data I took on the average op_add/ValueAdd size on various benchmarks:
+                   |   JetStream  |  Speedometer |  Unity 3D  |
+             ------| -------------|-----------------------------
+              Old  |  189 bytes   |  169 bytes   |  192 bytes |
+             ------| -------------|-----------------------------
+              New  |  148 bytes   |  124 bytes   |  143 bytes |
+             ---------------------------------------------------
+
+        Making an arithmetic IC is now easy. The JITMathIC class will hold a snippet
+        generator as a member variable. To make a snippet an IC, you need to implement
+        a generateInline(.) method, which generates the inline IC. Then, you need to
+        generate the IC where you used to generate the snippet. When generating the
+        IC, we need to inform JITMathIC of various data like we do with StructureStubInfo.
+        We need to tell it about where the slow path starts, where the slow path call is, etc.
+        When generating a JITMathIC, it may tell you that it didn't generate any code inline.
+        This is a request to the user of JITMathIC to just generate a C call along the
+        fast path. JITMathIC may also have the snippet tell it to just generate the full
+        snippet instead of the int+int path along the fast path.
+
+        In subsequent patches, we can improve upon how we decide to generate int+int or
+        the full snippet. I tried to get clever by having double+double, double+int, int+double,
+        fast paths, but they didn't work out nearly as well as the int+int fast path. I ended up
+        generating a lot of code when I did this and ended up using more memory than just generating
+        the full snippet. There is probably some way we can be clever and generate specialized fast
+        paths that are more successful than what I tried implementing, but I think that's worth deferring
+        this to follow up patches once the JITMathIC foundation has landed.
+
+        This patch also fixes a bug inside the slow path lambdas in the DFG.
+        Before, it was not legal to emit an exception check inside them. Now,
+        it is. So it's now easy to define arbitrary late paths using the DFG
+        slow path lambda API.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/ArithProfile.cpp: Added.
+        (JSC::ArithProfile::emitObserveResult):
+        (JSC::ArithProfile::shouldEmitSetDouble):
+        (JSC::ArithProfile::emitSetDouble):
+        (JSC::ArithProfile::shouldEmitSetNonNumber):
+        (JSC::ArithProfile::emitSetNonNumber):
+        (WTF::printInternal):
+        * bytecode/ArithProfile.h: Added.
+        (JSC::ObservedType::ObservedType):
+        (JSC::ObservedType::sawInt32):
+        (JSC::ObservedType::isOnlyInt32):
+        (JSC::ObservedType::sawNumber):
+        (JSC::ObservedType::isOnlyNumber):
+        (JSC::ObservedType::sawNonNumber):
+        (JSC::ObservedType::isOnlyNonNumber):
+        (JSC::ObservedType::isEmpty):
+        (JSC::ObservedType::bits):
+        (JSC::ObservedType::withInt32):
+        (JSC::ObservedType::withNumber):
+        (JSC::ObservedType::withNonNumber):
+        (JSC::ObservedType::withoutNonNumber):
+        (JSC::ObservedType::operator==):
+        (JSC::ArithProfile::ArithProfile):
+        (JSC::ArithProfile::fromInt):
+        (JSC::ArithProfile::lhsResultType):
+        (JSC::ArithProfile::rhsResultType):
+        (JSC::ArithProfile::lhsObservedType):
+        (JSC::ArithProfile::rhsObservedType):
+        (JSC::ArithProfile::setLhsObservedType):
+        (JSC::ArithProfile::setRhsObservedType):
+        (JSC::ArithProfile::tookSpecialFastPath):
+        (JSC::ArithProfile::didObserveNonInt32):
+        (JSC::ArithProfile::didObserveDouble):
+        (JSC::ArithProfile::didObserveNonNegZeroDouble):
+        (JSC::ArithProfile::didObserveNegZeroDouble):
+        (JSC::ArithProfile::didObserveNonNumber):
+        (JSC::ArithProfile::didObserveInt32Overflow):
+        (JSC::ArithProfile::didObserveInt52Overflow):
+        (JSC::ArithProfile::setObservedNonNegZeroDouble):
+        (JSC::ArithProfile::setObservedNegZeroDouble):
+        (JSC::ArithProfile::setObservedNonNumber):
+        (JSC::ArithProfile::setObservedInt32Overflow):
+        (JSC::ArithProfile::setObservedInt52Overflow):
+        (JSC::ArithProfile::addressOfBits):
+        (JSC::ArithProfile::observeResult):
+        (JSC::ArithProfile::lhsSawInt32):
+        (JSC::ArithProfile::lhsSawNumber):
+        (JSC::ArithProfile::lhsSawNonNumber):
+        (JSC::ArithProfile::rhsSawInt32):
+        (JSC::ArithProfile::rhsSawNumber):
+        (JSC::ArithProfile::rhsSawNonNumber):
+        (JSC::ArithProfile::observeLHSAndRHS):
+        (JSC::ArithProfile::bits):
+        (JSC::ArithProfile::hasBits):
+        (JSC::ArithProfile::setBit):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpRareCaseProfile):
+        (JSC::CodeBlock::dumpArithProfile):
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::addStubInfo):
+        (JSC::CodeBlock::addJITAddIC):
+        (JSC::CodeBlock::findStubInfo):
+        (JSC::CodeBlock::resetJITData):
+        (JSC::CodeBlock::shrinkToFit):
+        (JSC::CodeBlock::dumpValueProfiles):
+        (JSC::CodeBlock::rareCaseProfileCountForBytecodeOffset):
+        (JSC::CodeBlock::arithProfileForBytecodeOffset):
+        (JSC::CodeBlock::arithProfileForPC):
+        (JSC::CodeBlock::couldTakeSpecialFastCase):
+        (JSC::CodeBlock::dumpResultProfile): Deleted.
+        (JSC::CodeBlock::resultProfileForBytecodeOffset): Deleted.
+        (JSC::CodeBlock::specialFastCaseProfileCountForBytecodeOffset): Deleted.
+        (JSC::CodeBlock::ensureResultProfile): Deleted.
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::stubInfoBegin):
+        (JSC::CodeBlock::stubInfoEnd):
+        (JSC::CodeBlock::couldTakeSlowCase):
+        (JSC::CodeBlock::numberOfResultProfiles): Deleted.
+        * bytecode/MethodOfGettingAValueProfile.cpp:
+        (JSC::MethodOfGettingAValueProfile::emitReportValue):
+        * bytecode/MethodOfGettingAValueProfile.h:
+        (JSC::MethodOfGettingAValueProfile::MethodOfGettingAValueProfile):
+        * bytecode/ValueProfile.cpp:
+        (JSC::ResultProfile::emitDetectNumericness): Deleted.
+        (JSC::ResultProfile::emitSetDouble): Deleted.
+        (JSC::ResultProfile::emitSetNonNumber): Deleted.
+        (WTF::printInternal): Deleted.
+        * bytecode/ValueProfile.h:
+        (JSC::getRareCaseProfileBytecodeOffset):
+        (JSC::ResultProfile::ResultProfile): Deleted.
+        (JSC::ResultProfile::bytecodeOffset): Deleted.
+        (JSC::ResultProfile::specialFastPathCount): Deleted.
+        (JSC::ResultProfile::didObserveNonInt32): Deleted.
+        (JSC::ResultProfile::didObserveDouble): Deleted.
+        (JSC::ResultProfile::didObserveNonNegZeroDouble): Deleted.
+        (JSC::ResultProfile::didObserveNegZeroDouble): Deleted.
+        (JSC::ResultProfile::didObserveNonNumber): Deleted.
+        (JSC::ResultProfile::didObserveInt32Overflow): Deleted.
+        (JSC::ResultProfile::didObserveInt52Overflow): Deleted.
+        (JSC::ResultProfile::setObservedNonNegZeroDouble): Deleted.
+        (JSC::ResultProfile::setObservedNegZeroDouble): Deleted.
+        (JSC::ResultProfile::setObservedNonNumber): Deleted.
+        (JSC::ResultProfile::setObservedInt32Overflow): Deleted.
+        (JSC::ResultProfile::setObservedInt52Overflow): Deleted.
+        (JSC::ResultProfile::addressOfFlags): Deleted.
+        (JSC::ResultProfile::addressOfSpecialFastPathCount): Deleted.
+        (JSC::ResultProfile::detectNumericness): Deleted.
+        (JSC::ResultProfile::hasBits): Deleted.
+        (JSC::ResultProfile::setBit): Deleted.
+        (JSC::getResultProfileBytecodeOffset): Deleted.
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitBinaryOp):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::makeSafe):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::methodOfGettingAValueProfileFor):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::exceptionCheck):
+        * dfg/DFGSlowPathGenerator.h:
+        (JSC::DFG::SlowPathGenerator::generate):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::addSlowPathGenerator):
+        (JSC::DFG::SpeculativeJIT::runSlowPathGenerators):
+        (JSC::DFG::SpeculativeJIT::compileValueAdd):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::silentSpillAllRegistersImpl):
+        (JSC::DFG::SpeculativeJIT::silentSpillAllRegisters):
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
+        (JSC::FTL::DFG::LowerDFGToB3::compileStrCat):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::setupArgumentsWithExecState):
+        (JSC::CCallHelpers::setupArguments):
+        * jit/JIT.h:
+        * jit/JITAddGenerator.cpp:
+        (JSC::JITAddGenerator::generateInline):
+        (JSC::JITAddGenerator::generateFastPath):
+        * jit/JITAddGenerator.h:
+        (JSC::JITAddGenerator::JITAddGenerator):
+        (JSC::JITAddGenerator::didEmitFastPath): Deleted.
+        (JSC::JITAddGenerator::endJumpList): Deleted.
+        (JSC::JITAddGenerator::slowPathJumpList): Deleted.
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::emit_op_jless):
+        (JSC::JIT::emitSlow_op_urshift):
+        (JSC::getOperandTypes):
+        (JSC::JIT::emit_op_add):
+        (JSC::JIT::emitSlow_op_add):
+        (JSC::JIT::emit_op_div):
+        (JSC::JIT::emit_op_mul):
+        (JSC::JIT::emitSlow_op_mul):
+        (JSC::JIT::emit_op_sub):
+        (JSC::JIT::emitSlow_op_sub):
+        * jit/JITDivGenerator.cpp:
+        (JSC::JITDivGenerator::generateFastPath):
+        * jit/JITDivGenerator.h:
+        (JSC::JITDivGenerator::JITDivGenerator):
+        * jit/JITInlines.h:
+        (JSC::JIT::callOperation):
+        * jit/JITMathIC.h: Added.
+        (JSC::JITMathIC::doneLocation):
+        (JSC::JITMathIC::slowPathStartLocation):
+        (JSC::JITMathIC::slowPathCallLocation):
+        (JSC::JITMathIC::generateInline):
+        (JSC::JITMathIC::generateOutOfLine):
+        (JSC::JITMathIC::finalizeInlineCode):
+        * jit/JITMathICForwards.h: Added.
+        * jit/JITMathICInlineResult.h: Added.
+        * jit/JITMulGenerator.cpp:
+        (JSC::JITMulGenerator::generateFastPath):
+        * jit/JITMulGenerator.h:
+        (JSC::JITMulGenerator::JITMulGenerator):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jit/JITSubGenerator.cpp:
+        (JSC::JITSubGenerator::generateFastPath):
+        * jit/JITSubGenerator.h:
+        (JSC::JITSubGenerator::JITSubGenerator):
+        * jit/Repatch.cpp:
+        (JSC::readCallTarget):
+        (JSC::ftlThunkAwareRepatchCall):
+        (JSC::tryCacheGetByID):
+        (JSC::repatchGetByID):
+        (JSC::appropriateGenericPutByIdFunction):
+        (JSC::tryCachePutByID):
+        (JSC::repatchPutByID):
+        (JSC::tryRepatchIn):
+        (JSC::repatchIn):
+        (JSC::linkSlowFor):
+        (JSC::resetGetByID):
+        (JSC::resetPutByID):
+        (JSC::repatchCall): Deleted.
+        * jit/Repatch.h:
+        * llint/LLIntData.cpp:
+        (JSC::LLInt::Data::performAssertions):
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * parser/ResultType.h:
+        (JSC::ResultType::ResultType):
+        (JSC::ResultType::isInt32):
+        (JSC::ResultType::definitelyIsNumber):
+        (JSC::ResultType::definitelyIsString):
+        (JSC::ResultType::definitelyIsBoolean):
+        (JSC::ResultType::mightBeNumber):
+        (JSC::ResultType::isNotNumber):
+        (JSC::ResultType::forBitOp):
+        (JSC::ResultType::bits):
+        (JSC::OperandTypes::OperandTypes):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        (JSC::updateArithProfileForBinaryArithOp):
+        (JSC::updateResultProfileForBinaryArithOp): Deleted.
+        * tests/stress/op-add-exceptions.js: Added.
+        (assert):
+        (f1):
+        (f2):
+        (f3):
+        (let.oException.valueOf):
+        (foo):
+        (ident):
+        (bar):
+
</ins><span class="cx"> 2016-07-21  Csaba Osztrogonác  &lt;ossy@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Clarify testing mode names in run-jsc-stress-tests
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -1279,6 +1279,7 @@
</span><span class="cx">                 7905BB691D12050E0019FE57 /* InlineAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 7905BB671D12050E0019FE57 /* InlineAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 79160DBD1C8E3EC8008C085A /* ProxyRevoke.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79160DBB1C8E3EC8008C085A /* ProxyRevoke.cpp */; };
</span><span class="cx">                 79160DBE1C8E3EC8008C085A /* ProxyRevoke.h in Headers */ = {isa = PBXBuildFile; fileRef = 79160DBC1C8E3EC8008C085A /* ProxyRevoke.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                79233C2B1D34715700C5A834 /* JITMathIC.h in Headers */ = {isa = PBXBuildFile; fileRef = 79233C291D34715700C5A834 /* JITMathIC.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 792CB3491C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */; };
</span><span class="cx">                 792CB34A1C4EED5C00D13AF3 /* PCToCodeOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 796465681B952FF0003059EE /* GetPutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -1285,10 +1286,14 @@
</span><span class="cx">                 797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */; };
</span><span class="cx">                 797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                79A228351D35D71E00D8E067 /* ArithProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A228331D35D71E00D8E067 /* ArithProfile.cpp */; };
+                79A228361D35D71F00D8E067 /* ArithProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A228341D35D71E00D8E067 /* ArithProfile.h */; };
+                79AF0BE41D3EFD4C00E95FA5 /* JITMathICInlineResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 79AF0BE31D3EFD4C00E95FA5 /* JITMathICInlineResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 79B00CBC1C6AB07E0088C65D /* ProxyConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79B00CB81C6AB07E0088C65D /* ProxyConstructor.cpp */; };
</span><span class="cx">                 79B00CBD1C6AB07E0088C65D /* ProxyConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 79B00CB91C6AB07E0088C65D /* ProxyConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 79B00CBE1C6AB07E0088C65D /* ProxyObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79B00CBA1C6AB07E0088C65D /* ProxyObject.cpp */; settings = {COMPILER_FLAGS = &quot;-fno-optimize-sibling-calls&quot;; }; };
</span><span class="cx">                 79B00CBF1C6AB07E0088C65D /* ProxyObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 79B00CBB1C6AB07E0088C65D /* ProxyObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                79B1788E1D399B8000B1A567 /* JITMathICForwards.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A899FE1D38612E00D18C73 /* JITMathICForwards.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 79C4B15D1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */; };
</span><span class="cx">                 79C4B15E1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */ = {isa = PBXBuildFile; fileRef = 79CFC6EF1C33B10000C768EA /* LLIntPCRanges.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -3479,6 +3484,7 @@
</span><span class="cx">                 7905BB671D12050E0019FE57 /* InlineAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineAccess.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79160DBB1C8E3EC8008C085A /* ProxyRevoke.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyRevoke.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79160DBC1C8E3EC8008C085A /* ProxyRevoke.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProxyRevoke.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                79233C291D34715700C5A834 /* JITMathIC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMathIC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCToCodeOriginMap.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCToCodeOriginMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 796465681B952FF0003059EE /* GetPutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetPutInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3485,6 +3491,10 @@
</span><span class="cx">                 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalLexicalEnvironment.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalLexicalEnvironment.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PCToOriginMap.h; path = b3/B3PCToOriginMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                79A228331D35D71E00D8E067 /* ArithProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArithProfile.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                79A228341D35D71E00D8E067 /* ArithProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArithProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                79A899FE1D38612E00D18C73 /* JITMathICForwards.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMathICForwards.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                79AF0BE31D3EFD4C00E95FA5 /* JITMathICInlineResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMathICInlineResult.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 79B00CB81C6AB07E0088C65D /* ProxyConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyConstructor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79B00CB91C6AB07E0088C65D /* ProxyConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProxyConstructor.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79B00CBA1C6AB07E0088C65D /* ProxyObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyObject.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5070,6 +5080,9 @@
</span><span class="cx">                                 DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */,
</span><span class="cx">                                 1429D92D0ED22D7000B89619 /* JIT.cpp */,
</span><span class="cx">                                 1429D92E0ED22D7000B89619 /* JIT.h */,
</span><ins>+                                79233C291D34715700C5A834 /* JITMathIC.h */,
+                                79A899FE1D38612E00D18C73 /* JITMathICForwards.h */,
+                                79AF0BE31D3EFD4C00E95FA5 /* JITMathICInlineResult.h */,
</ins><span class="cx">                                 FE1220251BE7F5640039E6F2 /* JITAddGenerator.cpp */,
</span><span class="cx">                                 FE1220261BE7F5640039E6F2 /* JITAddGenerator.h */,
</span><span class="cx">                                 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */,
</span><span class="lines">@@ -6571,6 +6584,8 @@
</span><span class="cx">                                 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */,
</span><span class="cx">                                 0F63945115D07051006A597C /* ArrayProfile.cpp */,
</span><span class="cx">                                 0F63945215D07051006A597C /* ArrayProfile.h */,
</span><ins>+                                79A228331D35D71E00D8E067 /* ArithProfile.cpp */,
+                                79A228341D35D71E00D8E067 /* ArithProfile.h */,
</ins><span class="cx">                                 C2FCAE0C17A9C24E0034C735 /* BytecodeBasicBlock.cpp */,
</span><span class="cx">                                 C2FCAE0D17A9C24E0034C735 /* BytecodeBasicBlock.h */,
</span><span class="cx">                                 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */,
</span><span class="lines">@@ -7083,6 +7098,7 @@
</span><span class="cx">                                 A5EA70E819F5B1010098F5EC /* AugmentableInspectorControllerClient.h in Headers */,
</span><span class="cx">                                 0FEC84FF1BDACDAC0080FF74 /* B3ArgumentRegValue.h in Headers */,
</span><span class="cx">                                 0FEC85011BDACDAC0080FF74 /* B3BasicBlock.h in Headers */,
</span><ins>+                                79233C2B1D34715700C5A834 /* JITMathIC.h in Headers */,
</ins><span class="cx">                                 0FEC85021BDACDAC0080FF74 /* B3BasicBlockInlines.h in Headers */,
</span><span class="cx">                                 0FEC85031BDACDAC0080FF74 /* B3BasicBlockUtils.h in Headers */,
</span><span class="cx">                                 0FEC85041BDACDAC0080FF74 /* B3BlockWorklist.h in Headers */,
</span><span class="lines">@@ -7663,6 +7679,7 @@
</span><span class="cx">                                 A7A8AF3A17ADB5F3005AB174 /* Int8Array.h in Headers */,
</span><span class="cx">                                 BC11667B0E199C05008066DD /* InternalFunction.h in Headers */,
</span><span class="cx">                                 1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */,
</span><ins>+                                79AF0BE41D3EFD4C00E95FA5 /* JITMathICInlineResult.h in Headers */,
</ins><span class="cx">                                 A1B9E23A1B4E0D6700BC7FED /* IntlCollator.h in Headers */,
</span><span class="cx">                                 A1B9E23C1B4E0D6700BC7FED /* IntlCollatorConstructor.h in Headers */,
</span><span class="cx">                                 A18193E31B4E0CDB00FC1029 /* IntlCollatorConstructor.lut.h in Headers */,
</span><span class="lines">@@ -7772,6 +7789,7 @@
</span><span class="cx">                                 A51007C1187CC3C600B38879 /* JSGlobalObjectInspectorController.h in Headers */,
</span><span class="cx">                                 A50E4B6418809DD50068A46D /* JSGlobalObjectRuntimeAgent.h in Headers */,
</span><span class="cx">                                 A503FA2A188F105900110F14 /* JSGlobalObjectScriptDebugServer.h in Headers */,
</span><ins>+                                79A228361D35D71F00D8E067 /* ArithProfile.h in Headers */,
</ins><span class="cx">                                 A513E5C0185BFACC007E95AD /* JSInjectedScriptHost.h in Headers */,
</span><span class="cx">                                 A513E5C2185BFACC007E95AD /* JSInjectedScriptHostPrototype.h in Headers */,
</span><span class="cx">                                 C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
</span><span class="lines">@@ -8197,6 +8215,7 @@
</span><span class="cx">                                 0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */,
</span><span class="cx">                                 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */,
</span><span class="cx">                                 9959E92E1BD17FA4001AA413 /* xxd.pl in Headers */,
</span><ins>+                                79B1788E1D399B8000B1A567 /* JITMathICForwards.h in Headers */,
</ins><span class="cx">                                 451539B912DC994500EF7AC4 /* Yarr.h in Headers */,
</span><span class="cx">                                 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */,
</span><span class="cx">                                 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */,
</span><span class="lines">@@ -9282,6 +9301,7 @@
</span><span class="cx">                                 0FEB3ECF16237F6C00AB67AD /* MacroAssembler.cpp in Sources */,
</span><span class="cx">                                 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
</span><span class="cx">                                 FEB137571BB11EF900CD5100 /* MacroAssemblerARM64.cpp in Sources */,
</span><ins>+                                79A228351D35D71E00D8E067 /* ArithProfile.cpp in Sources */,
</ins><span class="cx">                                 A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
</span><span class="cx">                                 FE68C6381B90DE0B0042BCB3 /* MacroAssemblerPrinter.cpp in Sources */,
</span><span class="cx">                                 A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeArithProfilecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/ArithProfile.cpp (0 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ArithProfile.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/ArithProfile.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -0,0 +1,143 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;ArithProfile.h&quot;
+
+#include &quot;CCallHelpers.h&quot;
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+#if ENABLE(JIT)
+void ArithProfile::emitObserveResult(CCallHelpers&amp; jit, JSValueRegs regs, TagRegistersMode mode)
+{
+    if (!shouldEmitSetDouble() &amp;&amp; !shouldEmitSetNonNumber())
+        return;
+
+    CCallHelpers::Jump isInt32 = jit.branchIfInt32(regs, mode);
+    CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode);
+    emitSetDouble(jit);
+    CCallHelpers::Jump done = jit.jump();
+    notDouble.link(&amp;jit);
+    emitSetNonNumber(jit);
+    done.link(&amp;jit);
+    isInt32.link(&amp;jit);
+}
+
+bool ArithProfile::shouldEmitSetDouble() const
+{
+    uint32_t mask = ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble;
+    return (m_bits &amp; mask) != mask;
+}
+
+void ArithProfile::emitSetDouble(CCallHelpers&amp; jit)
+{
+    if (shouldEmitSetDouble())
+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfBits()));
+}
+
+bool ArithProfile::shouldEmitSetNonNumber() const
+{
+    uint32_t mask = ArithProfile::NonNumber;
+    return (m_bits &amp; mask) != mask;
+}
+
+void ArithProfile::emitSetNonNumber(CCallHelpers&amp; jit)
+{
+    if (shouldEmitSetNonNumber())
+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNumber), CCallHelpers::AbsoluteAddress(addressOfBits()));
+}
+#endif // ENABLE(JIT)
+
+} // namespace JSC
+
+namespace WTF {
+    
+using namespace JSC;
+
+void printInternal(PrintStream&amp; out, const ArithProfile&amp; profile)
+{
+    const char* separator = &quot;&quot;;
+
+    out.print(&quot;Result:&lt;&quot;);
+    if (!profile.didObserveNonInt32()) {
+        out.print(&quot;Int32&quot;);
+        separator = &quot;|&quot;;
+    } else {
+        if (profile.didObserveNegZeroDouble()) {
+            out.print(separator, &quot;NegZeroDouble&quot;);
+            separator = &quot;|&quot;;
+        }
+        if (profile.didObserveNonNegZeroDouble()) {
+            out.print(separator, &quot;NonNegZeroDouble&quot;);
+            separator = &quot;|&quot;;
+        }
+        if (profile.didObserveNonNumber()) {
+            out.print(separator, &quot;NonNumber&quot;);
+            separator = &quot;|&quot;;
+        }
+        if (profile.didObserveInt32Overflow()) {
+            out.print(separator, &quot;Int32Overflow&quot;);
+            separator = &quot;|&quot;;
+        }
+        if (profile.didObserveInt52Overflow()) {
+            out.print(separator, &quot;Int52Overflow&quot;);
+            separator = &quot;|&quot;;
+        }
+    }
+    if (profile.tookSpecialFastPath())
+        out.print(separator, &quot;Took special fast path.&quot;);
+    out.print(&quot;&gt;&quot;);
+
+    out.print(&quot; LHS ObservedType:&lt;&quot;);
+    out.print(profile.lhsObservedType());
+    out.print(&quot;&gt; RHS ObservedType:&lt;&quot;);
+    out.print(profile.rhsObservedType());
+    out.print(&quot;&gt;&quot;);
+
+    out.print(&quot; LHS ResultType:&lt;&quot;, RawPointer(bitwise_cast&lt;void*&gt;(static_cast&lt;uintptr_t&gt;(profile.lhsResultType().bits()))));
+    out.print(&quot;&gt; RHS ResultType:&lt;&quot;, RawPointer(bitwise_cast&lt;void*&gt;(static_cast&lt;uintptr_t&gt;(profile.rhsResultType().bits()))));
+    out.print(&quot;&gt;&quot;);
+}
+
+void printInternal(PrintStream&amp; out, const JSC::ObservedType&amp; observedType)
+{
+    const char* separator = &quot;&quot;;
+    if (observedType.sawInt32()) {
+        out.print(separator, &quot;Int32&quot;);
+        separator = &quot;|&quot;;
+    }
+    if (observedType.sawNumber()) {
+        out.print(separator, &quot;Number&quot;);
+        separator = &quot;|&quot;;
+    }
+    if (observedType.sawNonNumber()) {
+        out.print(separator, &quot;NonNumber&quot;);
+        separator = &quot;|&quot;;
+    }
+}
+
+} // namespace WTF
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeArithProfileh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/ArithProfile.h (0 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ArithProfile.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/ArithProfile.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -0,0 +1,225 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#include &quot;GPRInfo.h&quot;
+#include &quot;JSCJSValue.h&quot;
+#include &quot;ResultType.h&quot;
+#include &quot;TagRegistersMode.h&quot;
+
+namespace JSC {
+
+class CCallHelpers;
+
+struct ObservedType {
+    ObservedType(uint8_t bits = TypeEmpty)
+        : m_bits(bits)
+    { }
+
+    bool sawInt32() const { return m_bits &amp; TypeInt32; }
+    bool isOnlyInt32() const { return m_bits == TypeInt32; }
+    bool sawNumber() const { return m_bits &amp; TypeNumber; }
+    bool isOnlyNumber() const { return m_bits == TypeNumber; }
+    bool sawNonNumber() const { return m_bits &amp; TypeNonNumber; }
+    bool isOnlyNonNumber() const { return m_bits == TypeNonNumber; }
+    bool isEmpty() const { return !m_bits; }
+    uint8_t bits() const { return m_bits; }
+
+    ObservedType withInt32() const { return ObservedType(m_bits | TypeInt32); }
+    ObservedType withNumber() const { return ObservedType(m_bits | TypeNumber); }
+    ObservedType withNonNumber() const { return ObservedType(m_bits | TypeNonNumber); }
+    ObservedType withoutNonNumber() const { return ObservedType(m_bits &amp; ~TypeNonNumber); }
+
+    bool operator==(const ObservedType&amp; other) const { return m_bits == other.m_bits; }
+
+    static const uint8_t TypeEmpty = 0x0;
+    static const uint8_t TypeInt32 = 0x1;
+    static const uint8_t TypeNumber = 0x02;
+    static const uint8_t TypeNonNumber = 0x04;
+
+    static const uint32_t numBitsNeeded = 3;
+
+private:
+    uint8_t m_bits;
+};
+
+struct ArithProfile {
+private:
+    static const uint32_t numberOfFlagBits = 5;
+    static const uint32_t rhsResultTypeShift = numberOfFlagBits;
+    static const uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;
+    static const uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded;
+    static const uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
+
+    static_assert(ObservedType::numBitsNeeded == 3, &quot;We make a hard assumption about that here.&quot;);
+    static const uint32_t clearRhsObservedTypeBitMask = ~((1 &lt;&lt; rhsObservedTypeShift) | (1 &lt;&lt; (rhsObservedTypeShift + 1)) | (1 &lt;&lt; (rhsObservedTypeShift + 2)));
+    static const uint32_t clearLhsObservedTypeBitMask = ~((1 &lt;&lt; lhsObservedTypeShift) | (1 &lt;&lt; (lhsObservedTypeShift + 1)) | (1 &lt;&lt; (lhsObservedTypeShift + 2)));
+
+    static const uint32_t resultTypeMask = (1 &lt;&lt; ResultType::numBitsNeeded) - 1;
+    static const uint32_t observedTypeMask = (1 &lt;&lt; ObservedType::numBitsNeeded) - 1;
+public:
+    static const uint32_t specialFastPathBit = 1 &lt;&lt; (lhsObservedTypeShift + ObservedType::numBitsNeeded);
+    static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded) &lt;= (sizeof(uint32_t) * 8) - 1, &quot;Should fit in a uint32_t.&quot;);
+    static_assert(!(specialFastPathBit &amp; ~clearLhsObservedTypeBitMask), &quot;These bits should not intersect.&quot;);
+    static_assert(specialFastPathBit &amp; clearLhsObservedTypeBitMask, &quot;These bits should intersect.&quot;);
+    static_assert(specialFastPathBit &gt; ~clearLhsObservedTypeBitMask, &quot;These bits should not intersect and specialFastPathBit should be a higher bit.&quot;);
+
+    ArithProfile(ResultType lhs, ResultType rhs)
+    {
+        m_bits = (lhs.bits() &lt;&lt; lhsResultTypeShift) | (rhs.bits() &lt;&lt; rhsResultTypeShift);
+        ASSERT(lhsResultType().bits() == lhs.bits() &amp;&amp; rhsResultType().bits() == rhs.bits());
+        ASSERT(lhsObservedType().isEmpty());
+        ASSERT(rhsObservedType().isEmpty());
+    }
+    ArithProfile() { }
+
+    static ArithProfile fromInt(uint32_t bits)
+    {
+        ArithProfile result;
+        result.m_bits = bits;
+        return result;
+    }
+
+    enum ObservedResults {
+        NonNegZeroDouble = 1 &lt;&lt; 0,
+        NegZeroDouble    = 1 &lt;&lt; 1,
+        NonNumber        = 1 &lt;&lt; 2,
+        Int32Overflow    = 1 &lt;&lt; 3,
+        Int52Overflow    = 1 &lt;&lt; 4,
+    };
+
+    ResultType lhsResultType() const { return ResultType((m_bits &gt;&gt; lhsResultTypeShift) &amp; resultTypeMask); }
+    ResultType rhsResultType() const { return ResultType((m_bits &gt;&gt; rhsResultTypeShift) &amp; resultTypeMask); }
+
+    ObservedType lhsObservedType() const { return ObservedType((m_bits &gt;&gt; lhsObservedTypeShift) &amp; observedTypeMask); }
+    ObservedType rhsObservedType() const { return ObservedType((m_bits &gt;&gt; rhsObservedTypeShift) &amp; observedTypeMask); }
+    void setLhsObservedType(ObservedType type)
+    {
+        uint32_t bits = m_bits;
+        bits &amp;= clearLhsObservedTypeBitMask;
+        bits |= type.bits() &lt;&lt; lhsObservedTypeShift;
+        m_bits = bits;
+        ASSERT(lhsObservedType() == type);
+    }
+
+    void setRhsObservedType(ObservedType type)
+    { 
+        uint32_t bits = m_bits;
+        bits &amp;= clearRhsObservedTypeBitMask;
+        bits |= type.bits() &lt;&lt; rhsObservedTypeShift;
+        m_bits = bits;
+        ASSERT(rhsObservedType() == type);
+    }
+
+    bool tookSpecialFastPath() const { return m_bits &amp; specialFastPathBit; }
+
+    bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); }
+    bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); }
+    bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); }
+    bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); }
+    bool didObserveNonNumber() const { return hasBits(NonNumber); }
+    bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); }
+    bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); }
+
+    void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); }
+    void setObservedNegZeroDouble() { setBit(NegZeroDouble); }
+    void setObservedNonNumber() { setBit(NonNumber); }
+    void setObservedInt32Overflow() { setBit(Int32Overflow); }
+    void setObservedInt52Overflow() { setBit(Int52Overflow); }
+
+    void* addressOfBits() { return &amp;m_bits; }
+
+    void observeResult(JSValue value)
+    {
+        if (value.isInt32())
+            return;
+        if (value.isNumber()) {
+            m_bits |= Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble;
+            return;
+        }
+        m_bits |= NonNumber;
+    }
+
+    void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); }
+    void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); }
+    void lhsSawNonNumber() { setLhsObservedType(lhsObservedType().withNonNumber()); }
+    void rhsSawInt32() { setRhsObservedType(rhsObservedType().withInt32()); }
+    void rhsSawNumber() { setRhsObservedType(rhsObservedType().withNumber()); }
+    void rhsSawNonNumber() { setRhsObservedType(rhsObservedType().withNonNumber()); }
+
+    void observeLHSAndRHS(JSValue lhs, JSValue rhs)
+    {
+        ArithProfile newProfile = *this;
+        if (lhs.isNumber()) {
+            if (lhs.isInt32())
+                newProfile.lhsSawInt32();
+            else
+                newProfile.lhsSawNumber();
+        } else
+            newProfile.lhsSawNonNumber();
+
+        if (rhs.isNumber()) {
+            if (rhs.isInt32())
+                newProfile.rhsSawInt32();
+            else
+                newProfile.rhsSawNumber();
+        } else
+            newProfile.rhsSawNonNumber();
+
+        m_bits = newProfile.bits();
+    }
+
+#if ENABLE(JIT)    
+    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
+    // double. Sets NonNumber if it sees a non-number.
+    void emitObserveResult(CCallHelpers&amp;, JSValueRegs, TagRegistersMode = HaveTagRegisters);
+    
+    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
+    bool shouldEmitSetDouble() const;
+    void emitSetDouble(CCallHelpers&amp;);
+    
+    // Sets NonNumber.
+    void emitSetNonNumber(CCallHelpers&amp;);
+    bool shouldEmitSetNonNumber() const;
+#endif // ENABLE(JIT)
+
+    uint32_t bits() const { return m_bits; }
+
+private:
+    bool hasBits(int mask) const { return m_bits &amp; mask; }
+    void setBit(int mask) { m_bits |= mask; }
+
+    uint32_t m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it.
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+void printInternal(PrintStream&amp;, const JSC::ArithProfile&amp;);
+void printInternal(PrintStream&amp;, const JSC::ObservedType&amp;);
+
+} // namespace WTF
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;BasicBlockLocation.h&quot;
</span><span class="cx"> #include &quot;BytecodeGenerator.h&quot;
</span><span class="cx"> #include &quot;BytecodeUseDef.h&quot;
</span><span class="lines">@@ -45,6 +46,7 @@
</span><span class="cx"> #include &quot;InlineCallFrame.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JIT.h&quot;
</span><ins>+#include &quot;JITMathIC.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;JSLexicalEnvironment.h&quot;
</span><span class="lines">@@ -769,7 +771,7 @@
</span><span class="cx">     out.print(name, profile-&gt;m_counter);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CodeBlock::dumpResultProfile(PrintStream&amp; out, ResultProfile* profile, bool&amp; hasPrintedProfiling)
</del><ins>+void CodeBlock::dumpArithProfile(PrintStream&amp; out, ArithProfile* profile, bool&amp; hasPrintedProfiling)
</ins><span class="cx"> {
</span><span class="cx">     if (!profile)
</span><span class="cx">         return;
</span><span class="lines">@@ -1773,8 +1775,7 @@
</span><span class="cx"> 
</span><span class="cx">     dumpRareCaseProfile(out, &quot;rare case: &quot;, rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
</span><span class="cx">     {
</span><del>-        ConcurrentJITLocker locker(m_lock);
-        dumpResultProfile(out, resultProfileForBytecodeOffset(locker, location), hasPrintedProfiling);
</del><ins>+        dumpArithProfile(out, arithProfileForBytecodeOffset(location), hasPrintedProfiling);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="lines">@@ -3007,6 +3008,11 @@
</span><span class="cx">     return m_stubInfos.add(accessType);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JITAddIC* CodeBlock::addJITAddIC()
+{
+    return m_addICs.add();
+}
+
</ins><span class="cx"> StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
</span><span class="cx"> {
</span><span class="cx">     for (StructureStubInfo* stubInfo : m_stubInfos) {
</span><span class="lines">@@ -3053,11 +3059,6 @@
</span><span class="cx">     // We can clear this because the DFG's queries to these data structures are guarded by whether
</span><span class="cx">     // there is JIT code.
</span><span class="cx">     m_rareCaseProfiles.clear();
</span><del>-    
-    // We can clear these because the DFG only accesses members of this data structure when
-    // holding the lock or after querying whether we have JIT code.
-    m_resultProfiles.clear();
-    m_bytecodeOffsetToResultProfileIndexMap = nullptr;
</del><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -3287,7 +3288,6 @@
</span><span class="cx">     ConcurrentJITLocker locker(m_lock);
</span><span class="cx"> 
</span><span class="cx">     m_rareCaseProfiles.shrinkToFit();
</span><del>-    m_resultProfiles.shrinkToFit();
</del><span class="cx">     
</span><span class="cx">     if (shrinkMode == EarlyShrink) {
</span><span class="cx">         m_constantRegisters.shrinkToFit();
</span><span class="lines">@@ -4163,11 +4163,6 @@
</span><span class="cx">         RareCaseProfile* profile = rareCaseProfile(i);
</span><span class="cx">         dataLogF(&quot;   bc = %d: %u\n&quot;, profile-&gt;m_bytecodeOffset, profile-&gt;m_counter);
</span><span class="cx">     }
</span><del>-    dataLog(&quot;ResultProfile for &quot;, *this, &quot;:\n&quot;);
-    for (unsigned i = 0; i &lt; numberOfResultProfiles(); ++i) {
-        const ResultProfile&amp; profile = *resultProfile(i);
-        dataLog(&quot;   bc = &quot;, profile.bytecodeOffset(), &quot;: &quot;, profile, &quot;\n&quot;);
-    }
</del><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(VERBOSE_VALUE_PROFILE)
</span><span class="cx"> 
</span><span class="lines">@@ -4370,28 +4365,45 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ResultProfile* CodeBlock::resultProfileForBytecodeOffset(const ConcurrentJITLocker&amp;, int bytecodeOffset)
</del><ins>+ArithProfile* CodeBlock::arithProfileForBytecodeOffset(int bytecodeOffset)
</ins><span class="cx"> {
</span><del>-    if (!m_bytecodeOffsetToResultProfileIndexMap)
</del><ins>+    auto opcodeID = vm()-&gt;interpreter-&gt;getOpcodeID(instructions()[bytecodeOffset].u.opcode);
+    switch (opcodeID) {
+    case op_bitor:
+    case op_bitand:
+    case op_bitxor:
+    case op_add:
+    case op_mul:
+    case op_sub:
+    case op_div:
+        break;
+    default:
</ins><span class="cx">         return nullptr;
</span><del>-    auto iterator = m_bytecodeOffsetToResultProfileIndexMap-&gt;find(bytecodeOffset);
-    if (iterator == m_bytecodeOffsetToResultProfileIndexMap-&gt;end())
-        return nullptr;
-    return &amp;m_resultProfiles[iterator-&gt;value];
</del><ins>+    }
+
+    return &amp;arithProfileForPC(instructions().begin() + bytecodeOffset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned CodeBlock::specialFastCaseProfileCountForBytecodeOffset(int bytecodeOffset)
</del><ins>+ArithProfile&amp; CodeBlock::arithProfileForPC(Instruction* pc)
</ins><span class="cx"> {
</span><del>-    ConcurrentJITLocker locker(m_lock);
-    return specialFastCaseProfileCountForBytecodeOffset(locker, bytecodeOffset);
-}
</del><ins>+    if (!ASSERT_DISABLED) {
+        ASSERT(pc &gt;= instructions().begin() &amp;&amp; pc &lt; instructions().end());
+        auto opcodeID = vm()-&gt;interpreter-&gt;getOpcodeID(pc[0].u.opcode);
+        switch (opcodeID) {
+        case op_bitor:
+        case op_bitand:
+        case op_bitxor:
+        case op_add:
+        case op_mul:
+        case op_sub:
+        case op_div:
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
</ins><span class="cx"> 
</span><del>-unsigned CodeBlock::specialFastCaseProfileCountForBytecodeOffset(const ConcurrentJITLocker&amp; locker, int bytecodeOffset)
-{
-    ResultProfile* profile = resultProfileForBytecodeOffset(locker, bytecodeOffset);
-    if (!profile)
-        return 0;
-    return profile-&gt;specialFastPathCount();
</del><ins>+    return *bitwise_cast&lt;ArithProfile*&gt;(&amp;pc[4].u.operand);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool CodeBlock::couldTakeSpecialFastCase(int bytecodeOffset)
</span><span class="lines">@@ -4398,30 +4410,12 @@
</span><span class="cx"> {
</span><span class="cx">     if (!hasBaselineJITProfiling())
</span><span class="cx">         return false;
</span><del>-    unsigned specialFastCaseCount = specialFastCaseProfileCountForBytecodeOffset(bytecodeOffset);
-    return specialFastCaseCount &gt;= Options::couldTakeSlowCaseMinimumCount();
</del><ins>+    ArithProfile* profile = arithProfileForBytecodeOffset(bytecodeOffset);
+    if (!profile)
+        return false;
+    return profile-&gt;tookSpecialFastPath();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ResultProfile* CodeBlock::ensureResultProfile(int bytecodeOffset)
-{
-    ConcurrentJITLocker locker(m_lock);
-    return ensureResultProfile(locker, bytecodeOffset);
-}
-
-ResultProfile* CodeBlock::ensureResultProfile(const ConcurrentJITLocker&amp; locker, int bytecodeOffset)
-{
-    ResultProfile* profile = resultProfileForBytecodeOffset(locker, bytecodeOffset);
-    if (!profile) {
-        m_resultProfiles.append(ResultProfile(bytecodeOffset));
-        profile = &amp;m_resultProfiles.last();
-        ASSERT(&amp;m_resultProfiles.last() == &amp;m_resultProfiles[m_resultProfiles.size() - 1]);
-        if (!m_bytecodeOffsetToResultProfileIndexMap)
-            m_bytecodeOffsetToResultProfileIndexMap = std::make_unique&lt;BytecodeOffsetToResultProfileIndexMap&gt;();
-        m_bytecodeOffsetToResultProfileIndexMap-&gt;add(bytecodeOffset, m_resultProfiles.size() - 1);
-    }
-    return profile;
-}
-
</del><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> DFG::CapabilityLevel CodeBlock::capabilityLevel()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx"> #include &quot;HandlerInfo.h&quot;
</span><span class="cx"> #include &quot;Instruction.h&quot;
</span><span class="cx"> #include &quot;JITCode.h&quot;
</span><ins>+#include &quot;JITMathICForwards.h&quot;
</ins><span class="cx"> #include &quot;JITWriteBarrier.h&quot;
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><span class="lines">@@ -79,6 +80,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class ExecState;
</span><ins>+class JITAddGenerator;
</ins><span class="cx"> class JSModuleEnvironment;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><span class="cx"> class PCToCodeOriginMap;
</span><span class="lines">@@ -88,6 +90,8 @@
</span><span class="cx"> 
</span><span class="cx"> enum class AccessType : int8_t;
</span><span class="cx"> 
</span><ins>+struct ArithProfile;
+
</ins><span class="cx"> typedef HashMap&lt;CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash&gt; StubInfoMap;
</span><span class="cx"> 
</span><span class="cx"> enum ReoptimizationMode { DontCountReoptimization, CountReoptimization };
</span><span class="lines">@@ -245,6 +249,7 @@
</span><span class="cx">     
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     StructureStubInfo* addStubInfo(AccessType);
</span><ins>+    JITAddIC* addJITAddIC();
</ins><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><span class="cx">     
</span><span class="lines">@@ -440,14 +445,9 @@
</span><span class="cx">         return value &gt;= Options::couldTakeSlowCaseMinimumCount();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ResultProfile* ensureResultProfile(int bytecodeOffset);
-    ResultProfile* ensureResultProfile(const ConcurrentJITLocker&amp;, int bytecodeOffset);
-    unsigned numberOfResultProfiles() { return m_resultProfiles.size(); }
-    ResultProfile* resultProfileForBytecodeOffset(const ConcurrentJITLocker&amp;, int bytecodeOffset);
</del><ins>+    ArithProfile* arithProfileForBytecodeOffset(int bytecodeOffset);
+    ArithProfile&amp; arithProfileForPC(Instruction*);
</ins><span class="cx"> 
</span><del>-    unsigned specialFastCaseProfileCountForBytecodeOffset(const ConcurrentJITLocker&amp;, int bytecodeOffset);
-    unsigned specialFastCaseProfileCountForBytecodeOffset(int bytecodeOffset);
-
</del><span class="cx">     bool couldTakeSpecialFastCase(int bytecodeOffset);
</span><span class="cx"> 
</span><span class="cx">     unsigned numberOfArrayProfiles() const { return m_arrayProfiles.size(); }
</span><span class="lines">@@ -957,7 +957,7 @@
</span><span class="cx">     void dumpValueProfiling(PrintStream&amp;, const Instruction*&amp;, bool&amp; hasPrintedProfiling);
</span><span class="cx">     void dumpArrayProfiling(PrintStream&amp;, const Instruction*&amp;, bool&amp; hasPrintedProfiling);
</span><span class="cx">     void dumpRareCaseProfile(PrintStream&amp;, const char* name, RareCaseProfile*, bool&amp; hasPrintedProfiling);
</span><del>-    void dumpResultProfile(PrintStream&amp;, ResultProfile*, bool&amp; hasPrintedProfiling);
</del><ins>+    void dumpArithProfile(PrintStream&amp;, ArithProfile*, bool&amp; hasPrintedProfiling);
</ins><span class="cx"> 
</span><span class="cx">     bool shouldVisitStrongly();
</span><span class="cx">     bool shouldJettisonDueToWeakReference();
</span><span class="lines">@@ -1013,6 +1013,7 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     std::unique_ptr&lt;RegisterAtOffsetList&gt; m_calleeSaveRegisters;
</span><span class="cx">     Bag&lt;StructureStubInfo&gt; m_stubInfos;
</span><ins>+    Bag&lt;JITAddIC&gt; m_addICs;
</ins><span class="cx">     Bag&lt;ByValInfo&gt; m_byValInfos;
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     SentinelLinkedList&lt;CallLinkInfo, BasicRawSentinelNode&lt;CallLinkInfo&gt;&gt; m_incomingCalls;
</span><span class="lines">@@ -1029,9 +1030,6 @@
</span><span class="cx">     RefCountedArray&lt;ValueProfile&gt; m_argumentValueProfiles;
</span><span class="cx">     RefCountedArray&lt;ValueProfile&gt; m_valueProfiles;
</span><span class="cx">     SegmentedVector&lt;RareCaseProfile, 8&gt; m_rareCaseProfiles;
</span><del>-    SegmentedVector&lt;ResultProfile, 8&gt; m_resultProfiles;
-    typedef HashMap&lt;unsigned, unsigned, IntHash&lt;unsigned&gt;, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt; BytecodeOffsetToResultProfileIndexMap;
-    std::unique_ptr&lt;BytecodeOffsetToResultProfileIndexMap&gt; m_bytecodeOffsetToResultProfileIndexMap;
</del><span class="cx">     RefCountedArray&lt;ArrayAllocationProfile&gt; m_arrayAllocationProfiles;
</span><span class="cx">     ArrayProfileVector m_arrayProfiles;
</span><span class="cx">     RefCountedArray&lt;ObjectAllocationProfile&gt; m_objectAllocationProfiles;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeMethodOfGettingAValueProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="lines">@@ -65,8 +66,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case ResultProfileReady: {
-        u.resultProfile-&gt;emitDetectNumericness(jit, regs, DoNotHaveTagRegisters);
</del><ins>+    case ArithProfileReady: {
+        u.arithProfile-&gt;emitObserveResult(jit, regs, DoNotHaveTagRegisters);
</ins><span class="cx">         return;
</span><span class="cx">     } }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeMethodOfGettingAValueProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx"> class CCallHelpers;
</span><span class="cx"> class CodeBlock;
</span><span class="cx"> class LazyOperandValueProfileKey;
</span><del>-struct ResultProfile;
</del><ins>+struct ArithProfile;
</ins><span class="cx"> struct ValueProfile;
</span><span class="cx"> 
</span><span class="cx"> class MethodOfGettingAValueProfile {
</span><span class="lines">@@ -59,11 +59,11 @@
</span><span class="cx">             m_kind = None;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    MethodOfGettingAValueProfile(ResultProfile* profile)
</del><ins>+    MethodOfGettingAValueProfile(ArithProfile* profile)
</ins><span class="cx">     {
</span><span class="cx">         if (profile) {
</span><del>-            m_kind = ResultProfileReady;
-            u.resultProfile = profile;
</del><ins>+            m_kind = ArithProfileReady;
+            u.arithProfile = profile;
</ins><span class="cx">         } else
</span><span class="cx">             m_kind = None;
</span><span class="cx">     }
</span><span class="lines">@@ -79,7 +79,7 @@
</span><span class="cx">     enum Kind {
</span><span class="cx">         None,
</span><span class="cx">         Ready,
</span><del>-        ResultProfileReady,
</del><ins>+        ArithProfileReady,
</ins><span class="cx">         LazyOperand
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="lines">@@ -86,7 +86,7 @@
</span><span class="cx">     Kind m_kind;
</span><span class="cx">     union {
</span><span class="cx">         ValueProfile* profile;
</span><del>-        ResultProfile* resultProfile;
</del><ins>+        ArithProfile* arithProfile;
</ins><span class="cx">         struct {
</span><span class="cx">             CodeBlock* codeBlock;
</span><span class="cx">             unsigned bytecodeOffset;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeValueProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ValueProfile.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ValueProfile.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/bytecode/ValueProfile.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -31,70 +31,4 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-#if ENABLE(JIT)
-void ResultProfile::emitDetectNumericness(CCallHelpers&amp; jit, JSValueRegs regs, TagRegistersMode mode)
-{
-    CCallHelpers::Jump isInt32 = jit.branchIfInt32(regs, mode);
-    CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode);
-    // FIXME: We could be more precise here.
-    emitSetDouble(jit);
-    CCallHelpers::Jump done = jit.jump();
-    notDouble.link(&amp;jit);
-    emitSetNonNumber(jit);
-    done.link(&amp;jit);
-    isInt32.link(&amp;jit);
-}
-
-void ResultProfile::emitSetDouble(CCallHelpers&amp; jit)
-{
-    jit.or32(CCallHelpers::TrustedImm32(ResultProfile::Int32Overflow | ResultProfile::Int52Overflow | ResultProfile::NegZeroDouble | ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfFlags()));
-}
-
-void ResultProfile::emitSetNonNumber(CCallHelpers&amp; jit)
-{
-    jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNumber), CCallHelpers::AbsoluteAddress(addressOfFlags()));
-}
-#endif // ENABLE(JIT)
-
</del><span class="cx"> } // namespace JSC
</span><del>-
-namespace WTF {
-    
-using namespace JSC;
-
-void printInternal(PrintStream&amp; out, const ResultProfile&amp; profile)
-{
-    const char* separator = &quot;&quot;;
-
-    if (!profile.didObserveNonInt32()) {
-        out.print(&quot;Int32&quot;);
-        separator = &quot;|&quot;;
-    } else {
-        if (profile.didObserveNegZeroDouble()) {
-            out.print(separator, &quot;NegZeroDouble&quot;);
-            separator = &quot;|&quot;;
-        }
-        if (profile.didObserveNonNegZeroDouble()) {
-            out.print(&quot;NonNegZeroDouble&quot;);
-            separator = &quot;|&quot;;
-        }
-        if (profile.didObserveNonNumber()) {
-            out.print(&quot;NonNumber&quot;);
-            separator = &quot;|&quot;;
-        }
-        if (profile.didObserveInt32Overflow()) {
-            out.print(&quot;Int32Overflow&quot;);
-            separator = &quot;|&quot;;
-        }
-        if (profile.didObserveInt52Overflow()) {
-            out.print(&quot;Int52Overflow&quot;);
-            separator = &quot;|&quot;;
-        }
-    }
-    if (profile.specialFastPathCount()) {
-        out.print(&quot; special fast path: &quot;);
-        out.print(profile.specialFastPathCount());
-    }
-}
-
-} // namespace WTF
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeValueProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ValueProfile.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ValueProfile.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/bytecode/ValueProfile.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -209,88 +209,6 @@
</span><span class="cx">     return rareCaseProfile-&gt;m_bytecodeOffset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-struct ResultProfile {
-private:
-    static const int numberOfFlagBits = 5;
-
-public:
-    ResultProfile(int bytecodeOffset)
-        : m_bytecodeOffsetAndFlags(bytecodeOffset &lt;&lt; numberOfFlagBits)
-    {
-        ASSERT(((bytecodeOffset &lt;&lt; numberOfFlagBits) &gt;&gt; numberOfFlagBits) == bytecodeOffset);
-    }
-
-    enum ObservedResults {
-        NonNegZeroDouble = 1 &lt;&lt; 0,
-        NegZeroDouble    = 1 &lt;&lt; 1,
-        NonNumber        = 1 &lt;&lt; 2,
-        Int32Overflow    = 1 &lt;&lt; 3,
-        Int52Overflow    = 1 &lt;&lt; 4,
-    };
-
-    int bytecodeOffset() const { return m_bytecodeOffsetAndFlags &gt;&gt; numberOfFlagBits; }
-    unsigned specialFastPathCount() const { return m_specialFastPathCount; }
-
-    bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); }
-    bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); }
-    bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); }
-    bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); }
-    bool didObserveNonNumber() const { return hasBits(NonNumber); }
-    bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); }
-    bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); }
-
-    void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); }
-    void setObservedNegZeroDouble() { setBit(NegZeroDouble); }
-    void setObservedNonNumber() { setBit(NonNumber); }
-    void setObservedInt32Overflow() { setBit(Int32Overflow); }
-    void setObservedInt52Overflow() { setBit(Int52Overflow); }
-
-    void* addressOfFlags() { return &amp;m_bytecodeOffsetAndFlags; }
-    void* addressOfSpecialFastPathCount() { return &amp;m_specialFastPathCount; }
-    
-    void detectNumericness(JSValue value)
-    {
-        if (value.isInt32())
-            return;
-        if (value.isNumber()) {
-            m_bytecodeOffsetAndFlags |= Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble;
-            return;
-        }
-        m_bytecodeOffsetAndFlags |= NonNumber;
-    }
-
-#if ENABLE(JIT)    
-    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
-    // double. Sets NonNumber if it sees a non-number.
-    void emitDetectNumericness(CCallHelpers&amp;, JSValueRegs, TagRegistersMode = HaveTagRegisters);
-    
-    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
-    void emitSetDouble(CCallHelpers&amp;);
-    
-    // Sets NonNumber.
-    void emitSetNonNumber(CCallHelpers&amp;);
-#endif // ENABLE(JIT)
-
-private:
-    bool hasBits(int mask) const { return m_bytecodeOffsetAndFlags &amp; mask; }
-    void setBit(int mask) { m_bytecodeOffsetAndFlags |= mask; }
-
-    int m_bytecodeOffsetAndFlags;
-    unsigned m_specialFastPathCount { 0 };
-};
-
-inline int getResultProfileBytecodeOffset(ResultProfile* profile)
-{
-    return profile-&gt;bytecodeOffset();
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><del>-namespace WTF {
-
-void printInternal(PrintStream&amp;, const JSC::ResultProfile&amp;);
-
-} // namespace WTF
-
</del><span class="cx"> #endif // ValueProfile_h
</span><del>-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;BytecodeGenerator.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;BuiltinExecutables.h&quot;
</span><span class="cx"> #include &quot;BytecodeLivenessAnalysis.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="lines">@@ -1600,7 +1601,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
</span><span class="cx">         opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
</span><del>-        instructions().append(types.toInt());
</del><ins>+        instructions().append(ArithProfile(types.first(), types.second()).bits());
</ins><span class="cx"> 
</span><span class="cx">     return dst;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;ArrayConstructor.h&quot;
</span><span class="cx"> #include &quot;BasicBlockLocation.h&quot;
</span><span class="cx"> #include &quot;CallLinkStatus.h&quot;
</span><span class="lines">@@ -914,29 +915,28 @@
</span><span class="cx">             return node;
</span><span class="cx"> 
</span><span class="cx">         {
</span><del>-            ConcurrentJITLocker locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
-            ResultProfile* resultProfile = m_inlineStackTop-&gt;m_profiledBlock-&gt;resultProfileForBytecodeOffset(locker, m_currentIndex);
-            if (resultProfile) {
</del><ins>+            ArithProfile* arithProfile = m_inlineStackTop-&gt;m_profiledBlock-&gt;arithProfileForBytecodeOffset(m_currentIndex);
+            if (arithProfile) {
</ins><span class="cx">                 switch (node-&gt;op()) {
</span><span class="cx">                 case ArithAdd:
</span><span class="cx">                 case ArithSub:
</span><span class="cx">                 case ValueAdd:
</span><del>-                    if (resultProfile-&gt;didObserveDouble())
</del><ins>+                    if (arithProfile-&gt;didObserveDouble())
</ins><span class="cx">                         node-&gt;mergeFlags(NodeMayHaveDoubleResult);
</span><del>-                    if (resultProfile-&gt;didObserveNonNumber())
</del><ins>+                    if (arithProfile-&gt;didObserveNonNumber())
</ins><span class="cx">                         node-&gt;mergeFlags(NodeMayHaveNonNumberResult);
</span><span class="cx">                     break;
</span><span class="cx">                 
</span><span class="cx">                 case ArithMul: {
</span><del>-                    if (resultProfile-&gt;didObserveInt52Overflow())
</del><ins>+                    if (arithProfile-&gt;didObserveInt52Overflow())
</ins><span class="cx">                         node-&gt;mergeFlags(NodeMayOverflowInt52);
</span><del>-                    if (resultProfile-&gt;didObserveInt32Overflow() || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, Overflow))
</del><ins>+                    if (arithProfile-&gt;didObserveInt32Overflow() || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, Overflow))
</ins><span class="cx">                         node-&gt;mergeFlags(NodeMayOverflowInt32InBaseline);
</span><del>-                    if (resultProfile-&gt;didObserveNegZeroDouble() || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
</del><ins>+                    if (arithProfile-&gt;didObserveNegZeroDouble() || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
</ins><span class="cx">                         node-&gt;mergeFlags(NodeMayNegZeroInBaseline);
</span><del>-                    if (resultProfile-&gt;didObserveDouble())
</del><ins>+                    if (arithProfile-&gt;didObserveDouble())
</ins><span class="cx">                         node-&gt;mergeFlags(NodeMayHaveDoubleResult);
</span><del>-                    if (resultProfile-&gt;didObserveNonNumber())
</del><ins>+                    if (arithProfile-&gt;didObserveNonNumber())
</ins><span class="cx">                         node-&gt;mergeFlags(NodeMayHaveNonNumberResult);
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -1548,9 +1548,8 @@
</span><span class="cx">             return profiledBlock-&gt;valueProfileForBytecodeOffset(node-&gt;origin.semantic.bytecodeIndex);
</span><span class="cx">         
</span><span class="cx">         {
</span><del>-            ConcurrentJITLocker locker(profiledBlock-&gt;m_lock);
</del><span class="cx">             if (profiledBlock-&gt;hasBaselineJITProfiling()) {
</span><del>-                if (ResultProfile* result = profiledBlock-&gt;resultProfileForBytecodeOffset(locker, node-&gt;origin.semantic.bytecodeIndex))
</del><ins>+                if (ArithProfile* result = profiledBlock-&gt;arithProfileForBytecodeOffset(node-&gt;origin.semantic.bytecodeIndex))
</ins><span class="cx">                     return result;
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -604,7 +604,7 @@
</span><span class="cx">     HandlerInfo* exceptionHandler;
</span><span class="cx">     bool willCatchException = m_graph.willCatchExceptionInMachineFrame(m_speculative-&gt;m_currentNode-&gt;origin.forExit, opCatchOrigin, exceptionHandler); 
</span><span class="cx">     if (willCatchException) {
</span><del>-        unsigned streamIndex = m_speculative-&gt;m_outOfLineStreamIndex != UINT_MAX ? m_speculative-&gt;m_outOfLineStreamIndex : m_speculative-&gt;m_stream-&gt;size();
</del><ins>+        unsigned streamIndex = m_speculative-&gt;m_outOfLineStreamIndex ? *m_speculative-&gt;m_outOfLineStreamIndex : m_speculative-&gt;m_stream-&gt;size();
</ins><span class="cx">         MacroAssembler::Jump hadException = emitNonPatchableExceptionCheck();
</span><span class="cx">         // We assume here that this is called after callOpeartion()/appendCall() is called.
</span><span class="cx">         appendExceptionHandlingOSRExit(ExceptionCheck, streamIndex, opCatchOrigin, exceptionHandler, m_jitCode-&gt;common.lastCallSite(), hadException);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSlowPathGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">         jit-&gt;m_outOfLineStreamIndex = m_streamIndex;
</span><span class="cx">         jit-&gt;m_origin = m_origin;
</span><span class="cx">         generateInternal(jit);
</span><del>-        jit-&gt;m_outOfLineStreamIndex = UINT_MAX;
</del><ins>+        jit-&gt;m_outOfLineStreamIndex = Nullopt;
</ins><span class="cx">         if (!ASSERT_DISABLED)
</span><span class="cx">             jit-&gt;m_jit.abortWithReason(DFGSlowPathGeneratorFellThrough);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &quot;JITBitXorGenerator.h&quot;
</span><span class="cx"> #include &quot;JITDivGenerator.h&quot;
</span><span class="cx"> #include &quot;JITLeftShiftGenerator.h&quot;
</span><ins>+#include &quot;JITMathIC.h&quot;
</ins><span class="cx"> #include &quot;JITMulGenerator.h&quot;
</span><span class="cx"> #include &quot;JITRightShiftGenerator.h&quot;
</span><span class="cx"> #include &quot;JITSubGenerator.h&quot;
</span><span class="lines">@@ -56,6 +57,7 @@
</span><span class="cx"> #include &quot;ScopedArguments.h&quot;
</span><span class="cx"> #include &quot;ScratchRegisterAllocator.h&quot;
</span><span class="cx"> #include &quot;WriteBarrierBuffer.h&quot;
</span><ins>+#include &lt;wtf/Box.h&gt;
</ins><span class="cx"> #include &lt;wtf/MathExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="lines">@@ -362,7 +364,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::addSlowPathGenerator(std::function&lt;void()&gt; lambda)
</span><span class="cx"> {
</span><del>-    m_slowPathLambdas.append(std::make_pair(lambda, m_currentNode));
</del><ins>+    m_slowPathLambdas.append(SlowPathLambda{ lambda, m_currentNode, static_cast&lt;unsigned&gt;(m_stream-&gt;size()) });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder&amp; pcToCodeOriginMapBuilder)
</span><span class="lines">@@ -371,11 +373,13 @@
</span><span class="cx">         pcToCodeOriginMapBuilder.appendItem(m_jit.label(), slowPathGenerator-&gt;origin().semantic);
</span><span class="cx">         slowPathGenerator-&gt;generate(this);
</span><span class="cx">     }
</span><del>-    for (auto&amp; generatorPair : m_slowPathLambdas) {
-        Node* currentNode = generatorPair.second;
</del><ins>+    for (auto&amp; slowPathLambda : m_slowPathLambdas) {
+        Node* currentNode = slowPathLambda.currentNode;
</ins><span class="cx">         m_currentNode = currentNode;
</span><ins>+        m_outOfLineStreamIndex = slowPathLambda.streamIndex;
</ins><span class="cx">         pcToCodeOriginMapBuilder.appendItem(m_jit.label(), currentNode-&gt;origin.semantic);
</span><del>-        generatorPair.first();
</del><ins>+        slowPathLambda.generator();
+        m_outOfLineStreamIndex = Nullopt;
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -3379,31 +3383,64 @@
</span><span class="cx">         rightRegs = right-&gt;jsValueRegs();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JITAddGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
-        leftFPR, rightFPR, scratchGPR, scratchFPR);
-    gen.generateFastPath(m_jit);
</del><ins>+    JITAddIC* addIC = m_jit.codeBlock()-&gt;addJITAddIC();
+    Box&lt;MathICGenerationState&gt; addICGenerationState = Box&lt;MathICGenerationState&gt;::create();
+    ArithProfile* arithProfile = m_jit.graph().baselineCodeBlockFor(node-&gt;origin.semantic)-&gt;arithProfileForBytecodeOffset(node-&gt;origin.semantic.bytecodeIndex);
+    addIC-&gt;m_generator = JITAddGenerator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, leftFPR, rightFPR, scratchGPR, scratchFPR, arithProfile);
</ins><span class="cx"> 
</span><del>-    ASSERT(gen.didEmitFastPath());
-    gen.endJumpList().append(m_jit.jump());
</del><ins>+    bool generatedInline = addIC-&gt;generateInline(m_jit, *addICGenerationState);
</ins><span class="cx"> 
</span><del>-    gen.slowPathJumpList().link(&amp;m_jit);
</del><ins>+    if (generatedInline) {
+        ASSERT(!addICGenerationState-&gt;slowPathJumps.empty());
</ins><span class="cx"> 
</span><del>-    silentSpillAllRegisters(resultRegs);
</del><ins>+        Vector&lt;SilentRegisterSavePlan&gt; savePlans;
+        silentSpillAllRegistersImpl(false, savePlans, resultRegs);
</ins><span class="cx"> 
</span><del>-    if (leftOperand.isConst()) {
-        leftRegs = resultRegs;
-        m_jit.moveValue(leftChild-&gt;asJSValue(), leftRegs);
-    } else if (rightOperand.isConst()) {
-        rightRegs = resultRegs;
-        m_jit.moveValue(rightChild-&gt;asJSValue(), rightRegs);
-    }
</del><ins>+        auto done = m_jit.label();
</ins><span class="cx"> 
</span><del>-    callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
</del><ins>+        addSlowPathGenerator([=, savePlans = WTFMove(savePlans)] () {
+            addICGenerationState-&gt;slowPathJumps.link(&amp;m_jit);
+            addICGenerationState-&gt;slowPathStart = m_jit.label();
</ins><span class="cx"> 
</span><del>-    silentFillAllRegisters(resultRegs);
-    m_jit.exceptionCheck();
</del><ins>+            silentSpill(savePlans);
</ins><span class="cx"> 
</span><del>-    gen.endJumpList().link(&amp;m_jit);
</del><ins>+            auto innerLeftRegs = leftRegs;
+            auto innerRightRegs = rightRegs;
+            if (leftOperand.isConst()) {
+                innerLeftRegs = resultRegs;
+                m_jit.moveValue(leftChild-&gt;asJSValue(), innerLeftRegs);
+            } else if (rightOperand.isConst()) {
+                innerRightRegs = resultRegs;
+                m_jit.moveValue(rightChild-&gt;asJSValue(), innerRightRegs);
+            }
+
+            if (addICGenerationState-&gt;shouldSlowPathRepatch)
+                addICGenerationState-&gt;slowPathCall = callOperation(operationValueAddOptimize, resultRegs, innerLeftRegs, innerRightRegs, addIC);
+            else
+                addICGenerationState-&gt;slowPathCall = callOperation(operationValueAdd, resultRegs, innerLeftRegs, innerRightRegs);
+
+            silentFill(savePlans);
+            m_jit.exceptionCheck();
+            m_jit.jump().linkTo(done, &amp;m_jit);
+
+            m_jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                addIC-&gt;finalizeInlineCode(*addICGenerationState, linkBuffer);
+            });
+        });
+    } else {
+        if (leftOperand.isConst()) {
+            left = JSValueOperand(this, leftChild);
+            leftRegs = left-&gt;jsValueRegs();
+        } else if (rightOperand.isConst()) {
+            right = JSValueOperand(this, rightChild);
+            rightRegs = right-&gt;jsValueRegs();
+        }
+
+        flushRegisters();
+        callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
+        m_jit.exceptionCheck();
+    }
+
</ins><span class="cx">     jsValueResult(resultRegs, node);
</span><span class="cx">     return;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -388,13 +388,15 @@
</span><span class="cx">     {
</span><span class="cx">         silentSpillAllRegistersImpl(doSpill, plans, InvalidGPRReg, InvalidGPRReg, exclude);
</span><span class="cx">     }
</span><del>-#if USE(JSVALUE32_64)
</del><span class="cx">     template&lt;typename CollectionType&gt;
</span><span class="cx">     void silentSpillAllRegistersImpl(bool doSpill, CollectionType&amp; plans, JSValueRegs exclude)
</span><span class="cx">     {
</span><ins>+#if USE(JSVALUE32_64)
</ins><span class="cx">         silentSpillAllRegistersImpl(doSpill, plans, exclude.tagGPR(), exclude.payloadGPR());
</span><ins>+#else
+        silentSpillAllRegistersImpl(doSpill, plans, exclude.gpr());
+#endif
</ins><span class="cx">     }
</span><del>-#endif
</del><span class="cx">     
</span><span class="cx">     void silentSpillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg, FPRReg fprExclude = InvalidFPRReg)
</span><span class="cx">     {
</span><span class="lines">@@ -1285,6 +1287,13 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+
+    JITCompiler::Call callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, JITAddIC* addIC)
+    {
+        m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), TrustedImmPtr(addIC));
+        return appendCallSetResult(operation, result.gpr());
+    }
+
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EJJI operation, GPRReg result, GPRReg arg1, GPRReg arg2, UniquedStringImpl* uid)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(uid));
</span><span class="lines">@@ -1702,6 +1711,12 @@
</span><span class="cx">     }
</span><span class="cx"> #else // USE(JSVALUE32_64)
</span><span class="cx"> 
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, JITAddIC* addIC)
+    {
+        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), TrustedImmPtr(addIC));
+        return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
+    }
+
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EJJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, UniquedStringImpl* uid)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2Payload, arg2Tag, TrustedImmPtr(uid));
</span><span class="lines">@@ -2832,9 +2847,14 @@
</span><span class="cx">     MinifiedGraph* m_minifiedGraph;
</span><span class="cx">     
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;SlowPathGenerator&gt;, 8&gt; m_slowPathGenerators;
</span><del>-    Vector&lt;std::pair&lt;std::function&lt;void()&gt;, Node*&gt;, 8&gt; m_slowPathLambdas;
</del><ins>+    struct SlowPathLambda {
+        std::function&lt;void()&gt; generator;
+        Node* currentNode;
+        unsigned streamIndex;
+    };
+    Vector&lt;SlowPathLambda&gt; m_slowPathLambdas;
</ins><span class="cx">     Vector&lt;SilentRegisterSavePlan&gt; m_plans;
</span><del>-    unsigned m_outOfLineStreamIndex { UINT_MAX };
</del><ins>+    Optional&lt;unsigned&gt; m_outOfLineStreamIndex;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -62,6 +62,7 @@
</span><span class="cx"> #include &quot;JITDivGenerator.h&quot;
</span><span class="cx"> #include &quot;JITInlineCacheGenerator.h&quot;
</span><span class="cx"> #include &quot;JITLeftShiftGenerator.h&quot;
</span><ins>+#include &quot;JITMathIC.h&quot;
</ins><span class="cx"> #include &quot;JITMulGenerator.h&quot;
</span><span class="cx"> #include &quot;JITRightShiftGenerator.h&quot;
</span><span class="cx"> #include &quot;JITSubGenerator.h&quot;
</span><span class="lines">@@ -1538,7 +1539,72 @@
</span><span class="cx">     
</span><span class="cx">     void compileValueAdd()
</span><span class="cx">     {
</span><del>-        emitBinarySnippet&lt;JITAddGenerator&gt;(operationValueAdd);
</del><ins>+        Node* node = m_node;
+        
+        LValue left = lowJSValue(node-&gt;child1());
+        LValue right = lowJSValue(node-&gt;child2());
+
+        SnippetOperand leftOperand(m_state.forNode(node-&gt;child1()).resultType());
+        SnippetOperand rightOperand(m_state.forNode(node-&gt;child2()).resultType());
+            
+        PatchpointValue* patchpoint = m_out.patchpoint(Int64);
+        patchpoint-&gt;appendSomeRegister(left);
+        patchpoint-&gt;appendSomeRegister(right);
+        patchpoint-&gt;append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
+        patchpoint-&gt;append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
+        RefPtr&lt;PatchpointExceptionHandle&gt; exceptionHandle =
+            preparePatchpointForExceptions(patchpoint);
+        patchpoint-&gt;numGPScratchRegisters = 1;
+        patchpoint-&gt;numFPScratchRegisters = 2;
+        patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
+        State* state = &amp;m_ftlState;
+        patchpoint-&gt;setGenerator(
+            [=] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp; params) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+
+                Box&lt;CCallHelpers::JumpList&gt; exceptions =
+                    exceptionHandle-&gt;scheduleExitCreation(params)-&gt;jumps(jit);
+
+                JITAddIC* addIC = jit.codeBlock()-&gt;addJITAddIC();
+                Box&lt;MathICGenerationState&gt; addICGenerationState = Box&lt;MathICGenerationState&gt;::create();
+                ArithProfile* arithProfile = state-&gt;graph.baselineCodeBlockFor(node-&gt;origin.semantic)-&gt;arithProfileForBytecodeOffset(node-&gt;origin.semantic.bytecodeIndex);
+                addIC-&gt;m_generator = JITAddGenerator(leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
+                    JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()), params.fpScratch(0),
+                    params.fpScratch(1), params.gpScratch(0), InvalidFPRReg, arithProfile);
+
+                bool generatedInline = addIC-&gt;generateInline(jit, *addICGenerationState);
+
+                if (generatedInline) {
+                    ASSERT(!addICGenerationState-&gt;slowPathJumps.empty());
+                    auto done = jit.label();
+                    params.addLatePath([=] (CCallHelpers&amp; jit) {
+                        AllowMacroScratchRegisterUsage allowScratch(jit);
+                        addICGenerationState-&gt;slowPathJumps.link(&amp;jit);
+                        addICGenerationState-&gt;slowPathStart = jit.label();
+
+                        if (addICGenerationState-&gt;shouldSlowPathRepatch) {
+                            SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node-&gt;origin.semantic, exceptions.get(),
+                                operationValueAddOptimize, params[0].gpr(), params[1].gpr(), params[2].gpr(), CCallHelpers::TrustedImmPtr(addIC));
+                            addICGenerationState-&gt;slowPathCall = call.call();
+                        } else {
+                            SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node-&gt;origin.semantic,
+                                exceptions.get(), operationValueAdd, params[0].gpr(), params[1].gpr(), params[2].gpr());
+                            addICGenerationState-&gt;slowPathCall = call.call();
+                        }
+                        jit.jump().linkTo(done, &amp;jit);
+
+                        jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                            addIC-&gt;finalizeInlineCode(*addICGenerationState, linkBuffer);
+                        });
+                    });
+                } else {
+                    callOperation(
+                        *state, params.unavailableRegisters(), jit, node-&gt;origin.semantic, exceptions.get(),
+                        operationValueAdd, params[0].gpr(), params[1].gpr(), params[2].gpr());
+                }
+            });
+
+        setJSValue(patchpoint);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileStrCat()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -826,6 +826,18 @@
</span><span class="cx">         addCallArgument(arg6);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5, TrustedImmPtr arg6)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+        addCallArgument(arg5);
+        addCallArgument(arg6);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, GPRReg arg6, TrustedImmPtr arg7)
</span><span class="cx">     {
</span><span class="cx">         resetCallArguments();
</span><span class="lines">@@ -1594,6 +1606,14 @@
</span><span class="cx">         setupArgumentsWithExecState(arg1, arg2, arg3);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5, TrustedImmPtr arg6)
+    {
+        poke(arg6, POKE_ARGUMENT_OFFSET + 2);
+        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
+        poke(arg4, POKE_ARGUMENT_OFFSET);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5)
</span><span class="cx">     {
</span><span class="cx">         poke(arg5, POKE_ARGUMENT_OFFSET + 1);
</span><span class="lines">@@ -2099,6 +2119,14 @@
</span><span class="cx">         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImmPtr arg4)
+    {
+        setupTwoStubArgsGPR&lt;GPRInfo::argumentGPR1, GPRInfo::argumentGPR2&gt;(arg1, arg2);
+        move(arg3, GPRInfo::argumentGPR3);
+        move(arg4, GPRInfo::argumentGPR4);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
</span><span class="cx">     {
</span><span class="cx">         setupThreeStubArgsGPR&lt;GPRInfo::argumentGPR1, GPRInfo::argumentGPR4, GPRInfo::argumentGPR5&gt;(arg1, arg4, arg5);
</span><span class="lines">@@ -2207,6 +2235,15 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     
</span><ins>+    void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2)
+    {
+#if USE(JSVALUE64)
+        setupArgumentsWithExecState(arg1.gpr(), arg2.gpr());
+#else
+        setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR());
+#endif
+    }
+
</ins><span class="cx">     void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3)
</span><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="lines">@@ -2215,6 +2252,15 @@
</span><span class="cx">         setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3);
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><ins>+
+    void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3, TrustedImmPtr arg4)
+    {
+#if USE(JSVALUE64)
+        setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), arg3, arg4);
+#else
+        setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3, arg4);
+#endif
+    }
</ins><span class="cx">     
</span><span class="cx">     void setupArguments(JSValueRegs arg1)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -43,10 +43,10 @@
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JITDisassembler.h&quot;
</span><span class="cx"> #include &quot;JITInlineCacheGenerator.h&quot;
</span><ins>+#include &quot;JITMathIC.h&quot;
</ins><span class="cx"> #include &quot;JSInterfaceJIT.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;PCToCodeOriginMap.h&quot;
</span><del>-#include &quot;ResultType.h&quot;
</del><span class="cx"> #include &quot;UnusedPointer.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -435,7 +435,6 @@
</span><span class="cx">         void compileGetByIdHotPath(const Identifier*);
</span><span class="cx"> 
</span><span class="cx">         // Arithmetic opcode helpers
</span><del>-        void emitSub32Constant(int dst, int op, int32_t constant, ResultType opType);
</del><span class="cx">         void emitBinaryDoubleOp(OpcodeID, int dst, int op1, int op2, OperandTypes, JumpList&amp; notInt32Op1, JumpList&amp; notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
</span><span class="cx"> 
</span><span class="cx"> #else // USE(JSVALUE32_64)
</span><span class="lines">@@ -764,7 +763,10 @@
</span><span class="cx"> #endif
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJI, int, GPRReg, UniquedStringImpl*);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg);
</span><del>-        MacroAssembler::Call callOperation(J_JITOperation_EJJRp, JSValueRegs, JSValueRegs, JSValueRegs, ResultProfile*);
</del><ins>+        MacroAssembler::Call callOperation(J_JITOperation_EJJArp, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*);
+        MacroAssembler::Call callOperation(J_JITOperation_EJJ, JSValueRegs, JSValueRegs, JSValueRegs);
+        MacroAssembler::Call callOperation(J_JITOperation_EJJArpJaic, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*, JITAddIC*);
+        MacroAssembler::Call callOperation(J_JITOperation_EJJJaic, JSValueRegs, JSValueRegs, JSValueRegs, JITAddIC*);
</ins><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*);
</span><span class="cx">         MacroAssembler::Call callOperation(Z_JITOperation_EJOJ, GPRReg, GPRReg, GPRReg);
</span><span class="lines">@@ -954,6 +956,9 @@
</span><span class="cx"> 
</span><span class="cx">         PCToCodeOriginMapBuilder m_pcToCodeOriginMapBuilder;
</span><span class="cx"> 
</span><ins>+        HashMap&lt;Instruction*, JITAddIC*&gt; m_instructionToJITAddIC;
+        HashMap&lt;Instruction*, MathICGenerationState&gt; m_instructionToJITAddICGenerationState;
+
</ins><span class="cx">         bool m_canBeOptimized;
</span><span class="cx">         bool m_canBeOptimizedOrInlined;
</span><span class="cx">         bool m_shouldEmitProfiling;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITAddGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -26,12 +26,53 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;JITAddGenerator.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
+#include &quot;JITMathIC.h&quot;
+#include &quot;LinkBuffer.h&quot;
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-void JITAddGenerator::generateFastPath(CCallHelpers&amp; jit)
</del><ins>+JITMathICInlineResult JITAddGenerator::generateInline(CCallHelpers&amp; jit, MathICGenerationState&amp; state)
</ins><span class="cx"> {
</span><ins>+    // We default to speculating int32.
+    ObservedType lhs = ObservedType().withInt32();
+    ObservedType rhs = ObservedType().withInt32();
+    if (m_arithProfile) {
+        lhs = m_arithProfile-&gt;lhsObservedType();
+        rhs = m_arithProfile-&gt;rhsObservedType();
+        if (lhs.isEmpty() || rhs.isEmpty()) {
+            lhs = ObservedType().withInt32();
+            rhs = ObservedType().withInt32();
+        }
+    }
+
+    if (lhs.isOnlyNonNumber() &amp;&amp; rhs.isOnlyNonNumber())
+        return JITMathICInlineResult::DontGenerate;
+
+    if ((lhs.isOnlyInt32() || m_leftOperand.isConstInt32()) &amp;&amp; (rhs.isOnlyInt32() || m_rightOperand.isConstInt32())) {
+        ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
+        if (!m_leftOperand.isConstInt32())
+            state.slowPathJumps.append(jit.branchIfNotInt32(m_left));
+        if (!m_rightOperand.isConstInt32())
+            state.slowPathJumps.append(jit.branchIfNotInt32(m_right));
+
+        if (m_leftOperand.isConstInt32() || m_rightOperand.isConstInt32()) {
+            JSValueRegs var = m_leftOperand.isConstInt32() ? m_right : m_left;
+            int32_t constValue = m_leftOperand.isConstInt32() ? m_leftOperand.asConstInt32() : m_rightOperand.asConstInt32();
+            state.slowPathJumps.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constValue), m_scratchGPR));
+        } else
+            state.slowPathJumps.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
+        jit.boxInt32(m_scratchGPR, m_result);
+        return JITMathICInlineResult::GeneratedFastPath;
+    }
+
+    return JITMathICInlineResult::GenerateFullSnippet;
+}
+
+bool JITAddGenerator::generateFastPath(CCallHelpers&amp; jit, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList)
+{
</ins><span class="cx">     ASSERT(m_scratchGPR != InvalidGPRReg);
</span><span class="cx">     ASSERT(m_scratchGPR != m_left.payloadGPR());
</span><span class="cx">     ASSERT(m_scratchGPR != m_right.payloadGPR());
</span><span class="lines">@@ -43,13 +84,9 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
</span><span class="cx">     
</span><del>-    if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber()) {
-        ASSERT(!m_didEmitFastPath);
-        return;
-    }
</del><ins>+    if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber())
+        return false;
</ins><span class="cx"> 
</span><del>-    m_didEmitFastPath = true;
-
</del><span class="cx">     if (m_leftOperand.isConstInt32() || m_rightOperand.isConstInt32()) {
</span><span class="cx">         JSValueRegs var = m_leftOperand.isConstInt32() ? m_right : m_left;
</span><span class="cx">         SnippetOperand&amp; varOpr = m_leftOperand.isConstInt32() ? m_rightOperand : m_leftOperand;
</span><span class="lines">@@ -58,20 +95,20 @@
</span><span class="cx">         // Try to do intVar + intConstant.
</span><span class="cx">         CCallHelpers::Jump notInt32 = jit.branchIfNotInt32(var);
</span><span class="cx"> 
</span><del>-        m_slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), m_scratchGPR));
</del><ins>+        slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.boxInt32(m_scratchGPR, m_result);
</span><del>-        m_endJumpList.append(jit.jump());
</del><ins>+        endJumpList.append(jit.jump());
</ins><span class="cx"> 
</span><span class="cx">         if (!jit.supportsFloatingPoint()) {
</span><del>-            m_slowPathJumpList.append(notInt32);
-            return;
</del><ins>+            slowPathJumpList.append(notInt32);
+            return true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Try to do doubleVar + double(intConstant).
</span><span class="cx">         notInt32.link(&amp;jit);
</span><span class="cx">         if (!varOpr.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.unboxDoubleNonDestructive(var, m_leftFPR, m_scratchGPR, m_scratchFPR);
</span><span class="cx"> 
</span><span class="lines">@@ -89,22 +126,23 @@
</span><span class="cx">         leftNotInt = jit.branchIfNotInt32(m_left);
</span><span class="cx">         rightNotInt = jit.branchIfNotInt32(m_right);
</span><span class="cx"> 
</span><del>-        m_slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
</del><ins>+        slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.boxInt32(m_scratchGPR, m_result);
</span><del>-        m_endJumpList.append(jit.jump());
</del><ins>+        endJumpList.append(jit.jump());
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">         if (!jit.supportsFloatingPoint()) {
</span><del>-            m_slowPathJumpList.append(leftNotInt);
-            m_slowPathJumpList.append(rightNotInt);
-            return;
</del><ins>+            slowPathJumpList.append(leftNotInt);
+            slowPathJumpList.append(rightNotInt);
+            return true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         leftNotInt.link(&amp;jit);
</span><span class="cx">         if (!m_leftOperand.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
</ins><span class="cx">         if (!m_rightOperand.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.unboxDoubleNonDestructive(m_left, m_leftFPR, m_scratchGPR, m_scratchFPR);
</span><span class="cx">         CCallHelpers::Jump rightIsDouble = jit.branchIfNotInt32(m_right);
</span><span class="lines">@@ -114,7 +152,7 @@
</span><span class="cx"> 
</span><span class="cx">         rightNotInt.link(&amp;jit);
</span><span class="cx">         if (!m_rightOperand.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.convertInt32ToDouble(m_left.payloadGPR(), m_leftFPR);
</span><span class="cx"> 
</span><span class="lines">@@ -128,10 +166,12 @@
</span><span class="cx"> 
</span><span class="cx">     // Do doubleVar + doubleVar.
</span><span class="cx">     jit.addDouble(m_rightFPR, m_leftFPR);
</span><del>-    if (m_resultProfile)
-        m_resultProfile-&gt;emitSetDouble(jit);
</del><ins>+    if (m_arithProfile)
+        m_arithProfile-&gt;emitSetDouble(jit);
</ins><span class="cx">         
</span><span class="cx">     jit.boxDouble(m_leftFPR, m_result);
</span><ins>+
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITAddGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITAddGenerator.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITAddGenerator.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITAddGenerator.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -29,16 +29,23 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><ins>+#include &quot;JITMathICInlineResult.h&quot;
+#include &quot;JITOperations.h&quot;
</ins><span class="cx"> #include &quot;SnippetOperand.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+struct MathICGenerationState;
+
</ins><span class="cx"> class JITAddGenerator {
</span><span class="cx"> public:
</span><ins>+    JITAddGenerator()
+    { }
+
</ins><span class="cx">     JITAddGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
</span><span class="cx">         JSValueRegs result, JSValueRegs left, JSValueRegs right,
</span><span class="cx">         FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
</span><del>-        ResultProfile* resultProfile = nullptr)
</del><ins>+        ArithProfile* arithProfile = nullptr)
</ins><span class="cx">         : m_leftOperand(leftOperand)
</span><span class="cx">         , m_rightOperand(rightOperand)
</span><span class="cx">         , m_result(result)
</span><span class="lines">@@ -48,17 +55,14 @@
</span><span class="cx">         , m_rightFPR(rightFPR)
</span><span class="cx">         , m_scratchGPR(scratchGPR)
</span><span class="cx">         , m_scratchFPR(scratchFPR)
</span><del>-        , m_resultProfile(resultProfile)
</del><ins>+        , m_arithProfile(arithProfile)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void generateFastPath(CCallHelpers&amp;);
</del><ins>+    JITMathICInlineResult generateInline(CCallHelpers&amp;, MathICGenerationState&amp;);
+    bool generateFastPath(CCallHelpers&amp;, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList);
</ins><span class="cx"> 
</span><del>-    bool didEmitFastPath() const { return m_didEmitFastPath; }
-    CCallHelpers::JumpList&amp; endJumpList() { return m_endJumpList; }
-    CCallHelpers::JumpList&amp; slowPathJumpList() { return m_slowPathJumpList; }
-
</del><span class="cx"> private:
</span><span class="cx">     SnippetOperand m_leftOperand;
</span><span class="cx">     SnippetOperand m_rightOperand;
</span><span class="lines">@@ -69,11 +73,7 @@
</span><span class="cx">     FPRReg m_rightFPR;
</span><span class="cx">     GPRReg m_scratchGPR;
</span><span class="cx">     FPRReg m_scratchFPR;
</span><del>-    ResultProfile* m_resultProfile;
-    bool m_didEmitFastPath { false };
-
-    CCallHelpers::JumpList m_endJumpList;
-    CCallHelpers::JumpList m_slowPathJumpList;
</del><ins>+    ArithProfile* m_arithProfile;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITArithmeticcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> #include &quot;JIT.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;JITAddGenerator.h&quot;
</span><span class="cx"> #include &quot;JITBitAndGenerator.h&quot;
</span><span class="lines">@@ -36,6 +37,7 @@
</span><span class="cx"> #include &quot;JITDivGenerator.h&quot;
</span><span class="cx"> #include &quot;JITInlines.h&quot;
</span><span class="cx"> #include &quot;JITLeftShiftGenerator.h&quot;
</span><ins>+#include &quot;JITMathIC.h&quot;
</ins><span class="cx"> #include &quot;JITMulGenerator.h&quot;
</span><span class="cx"> #include &quot;JITNegGenerator.h&quot;
</span><span class="cx"> #include &quot;JITOperations.h&quot;
</span><span class="lines">@@ -45,10 +47,10 @@
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;LinkBuffer.h&quot;
</ins><span class="cx"> #include &quot;ResultType.h&quot;
</span><span class="cx"> #include &quot;SlowPathCall.h&quot;
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_jless(Instruction* currentInstruction)
</span><span class="lines">@@ -675,14 +677,19 @@
</span><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE static OperandTypes getOperandTypes(Instruction* instruction)
+{
+    return OperandTypes(ArithProfile::fromInt(instruction[4].u.operand).lhsResultType(), ArithProfile::fromInt(instruction[4].u.operand).rhsResultType());
+}
+
</ins><span class="cx"> void JIT::emit_op_add(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><del>-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</del><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -689,6 +696,7 @@
</span><span class="cx">     GPRReg scratchGPR = regT2;
</span><span class="cx">     FPRReg scratchFPR = InvalidFPRReg;
</span><span class="cx"> #else
</span><ins>+    OperandTypes types = getOperandTypes(currentInstruction);
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -696,9 +704,9 @@
</span><span class="cx">     FPRReg scratchFPR = fpRegT2;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    ResultProfile* resultProfile = nullptr;
</del><ins>+    ArithProfile* arithProfile = nullptr;
</ins><span class="cx">     if (shouldEmitProfiling())
</span><del>-        resultProfile = m_codeBlock-&gt;ensureResultProfile(m_bytecodeOffset);
</del><ins>+        arithProfile = &amp;m_codeBlock-&gt;arithProfileForPC(currentInstruction);
</ins><span class="cx"> 
</span><span class="cx">     SnippetOperand leftOperand(types.first());
</span><span class="cx">     SnippetOperand rightOperand(types.second());
</span><span class="lines">@@ -715,31 +723,27 @@
</span><span class="cx">     if (!rightOperand.isConst())
</span><span class="cx">         emitGetVirtualRegister(op2, rightRegs);
</span><span class="cx"> 
</span><del>-    JITAddGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
-        fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
</del><ins>+    JITAddIC* addIC = m_codeBlock-&gt;addJITAddIC();
</ins><span class="cx"> 
</span><del>-    gen.generateFastPath(*this);
</del><ins>+    m_instructionToJITAddIC.add(currentInstruction, addIC);
+    MathICGenerationState&amp; addICGenerationState = m_instructionToJITAddICGenerationState.add(currentInstruction, MathICGenerationState()).iterator-&gt;value;
</ins><span class="cx"> 
</span><del>-    if (gen.didEmitFastPath()) {
-        gen.endJumpList().link(this);
-        emitPutVirtualRegister(result, resultRegs);
-        
-        addSlowCase(gen.slowPathJumpList());
-    } else {
-        ASSERT(gen.endJumpList().empty());
-        ASSERT(gen.slowPathJumpList().empty());
-        if (resultProfile) {
-            if (leftOperand.isConst())
-                emitGetVirtualRegister(op1, leftRegs);
-            if (rightOperand.isConst())
-                emitGetVirtualRegister(op2, rightRegs);
-            callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
-            emitPutVirtualRegister(result, resultRegs);
-        } else {
-            JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add);
-            slowPathCall.call();
-        }
-    }
</del><ins>+    addIC-&gt;m_generator = JITAddGenerator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
+
+    bool generatedInlineCode = addIC-&gt;generateInline(*this, addICGenerationState);
+    if (!generatedInlineCode) {
+        if (leftOperand.isConst())
+            emitGetVirtualRegister(op1, leftRegs);
+        else if (rightOperand.isConst())
+            emitGetVirtualRegister(op2, rightRegs);
+
+        if (arithProfile)
+            callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, arithProfile);
+        else
+            callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
+    } else
+        addSlowCase(addICGenerationState.slowPathJumps);
+    emitPutVirtualRegister(result, resultRegs);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="lines">@@ -746,16 +750,20 @@
</span><span class="cx"> {
</span><span class="cx">     linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
</span><span class="cx"> 
</span><ins>+    MathICGenerationState&amp; addICGenerationState = m_instructionToJITAddICGenerationState.find(currentInstruction)-&gt;value;
+    addICGenerationState.slowPathStart = label();
+
</ins><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><del>-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</del><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="cx"> #else
</span><ins>+    OperandTypes types = getOperandTypes(currentInstruction);
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -769,18 +777,26 @@
</span><span class="cx">     else if (isOperandConstantInt(op2))
</span><span class="cx">         rightOperand.setConstInt32(getOperandConstantInt(op2));
</span><span class="cx"> 
</span><ins>+    if (leftOperand.isConst())
+        emitGetVirtualRegister(op1, leftRegs);
+    if (rightOperand.isConst())
+        emitGetVirtualRegister(op2, rightRegs);
+
+    JITAddIC* addIC = m_instructionToJITAddIC.get(currentInstruction);
</ins><span class="cx">     if (shouldEmitProfiling()) {
</span><del>-        if (leftOperand.isConst())
-            emitGetVirtualRegister(op1, leftRegs);
-        if (rightOperand.isConst())
-            emitGetVirtualRegister(op2, rightRegs);
-        ResultProfile* resultProfile = m_codeBlock-&gt;ensureResultProfile(m_bytecodeOffset);
-        callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
-        emitPutVirtualRegister(result, resultRegs);
-    } else {
-        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add);
-        slowPathCall.call();
-    }
</del><ins>+        ArithProfile&amp; arithProfile = m_codeBlock-&gt;arithProfileForPC(currentInstruction);
+        if (addICGenerationState.shouldSlowPathRepatch)
+            addICGenerationState.slowPathCall = callOperation(operationValueAddProfiledOptimize, resultRegs, leftRegs, rightRegs, &amp;arithProfile, addIC);
+        else
+            addICGenerationState.slowPathCall = callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, &amp;arithProfile);
+    } else
+        addICGenerationState.slowPathCall = callOperation(operationValueAddOptimize, resultRegs, leftRegs, rightRegs, addIC);
+    emitPutVirtualRegister(result, resultRegs);
+
+    addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+        MathICGenerationState&amp; addICGenerationState = m_instructionToJITAddICGenerationState.find(currentInstruction)-&gt;value;
+        addIC-&gt;finalizeInlineCode(addICGenerationState, linkBuffer);
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_div(Instruction* currentInstruction)
</span><span class="lines">@@ -788,14 +804,15 @@
</span><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><del>-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</del><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="cx">     GPRReg scratchGPR = regT2;
</span><span class="cx"> #else
</span><ins>+    OperandTypes types = getOperandTypes(currentInstruction);
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -803,9 +820,9 @@
</span><span class="cx"> #endif
</span><span class="cx">     FPRReg scratchFPR = fpRegT2;
</span><span class="cx"> 
</span><del>-    ResultProfile* resultProfile = nullptr;
</del><ins>+    ArithProfile* arithProfile = nullptr;
</ins><span class="cx">     if (shouldEmitProfiling())
</span><del>-        resultProfile = m_codeBlock-&gt;ensureResultProfile(m_bytecodeOffset);
</del><ins>+        arithProfile = &amp;m_codeBlock-&gt;arithProfileForPC(currentInstruction);
</ins><span class="cx"> 
</span><span class="cx">     SnippetOperand leftOperand(types.first());
</span><span class="cx">     SnippetOperand rightOperand(types.second());
</span><span class="lines">@@ -831,7 +848,7 @@
</span><span class="cx">         emitGetVirtualRegister(op2, rightRegs);
</span><span class="cx"> 
</span><span class="cx">     JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
</span><del>-        fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
</del><ins>+        fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
</ins><span class="cx"> 
</span><span class="cx">     gen.generateFastPath(*this);
</span><span class="cx"> 
</span><span class="lines">@@ -861,9 +878,9 @@
</span><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><del>-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</del><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><span class="cx">     JSValueRegs resultRegs = JSValueRegs(regT2);
</span><span class="lines">@@ -870,6 +887,7 @@
</span><span class="cx">     GPRReg scratchGPR = regT3;
</span><span class="cx">     FPRReg scratchFPR = InvalidFPRReg;
</span><span class="cx"> #else
</span><ins>+    OperandTypes types = getOperandTypes(currentInstruction);
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -877,9 +895,9 @@
</span><span class="cx">     FPRReg scratchFPR = fpRegT2;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    ResultProfile* resultProfile = nullptr;
</del><ins>+    ArithProfile* arithProfile = nullptr;
</ins><span class="cx">     if (shouldEmitProfiling())
</span><del>-        resultProfile = m_codeBlock-&gt;ensureResultProfile(m_bytecodeOffset);
</del><ins>+        arithProfile = &amp;m_codeBlock-&gt;arithProfileForPC(currentInstruction);
</ins><span class="cx"> 
</span><span class="cx">     SnippetOperand leftOperand(types.first());
</span><span class="cx">     SnippetOperand rightOperand(types.second());
</span><span class="lines">@@ -897,7 +915,7 @@
</span><span class="cx">         emitGetVirtualRegister(op2, rightRegs);
</span><span class="cx"> 
</span><span class="cx">     JITMulGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
</span><del>-        fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
</del><ins>+        fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
</ins><span class="cx"> 
</span><span class="cx">     gen.generateFastPath(*this);
</span><span class="cx"> 
</span><span class="lines">@@ -909,12 +927,12 @@
</span><span class="cx">     } else {
</span><span class="cx">         ASSERT(gen.endJumpList().empty());
</span><span class="cx">         ASSERT(gen.slowPathJumpList().empty());
</span><del>-        if (resultProfile) {
</del><ins>+        if (arithProfile) {
</ins><span class="cx">             if (leftOperand.isPositiveConstInt32())
</span><span class="cx">                 emitGetVirtualRegister(op1, leftRegs);
</span><span class="cx">             if (rightOperand.isPositiveConstInt32())
</span><span class="cx">                 emitGetVirtualRegister(op2, rightRegs);
</span><del>-            callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
</del><ins>+            callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, arithProfile);
</ins><span class="cx">             emitPutVirtualRegister(result, resultRegs);
</span><span class="cx">         } else {
</span><span class="cx">             JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
</span><span class="lines">@@ -930,13 +948,14 @@
</span><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><del>-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</del><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="cx"> #else
</span><ins>+    OperandTypes types = getOperandTypes(currentInstruction);
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -955,8 +974,8 @@
</span><span class="cx">             emitGetVirtualRegister(op1, leftRegs);
</span><span class="cx">         if (rightOperand.isPositiveConstInt32())
</span><span class="cx">             emitGetVirtualRegister(op2, rightRegs);
</span><del>-        ResultProfile* resultProfile = m_codeBlock-&gt;ensureResultProfile(m_bytecodeOffset);
-        callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
</del><ins>+        ArithProfile&amp; arithProfile = m_codeBlock-&gt;arithProfileForPC(currentInstruction);
+        callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, &amp;arithProfile);
</ins><span class="cx">         emitPutVirtualRegister(result, resultRegs);
</span><span class="cx">     } else {
</span><span class="cx">         JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
</span><span class="lines">@@ -969,9 +988,9 @@
</span><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><del>-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</del><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -978,6 +997,7 @@
</span><span class="cx">     GPRReg scratchGPR = regT2;
</span><span class="cx">     FPRReg scratchFPR = InvalidFPRReg;
</span><span class="cx"> #else
</span><ins>+    OperandTypes types = getOperandTypes(currentInstruction);
</ins><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
</span><span class="cx">     JSValueRegs resultRegs = leftRegs;
</span><span class="lines">@@ -985,9 +1005,9 @@
</span><span class="cx">     FPRReg scratchFPR = fpRegT2;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    ResultProfile* resultProfile = nullptr;
</del><ins>+    ArithProfile* arithProfile = nullptr;
</ins><span class="cx">     if (shouldEmitProfiling())
</span><del>-        resultProfile = m_codeBlock-&gt;ensureResultProfile(m_bytecodeOffset);
</del><ins>+        arithProfile = &amp;m_codeBlock-&gt;arithProfileForPC(currentInstruction);
</ins><span class="cx"> 
</span><span class="cx">     SnippetOperand leftOperand(types.first());
</span><span class="cx">     SnippetOperand rightOperand(types.second());
</span><span class="lines">@@ -996,7 +1016,7 @@
</span><span class="cx">     emitGetVirtualRegister(op2, rightRegs);
</span><span class="cx"> 
</span><span class="cx">     JITSubGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
</span><del>-        fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
</del><ins>+        fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
</ins><span class="cx"> 
</span><span class="cx">     gen.generateFastPath(*this);
</span><span class="cx"> 
</span><span class="lines">@@ -1023,8 +1043,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     if (shouldEmitProfiling()) {
</span><del>-        ResultProfile* resultProfile = m_codeBlock-&gt;ensureResultProfile(m_bytecodeOffset);
-        callOperation(operationValueSubProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
</del><ins>+        ArithProfile&amp; arithProfile = m_codeBlock-&gt;arithProfileForPC(currentInstruction);
+        callOperation(operationValueSubProfiled, resultRegs, leftRegs, rightRegs, &amp;arithProfile);
</ins><span class="cx">         emitPutVirtualRegister(result, resultRegs);
</span><span class="cx">     } else {
</span><span class="cx">         JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITDivGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITDivGenerator.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITDivGenerator.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITDivGenerator.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValueInlines.h&quot;
</span><span class="cx"> #include &quot;MathCommon.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -101,9 +102,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Is the result actually an integer? The DFG JIT would really like to know. If it's
</span><del>-    // not an integer, we increment a count. If this together with the slow case counter
-    // are below threshold then the DFG JIT will compile this division with a speculation
-    // that the remainder is zero.
</del><ins>+    // not an integer, we set a bit. If this together with the slow case counter are below
+    // threshold then the DFG JIT will compile this division with a speculation that the
+    // remainder is zero.
</ins><span class="cx"> 
</span><span class="cx">     // As well, there are cases where a double result here would cause an important field
</span><span class="cx">     // in the heap to sometimes have doubles in it, resulting in double predictions getting
</span><span class="lines">@@ -128,8 +129,8 @@
</span><span class="cx"> 
</span><span class="cx">     notDoubleZero.link(&amp;jit);
</span><span class="cx"> #endif
</span><del>-    if (m_resultProfile)
-        jit.add32(CCallHelpers::TrustedImm32(1), CCallHelpers::AbsoluteAddress(m_resultProfile-&gt;addressOfSpecialFastPathCount()));
</del><ins>+    if (m_arithProfile)
+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::specialFastPathBit), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</ins><span class="cx">     jit.boxDouble(m_leftFPR, m_result);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITDivGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITDivGenerator.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITDivGenerator.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITDivGenerator.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     JITDivGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
</span><span class="cx">         JSValueRegs result, JSValueRegs left, JSValueRegs right,
</span><span class="cx">         FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
</span><del>-        ResultProfile* resultProfile = nullptr)
</del><ins>+        ArithProfile* arithProfile = nullptr)
</ins><span class="cx">         : m_leftOperand(leftOperand)
</span><span class="cx">         , m_rightOperand(rightOperand)
</span><span class="cx">         , m_result(result)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx">         , m_rightFPR(rightFPR)
</span><span class="cx">         , m_scratchGPR(scratchGPR)
</span><span class="cx">         , m_scratchFPR(scratchFPR)
</span><del>-        , m_resultProfile(resultProfile)
</del><ins>+        , m_arithProfile(arithProfile)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
</span><span class="cx">     }
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">     FPRReg m_rightFPR;
</span><span class="cx">     GPRReg m_scratchGPR;
</span><span class="cx">     FPRReg m_scratchFPR;
</span><del>-    ResultProfile* m_resultProfile;
</del><ins>+    ArithProfile* m_arithProfile;
</ins><span class="cx">     bool m_didEmitFastPath { false };
</span><span class="cx"> 
</span><span class="cx">     CCallHelpers::JumpList m_endJumpList;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -416,14 +416,38 @@
</span><span class="cx">     return appendCallWithExceptionCheck(operation);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJRp operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ResultProfile* resultProfile)
</del><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2)
</ins><span class="cx"> {
</span><del>-    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(resultProfile));
</del><ins>+    setupArgumentsWithExecState(arg1, arg2);
</ins><span class="cx">     Call call = appendCallWithExceptionCheck(operation);
</span><span class="cx">     setupResults(result);
</span><span class="cx">     return call;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJArp operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ArithProfile* arithProfile)
+{
+    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arithProfile));
+    Call call = appendCallWithExceptionCheck(operation);
+    setupResults(result);
+    return call;
+}
+
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJArpJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ArithProfile* arithProfile, JITAddIC* addIC)
+{
+    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arithProfile), TrustedImmPtr(addIC));
+    Call call = appendCallWithExceptionCheck(operation);
+    setupResults(result);
+    return call;
+}
+
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, JITAddIC* addIC)
+{
+    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(addIC));
+    Call call = appendCallWithExceptionCheck(operation);
+    setupResults(result);
+    return call;
+}
+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMathICh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/jit/JITMathIC.h (0 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMathIC.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/JITMathIC.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -0,0 +1,163 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(JIT)
+
+#include &quot;CCallHelpers.h&quot;
+#include &quot;JITAddGenerator.h&quot;
+#include &quot;JITMathICInlineResult.h&quot;
+#include &quot;LinkBuffer.h&quot;
+#include &quot;Repatch.h&quot;
+#include &quot;SnippetOperand.h&quot;
+
+namespace JSC {
+
+class LinkBuffer;
+
+struct MathICGenerationState {
+    MacroAssembler::Label fastPathStart;
+    MacroAssembler::Label fastPathEnd;
+    MacroAssembler::Label slowPathStart;
+    MacroAssembler::Call slowPathCall;
+    MacroAssembler::JumpList slowPathJumps;
+    bool shouldSlowPathRepatch;
+};
+
+template &lt;typename GeneratorType&gt;
+class JITMathIC {
+public:
+    CodeLocationLabel doneLocation() { return m_inlineStart.labelAtOffset(m_inlineSize); }
+    CodeLocationLabel slowPathStartLocation() { return m_inlineStart.labelAtOffset(m_deltaFromStartToSlowPathStart); }
+    CodeLocationCall slowPathCallLocation() { return m_inlineStart.callAtOffset(m_deltaFromStartToSlowPathCallLocation); }
+
+    bool generateInline(CCallHelpers&amp; jit, MathICGenerationState&amp; state)
+    {
+        state.fastPathStart = jit.label();
+        size_t startSize = jit.m_assembler.buffer().codeSize();
+        JITMathICInlineResult result = m_generator.generateInline(jit, state);
+
+        switch (result) {
+        case JITMathICInlineResult::GeneratedFastPath: {
+            size_t inlineSize = jit.m_assembler.buffer().codeSize() - startSize;
+            if (static_cast&lt;ptrdiff_t&gt;(inlineSize) &lt; MacroAssembler::maxJumpReplacementSize()) {
+                size_t nopsToEmitInBytes = MacroAssembler::maxJumpReplacementSize() - inlineSize;
+                jit.emitNops(nopsToEmitInBytes);
+            }
+            state.shouldSlowPathRepatch = true;
+            state.fastPathEnd = jit.label();
+            return true;
+        }
+        case JITMathICInlineResult::GenerateFullSnippet: {
+            MacroAssembler::JumpList endJumpList;
+            bool result = m_generator.generateFastPath(jit, endJumpList, state.slowPathJumps);
+            if (result) {
+                state.fastPathEnd = jit.label();
+                state.shouldSlowPathRepatch = false;
+                endJumpList.link(&amp;jit);
+                return true;
+            }
+            return false;
+        }
+        case JITMathICInlineResult::DontGenerate: {
+            return false;
+        }
+        default:
+            ASSERT_NOT_REACHED();
+        }
+
+        return false;
+    }
+
+    void generateOutOfLine(VM&amp; vm, CodeBlock* codeBlock, FunctionPtr callReplacement)
+    {
+        // We rewire to the alternate regardless of whether or not we can allocate the out of line path
+        // because if we fail allocating the out of line path, we don't want to waste time trying to
+        // allocate it in the future.
+        ftlThunkAwareRepatchCall(codeBlock, slowPathCallLocation(), callReplacement);
+
+        {
+            CCallHelpers jit(&amp;vm, codeBlock);
+
+            MacroAssembler::JumpList endJumpList; 
+            MacroAssembler::JumpList slowPathJumpList; 
+            bool emittedFastPath = m_generator.generateFastPath(jit, endJumpList, slowPathJumpList);
+            if (!emittedFastPath)
+                return;
+            endJumpList.append(jit.jump());
+
+            LinkBuffer linkBuffer(vm, jit, codeBlock, JITCompilationCanFail);
+            if (linkBuffer.didFailToAllocate())
+                return;
+
+            linkBuffer.link(endJumpList, doneLocation());
+            linkBuffer.link(slowPathJumpList, slowPathStartLocation());
+
+            m_code = FINALIZE_CODE_FOR(
+                codeBlock, linkBuffer, (&quot;JITMathIC: generating out of line IC snippet&quot;));
+        }
+
+        {
+            CCallHelpers jit(&amp;vm, codeBlock);
+            auto jump = jit.jump();
+            // We don't need a nop sled here because nobody should be jumping into the middle of an IC.
+            bool needsBranchCompaction = false;
+            RELEASE_ASSERT(jit.m_assembler.buffer().codeSize() &lt;= static_cast&lt;size_t&gt;(m_inlineSize));
+            LinkBuffer linkBuffer(jit, m_inlineStart.dataLocation(), jit.m_assembler.buffer().codeSize(), JITCompilationMustSucceed, needsBranchCompaction);
+            RELEASE_ASSERT(linkBuffer.isValid());
+            linkBuffer.link(jump, CodeLocationLabel(m_code.code().executableAddress()));
+            FINALIZE_CODE(linkBuffer, (&quot;JITMathIC: linking constant jump to out of line stub&quot;));
+        }
+    }
+
+    void finalizeInlineCode(const MathICGenerationState&amp; state, LinkBuffer&amp; linkBuffer)
+    {
+        CodeLocationLabel start = linkBuffer.locationOf(state.fastPathStart);
+        m_inlineStart = start;
+
+        m_inlineSize = MacroAssembler::differenceBetweenCodePtr(
+            start, linkBuffer.locationOf(state.fastPathEnd));
+        ASSERT(m_inlineSize &gt; 0);
+
+        m_deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr(
+            start, linkBuffer.locationOf(state.slowPathCall));
+        m_deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr(
+            start, linkBuffer.locationOf(state.slowPathStart));
+    }
+
+    MacroAssemblerCodeRef m_code;
+    CodeLocationLabel m_inlineStart;
+    int32_t m_inlineSize;
+    int32_t m_deltaFromStartToSlowPathCallLocation;
+    int32_t m_deltaFromStartToSlowPathStart;
+    GeneratorType m_generator;
+};
+
+typedef JITMathIC&lt;JITAddGenerator&gt; JITAddIC;
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMathICForwardsh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/jit/JITMathICForwards.h (0 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMathICForwards.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/JITMathICForwards.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(JIT)
+
+namespace JSC {
+
+template &lt;typename Generator&gt; class JITMathIC;
+class JITAddGenerator;
+
+typedef JITMathIC&lt;JITAddGenerator&gt; JITAddIC;
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMathICInlineResulth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/jit/JITMathICInlineResult.h (0 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMathICInlineResult.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/JITMathICInlineResult.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(JIT)
+
+namespace JSC {
+
+enum class JITMathICInlineResult {
+    GeneratedFastPath,
+    GenerateFullSnippet,
+    DontGenerate
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMulGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -28,6 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> void JITMulGenerator::generateFastPath(CCallHelpers&amp; jit)
</span><span class="lines">@@ -137,7 +139,7 @@
</span><span class="cx">     // Do doubleVar * doubleVar.
</span><span class="cx">     jit.mulDouble(m_rightFPR, m_leftFPR);
</span><span class="cx"> 
</span><del>-    if (!m_resultProfile)
</del><ins>+    if (!m_arithProfile)
</ins><span class="cx">         jit.boxDouble(m_leftFPR, m_result);
</span><span class="cx">     else {
</span><span class="cx">         // The Int52 overflow check below intentionally omits 1ll &lt;&lt; 51 as a valid negative Int52 value.
</span><span class="lines">@@ -149,11 +151,11 @@
</span><span class="cx">         jit.moveDoubleTo64(m_leftFPR, m_result.payloadGPR());
</span><span class="cx">         CCallHelpers::Jump notNegativeZero = jit.branch64(CCallHelpers::NotEqual, m_result.payloadGPR(), CCallHelpers::TrustedImm64(negativeZeroBits));
</span><span class="cx"> 
</span><del>-        jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile-&gt;addressOfFlags()));
</del><ins>+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</ins><span class="cx">         CCallHelpers::Jump done = jit.jump();
</span><span class="cx"> 
</span><span class="cx">         notNegativeZero.link(&amp;jit);
</span><del>-        jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile-&gt;addressOfFlags()));
</del><ins>+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</ins><span class="cx"> 
</span><span class="cx">         jit.move(m_result.payloadGPR(), m_scratchGPR);
</span><span class="cx">         jit.urshiftPtr(CCallHelpers::Imm32(52), m_scratchGPR);
</span><span class="lines">@@ -160,7 +162,7 @@
</span><span class="cx">         jit.and32(CCallHelpers::Imm32(0x7ff), m_scratchGPR);
</span><span class="cx">         CCallHelpers::Jump noInt52Overflow = jit.branch32(CCallHelpers::LessThanOrEqual, m_scratchGPR, CCallHelpers::TrustedImm32(0x431));
</span><span class="cx"> 
</span><del>-        jit.or32(CCallHelpers::TrustedImm32(ResultProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_resultProfile-&gt;addressOfFlags()));
</del><ins>+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</ins><span class="cx">         noInt52Overflow.link(&amp;jit);
</span><span class="cx"> 
</span><span class="cx">         done.link(&amp;jit);
</span><span class="lines">@@ -171,11 +173,11 @@
</span><span class="cx">         notNegativeZero.append(jit.branch32(CCallHelpers::NotEqual, m_result.payloadGPR(), CCallHelpers::TrustedImm32(0)));
</span><span class="cx">         notNegativeZero.append(jit.branch32(CCallHelpers::NotEqual, m_result.tagGPR(), CCallHelpers::TrustedImm32(negativeZeroBits &gt;&gt; 32)));
</span><span class="cx"> 
</span><del>-        jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile-&gt;addressOfFlags()));
</del><ins>+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</ins><span class="cx">         CCallHelpers::Jump done = jit.jump();
</span><span class="cx"> 
</span><span class="cx">         notNegativeZero.link(&amp;jit);
</span><del>-        jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile-&gt;addressOfFlags()));
</del><ins>+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</ins><span class="cx"> 
</span><span class="cx">         jit.move(m_result.tagGPR(), m_scratchGPR);
</span><span class="cx">         jit.urshiftPtr(CCallHelpers::Imm32(52 - 32), m_scratchGPR);
</span><span class="lines">@@ -182,7 +184,7 @@
</span><span class="cx">         jit.and32(CCallHelpers::Imm32(0x7ff), m_scratchGPR);
</span><span class="cx">         CCallHelpers::Jump noInt52Overflow = jit.branch32(CCallHelpers::LessThanOrEqual, m_scratchGPR, CCallHelpers::TrustedImm32(0x431));
</span><span class="cx">         
</span><del>-        jit.or32(CCallHelpers::TrustedImm32(ResultProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_resultProfile-&gt;addressOfFlags()));
</del><ins>+        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</ins><span class="cx"> 
</span><span class="cx">         m_endJumpList.append(noInt52Overflow);
</span><span class="cx">         if (m_scratchGPR == m_result.tagGPR() || m_scratchGPR == m_result.payloadGPR())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMulGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITMulGenerator.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMulGenerator.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITMulGenerator.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     JITMulGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
</span><span class="cx">         JSValueRegs result, JSValueRegs left, JSValueRegs right,
</span><span class="cx">         FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
</span><del>-        ResultProfile* resultProfile = nullptr)
</del><ins>+        ArithProfile* arithProfile = nullptr)
</ins><span class="cx">         : m_leftOperand(leftOperand)
</span><span class="cx">         , m_rightOperand(rightOperand)
</span><span class="cx">         , m_result(result)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx">         , m_rightFPR(rightFPR)
</span><span class="cx">         , m_scratchGPR(scratchGPR)
</span><span class="cx">         , m_scratchFPR(scratchFPR)
</span><del>-        , m_resultProfile(resultProfile)
</del><ins>+        , m_arithProfile(arithProfile)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(!m_leftOperand.isPositiveConstInt32() || !m_rightOperand.isPositiveConstInt32());
</span><span class="cx">     }
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     FPRReg m_rightFPR;
</span><span class="cx">     GPRReg m_scratchGPR;
</span><span class="cx">     FPRReg m_scratchFPR;
</span><del>-    ResultProfile* m_resultProfile;
</del><ins>+    ArithProfile* m_arithProfile;
</ins><span class="cx">     bool m_didEmitFastPath { false };
</span><span class="cx"> 
</span><span class="cx">     CCallHelpers::JumpList m_endJumpList;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;ArrayConstructor.h&quot;
</span><span class="cx"> #include &quot;CommonSlowPaths.h&quot;
</span><span class="cx"> #include &quot;DFGCompilationMode.h&quot;
</span><span class="lines">@@ -2247,18 +2248,82 @@
</span><span class="cx">     return jsString(exec, Identifier::from(exec, index).string());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE static EncodedJSValue unprofiledAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+    
+    return JSValue::encode(jsAdd(exec, op1, op2));
+}
+
+ALWAYS_INLINE static EncodedJSValue profiledAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+
+    ASSERT(arithProfile);
+    arithProfile-&gt;observeLHSAndRHS(op1, op2);
+
+    JSValue result = jsAdd(exec, op1, op2);
+    arithProfile-&gt;observeResult(result);
+
+    return JSValue::encode(result);
+}
+
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</span><span class="cx"> {
</span><ins>+    return unprofiledAdd(exec, encodedOp1, encodedOp2);
+}
+
+EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
+{
+    return profiledAdd(exec, encodedOp1, encodedOp2, arithProfile);
+}
+
+EncodedJSValue JIT_OPERATION operationValueAddProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITAddIC* addIC)
+{
</ins><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx">     
</span><span class="cx">     JSValue op1 = JSValue::decode(encodedOp1);
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><ins>+
+    ASSERT(arithProfile);
+    arithProfile-&gt;observeLHSAndRHS(op1, op2);
+    auto nonOptimizeVariant = operationValueAddProfiledNoOptimize;
+    addIC-&gt;generateOutOfLine(*vm, exec-&gt;codeBlock(), nonOptimizeVariant);
</ins><span class="cx">     
</span><ins>+    JSValue result = jsAdd(exec, op1, op2);
+    arithProfile-&gt;observeResult(result);
+
+    return JSValue::encode(result);
+}
+
+EncodedJSValue JIT_OPERATION operationValueAddProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITAddIC*)
+{
+    return profiledAdd(exec, encodedOp1, encodedOp2, arithProfile);
+}
+
+EncodedJSValue JIT_OPERATION operationValueAddOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    auto nonOptimizeVariant = operationValueAddNoOptimize;
+    addIC-&gt;generateOutOfLine(*vm, exec-&gt;codeBlock(), nonOptimizeVariant);
+
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
</ins><span class="cx">     return JSValue::encode(jsAdd(exec, op1, op2));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile)
</del><ins>+EncodedJSValue JIT_OPERATION operationValueAddNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*)
</ins><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="lines">@@ -2267,7 +2332,7 @@
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx">     
</span><span class="cx">     JSValue result = jsAdd(exec, op1, op2);
</span><del>-    resultProfile-&gt;detectNumericness(result);
</del><ins>+
</ins><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2284,7 +2349,7 @@
</span><span class="cx">     return JSValue::encode(jsNumber(a * b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile)
</del><ins>+EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
</ins><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="lines">@@ -2296,7 +2361,7 @@
</span><span class="cx">     double b = op2.toNumber(exec);
</span><span class="cx">     
</span><span class="cx">     JSValue result = jsNumber(a * b);
</span><del>-    resultProfile-&gt;detectNumericness(result);
</del><ins>+    arithProfile-&gt;observeResult(result);
</ins><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2313,7 +2378,7 @@
</span><span class="cx">     return JSValue::encode(jsNumber(a - b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile)
</del><ins>+EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
</ins><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="lines">@@ -2325,7 +2390,7 @@
</span><span class="cx">     double b = op2.toNumber(exec);
</span><span class="cx">     
</span><span class="cx">     JSValue result = jsNumber(a - b);
</span><del>-    resultProfile-&gt;detectNumericness(result);
</del><ins>+    arithProfile-&gt;observeResult(result);
</ins><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;JITMathICForwards.h&quot;
</ins><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;PropertyOffset.h&quot;
</span><span class="cx"> #include &quot;SlowPathReturnType.h&quot;
</span><span class="lines">@@ -42,6 +43,7 @@
</span><span class="cx"> class CallLinkInfo;
</span><span class="cx"> class CodeBlock;
</span><span class="cx"> class ExecState;
</span><ins>+class JITAddGenerator;
</ins><span class="cx"> class JSArray;
</span><span class="cx"> class JSFunction;
</span><span class="cx"> class JSLexicalEnvironment;
</span><span class="lines">@@ -54,7 +56,7 @@
</span><span class="cx"> 
</span><span class="cx"> struct ByValInfo;
</span><span class="cx"> struct InlineCallFrame;
</span><del>-struct ResultProfile;
</del><ins>+struct ArithProfile;
</ins><span class="cx"> 
</span><span class="cx"> typedef ExecState CallFrame;
</span><span class="cx"> 
</span><span class="lines">@@ -69,6 +71,7 @@
</span><span class="cx">     A: JSArray*
</span><span class="cx">     Aap: ArrayAllocationProfile*
</span><span class="cx">     Ap: ArrayProfile*
</span><ins>+    Arp: ArithProfile*
</ins><span class="cx">     By: ByValInfo*
</span><span class="cx">     C: JSCell*
</span><span class="cx">     Cb: CodeBlock*
</span><span class="lines">@@ -81,6 +84,7 @@
</span><span class="cx">     Icf: InlineCallFrame*
</span><span class="cx">     Idc: const Identifier*
</span><span class="cx">     J: EncodedJSValue
</span><ins>+    Jaic: JITAddIC*
</ins><span class="cx">     Jcp: const JSValue*
</span><span class="cx">     Jsc: JSScope*
</span><span class="cx">     Jsf: JSFunction*
</span><span class="lines">@@ -92,7 +96,6 @@
</span><span class="cx">     Q: int64_t
</span><span class="cx">     R: Register
</span><span class="cx">     Reo: RegExpObject*
</span><del>-    Rp: ResultProfile*
</del><span class="cx">     S: size_t
</span><span class="cx">     Sprt: SlowPathReturnType
</span><span class="cx">     Ssi: StructureStubInfo*
</span><span class="lines">@@ -133,7 +136,9 @@
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, ArrayProfile*);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, ByValInfo*);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
</span><del>-typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJRp)(ExecState*, EncodedJSValue, EncodedJSValue, ResultProfile*);
</del><ins>+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJArp)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*);
+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJArpJaic)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*, JITAddIC*);
+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJJaic)(ExecState*, EncodedJSValue, EncodedJSValue, JITAddIC*);
</ins><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReo)(ExecState*, JSString*, RegExpObject*);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReoJss)(ExecState*, JSString*, RegExpObject*, JSString*);
</span><span class="lines">@@ -408,11 +413,15 @@
</span><span class="cx"> JSCell* JIT_OPERATION operationToIndexString(ExecState*, int32_t);
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><del>-EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL;
</del><ins>+EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueAddProfiledOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITAddIC*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueAddProfiledNoOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITAddIC*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueAddOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueAddNoOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><del>-EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL;
</del><ins>+EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><del>-EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL;
</del><ins>+EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
</ins><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION operationProcessTypeProfilerLog(ExecState*) WTF_INTERNAL;
</span><span class="cx"> void JIT_OPERATION operationProcessShadowChickenLog(ExecState*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITSubGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITSubGenerator.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITSubGenerator.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITSubGenerator.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -26,6 +26,8 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;JITSubGenerator.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -83,8 +85,8 @@
</span><span class="cx">     rightWasInteger.link(&amp;jit);
</span><span class="cx"> 
</span><span class="cx">     jit.subDouble(m_rightFPR, m_leftFPR);
</span><del>-    if (m_resultProfile)
-        m_resultProfile-&gt;emitSetDouble(jit);
</del><ins>+    if (m_arithProfile)
+        m_arithProfile-&gt;emitSetDouble(jit);
</ins><span class="cx"> 
</span><span class="cx">     jit.boxDouble(m_leftFPR, m_result);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITSubGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITSubGenerator.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITSubGenerator.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/JITSubGenerator.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     JITSubGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
</span><span class="cx">         JSValueRegs result, JSValueRegs left, JSValueRegs right,
</span><span class="cx">         FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
</span><del>-        ResultProfile* resultProfile = nullptr)
</del><ins>+        ArithProfile* arithProfile = nullptr)
</ins><span class="cx">         : m_leftOperand(leftOperand)
</span><span class="cx">         , m_rightOperand(rightOperand)
</span><span class="cx">         , m_result(result)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx">         , m_rightFPR(rightFPR)
</span><span class="cx">         , m_scratchGPR(scratchGPR)
</span><span class="cx">         , m_scratchFPR(scratchFPR)
</span><del>-        , m_resultProfile(resultProfile)
</del><ins>+        , m_arithProfile(arithProfile)
</ins><span class="cx">     { }
</span><span class="cx"> 
</span><span class="cx">     void generateFastPath(CCallHelpers&amp;);
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx">     FPRReg m_rightFPR;
</span><span class="cx">     GPRReg m_scratchGPR;
</span><span class="cx">     FPRReg m_scratchFPR;
</span><del>-    ResultProfile* m_resultProfile;
</del><ins>+    ArithProfile* m_arithProfile;
</ins><span class="cx">     bool m_didEmitFastPath { false };
</span><span class="cx"> 
</span><span class="cx">     CCallHelpers::JumpList m_endJumpList;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void repatchCall(CodeBlock* codeBlock, CodeLocationCall call, FunctionPtr newCalleeFunction)
</del><ins>+void ftlThunkAwareRepatchCall(CodeBlock* codeBlock, CodeLocationCall call, FunctionPtr newCalleeFunction)
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx">     if (codeBlock-&gt;jitType() == JITCode::FTLJIT) {
</span><span class="lines">@@ -167,7 +167,7 @@
</span><span class="cx"> 
</span><span class="cx">                 bool generatedCodeInline = InlineAccess::generateArrayLength(*codeBlock-&gt;vm(), stubInfo, jsCast&lt;JSArray*&gt;(baseValue));
</span><span class="cx">                 if (generatedCodeInline) {
</span><del>-                    repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
</del><ins>+                    ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
</ins><span class="cx">                     stubInfo.initArrayLength();
</span><span class="cx">                     return RetryCacheLater;
</span><span class="cx">                 }
</span><span class="lines">@@ -220,7 +220,7 @@
</span><span class="cx">             if (generatedCodeInline) {
</span><span class="cx">                 LOG_IC((ICEvent::GetByIdSelfPatch, structure-&gt;classInfo(), propertyName));
</span><span class="cx">                 structure-&gt;startWatchingPropertyForReplacements(vm, slot.cachedOffset());
</span><del>-                repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
</del><ins>+                ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
</ins><span class="cx">                 stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset());
</span><span class="cx">                 return RetryCacheLater;
</span><span class="cx">             }
</span><span class="lines">@@ -314,7 +314,7 @@
</span><span class="cx">     GCSafeConcurrentJITLocker locker(exec-&gt;codeBlock()-&gt;m_lock, exec-&gt;vm().heap);
</span><span class="cx">     
</span><span class="cx">     if (tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo, kind) == GiveUpOnCache)
</span><del>-        repatchCall(exec-&gt;codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericGetByIdFunction(kind));
</del><ins>+        ftlThunkAwareRepatchCall(exec-&gt;codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericGetByIdFunction(kind));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static V_JITOperation_ESsiJJI appropriateGenericPutByIdFunction(const PutPropertySlot &amp;slot, PutKind putKind)
</span><span class="lines">@@ -372,7 +372,7 @@
</span><span class="cx">                 bool generatedCodeInline = InlineAccess::generateSelfPropertyReplace(vm, stubInfo, structure, slot.cachedOffset());
</span><span class="cx">                 if (generatedCodeInline) {
</span><span class="cx">                     LOG_IC((ICEvent::PutByIdSelfPatch, structure-&gt;classInfo(), ident));
</span><del>-                    repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingPutByIdFunction(slot, putKind));
</del><ins>+                    ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingPutByIdFunction(slot, putKind));
</ins><span class="cx">                     stubInfo.initPutByIdReplace(codeBlock, structure, slot.cachedOffset());
</span><span class="cx">                     return RetryCacheLater;
</span><span class="cx">                 }
</span><span class="lines">@@ -468,7 +468,7 @@
</span><span class="cx">     GCSafeConcurrentJITLocker locker(exec-&gt;codeBlock()-&gt;m_lock, exec-&gt;vm().heap);
</span><span class="cx">     
</span><span class="cx">     if (tryCachePutByID(exec, baseValue, structure, propertyName, slot, stubInfo, putKind) == GiveUpOnCache)
</span><del>-        repatchCall(exec-&gt;codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericPutByIdFunction(slot, putKind));
</del><ins>+        ftlThunkAwareRepatchCall(exec-&gt;codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericPutByIdFunction(slot, putKind));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static InlineCacheAction tryRepatchIn(
</span><span class="lines">@@ -529,7 +529,7 @@
</span><span class="cx"> {
</span><span class="cx">     SuperSamplerScope superSamplerScope(false);
</span><span class="cx">     if (tryRepatchIn(exec, base, ident, wasFound, slot, stubInfo) == GiveUpOnCache)
</span><del>-        repatchCall(exec-&gt;codeBlock(), stubInfo.slowPathCallLocation(), operationIn);
</del><ins>+        ftlThunkAwareRepatchCall(exec-&gt;codeBlock(), stubInfo.slowPathCallLocation(), operationIn);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void linkSlowFor(VM*, CallLinkInfo&amp; callLinkInfo, MacroAssemblerCodeRef codeRef)
</span><span class="lines">@@ -901,7 +901,7 @@
</span><span class="cx"> 
</span><span class="cx"> void resetGetByID(CodeBlock* codeBlock, StructureStubInfo&amp; stubInfo, GetByIDKind kind)
</span><span class="cx"> {
</span><del>-    repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
</del><ins>+    ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
</ins><span class="cx">     InlineAccess::rewireStubAsJump(*codeBlock-&gt;vm(), stubInfo, stubInfo.slowPathStartLocation());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -920,7 +920,7 @@
</span><span class="cx">         optimizedFunction = operationPutByIdDirectNonStrictOptimize;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    repatchCall(codeBlock, stubInfo.slowPathCallLocation(), optimizedFunction);
</del><ins>+    ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), optimizedFunction);
</ins><span class="cx">     InlineAccess::rewireStubAsJump(*codeBlock-&gt;vm(), stubInfo, stubInfo.slowPathStartLocation());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/jit/Repatch.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx"> void resetGetByID(CodeBlock*, StructureStubInfo&amp;, GetByIDKind);
</span><span class="cx"> void resetPutByID(CodeBlock*, StructureStubInfo&amp;);
</span><span class="cx"> void resetIn(CodeBlock*, StructureStubInfo&amp;);
</span><ins>+void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall, FunctionPtr newCalleeFunction);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntData.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntData.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/llint/LLIntData.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;LLIntData.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;BytecodeConventions.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;CodeType.h&quot;
</span><span class="lines">@@ -223,6 +224,47 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     ASSERT(StringImpl::s_hashFlag8BitBuffer == 8);
</span><ins>+
+    {
+        uint32_t bits = 0x120000;
+        UNUSED_PARAM(bits);
+        ArithProfile arithProfile;
+        arithProfile.lhsSawInt32();
+        arithProfile.rhsSawInt32();
+        ASSERT(arithProfile.bits() == bits);
+        ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyInt32());
+        ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyInt32());
+    }
+    {
+        uint32_t bits = 0x220000;
+        UNUSED_PARAM(bits);
+        ArithProfile arithProfile;
+        arithProfile.lhsSawNumber();
+        arithProfile.rhsSawInt32();
+        ASSERT(arithProfile.bits() == bits);
+        ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyNumber());
+        ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyInt32());
+    }
+    {
+        uint32_t bits = 0x240000;
+        UNUSED_PARAM(bits);
+        ArithProfile arithProfile;
+        arithProfile.lhsSawNumber();
+        arithProfile.rhsSawNumber();
+        ASSERT(arithProfile.bits() == bits);
+        ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyNumber());
+        ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyNumber());
+    }
+    {
+        uint32_t bits = 0x140000;
+        UNUSED_PARAM(bits);
+        ArithProfile arithProfile;
+        arithProfile.lhsSawInt32();
+        arithProfile.rhsSawNumber();
+        ASSERT(arithProfile.bits() == bits);
+        ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyInt32());
+        ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyNumber());
+    }
</ins><span class="cx"> }
</span><span class="cx"> #if COMPILER(CLANG)
</span><span class="cx"> #pragma clang diagnostic pop
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -252,6 +252,12 @@
</span><span class="cx"> # ShadowChicken data
</span><span class="cx"> const ShadowChickenTailMarker = 0x7a11
</span><span class="cx"> 
</span><ins>+# ArithProfile data
+const ArithProfileIntInt = 0x120000
+const ArithProfileNumberInt = 0x220000
+const ArithProfileNumberNumber = 0x240000
+const ArithProfileIntNumber = 0x140000
+
</ins><span class="cx"> # Some register conventions.
</span><span class="cx"> if JSVALUE64
</span><span class="cx">     # - Use a pair of registers to represent the PC: one register for the
</span><span class="lines">@@ -286,6 +292,10 @@
</span><span class="cx">         loadp offset * 8[PB, PC, 8], dest
</span><span class="cx">     end
</span><span class="cx">     
</span><ins>+    macro storeisToInstruction(value, offset)
+        storei value, offset * 8[PB, PC, 8]
+    end
+
</ins><span class="cx">     macro storepToInstruction(value, offset)
</span><span class="cx">         storep value, offset * 8[PB, PC, 8]
</span><span class="cx">     end
</span><span class="lines">@@ -299,6 +309,10 @@
</span><span class="cx">     macro loadpFromInstruction(offset, dest)
</span><span class="cx">         loadp offset * 4[PC], dest
</span><span class="cx">     end
</span><ins>+
+    macro storeisToInstruction(value, offset)
+        storei value, offset * 4[PC]
+    end
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> if X86_64_WIN
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -1014,6 +1014,9 @@
</span><span class="cx">     loadConstantOrVariable2Reg(t0, t2, t0)
</span><span class="cx">     bineq t2, Int32Tag, .op1NotInt
</span><span class="cx">     bineq t3, Int32Tag, .op2NotInt
</span><ins>+    loadisFromInstruction(4, t5)
+    ori ArithProfileIntInt, t5
+    storeisToInstruction(t5, 4)
</ins><span class="cx">     loadi 4[PC], t2
</span><span class="cx">     integerOperationAndStore(t3, t1, t0, .slow, t2)
</span><span class="cx">     dispatch(5)
</span><span class="lines">@@ -1023,10 +1026,16 @@
</span><span class="cx">     bia t2, LowestTag, .slow
</span><span class="cx">     bib t3, LowestTag, .op1NotIntOp2Double
</span><span class="cx">     bineq t3, Int32Tag, .slow
</span><ins>+    loadisFromInstruction(4, t5)
+    ori ArithProfileNumberInt, t5
+    storeisToInstruction(t5, 4)
</ins><span class="cx">     ci2d t1, ft1
</span><span class="cx">     jmp .op1NotIntReady
</span><span class="cx"> .op1NotIntOp2Double:
</span><span class="cx">     fii2d t1, t3, ft1
</span><ins>+    loadisFromInstruction(4, t5)
+    ori ArithProfileNumberNumber, t5
+    storeisToInstruction(t5, 4)
</ins><span class="cx"> .op1NotIntReady:
</span><span class="cx">     loadi 4[PC], t1
</span><span class="cx">     fii2d t0, t2, ft0
</span><span class="lines">@@ -1038,6 +1047,9 @@
</span><span class="cx">     # First operand is definitely an int, the second operand is definitely not.
</span><span class="cx">     loadi 4[PC], t2
</span><span class="cx">     bia t3, LowestTag, .slow
</span><ins>+    loadisFromInstruction(4, t5)
+    ori ArithProfileIntNumber, t5
+    storeisToInstruction(t5, 4)
</ins><span class="cx">     ci2d t0, ft0
</span><span class="cx">     fii2d t1, t3, ft1
</span><span class="cx">     doubleOperation(ft1, ft0)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -893,6 +893,9 @@
</span><span class="cx">     bqb t1, tagTypeNumber, .op2NotInt
</span><span class="cx">     loadisFromInstruction(1, t2)
</span><span class="cx">     integerOperationAndStore(t1, t0, .slow, t2)
</span><ins>+    loadisFromInstruction(4, t1)
+    ori ArithProfileIntInt, t1
+    storeisToInstruction(t1, 4)
</ins><span class="cx">     dispatch(5)
</span><span class="cx"> 
</span><span class="cx"> .op1NotInt:
</span><span class="lines">@@ -902,8 +905,14 @@
</span><span class="cx">     btqz t1, tagTypeNumber, .slow
</span><span class="cx">     addq tagTypeNumber, t1
</span><span class="cx">     fq2d t1, ft1
</span><ins>+    loadisFromInstruction(4, t2)
+    ori ArithProfileNumberNumber, t2
+    storeisToInstruction(t2, 4)
</ins><span class="cx">     jmp .op1NotIntReady
</span><span class="cx"> .op1NotIntOp2Int:
</span><ins>+    loadisFromInstruction(4, t2)
+    ori ArithProfileNumberInt, t2
+    storeisToInstruction(t2, 4)
</ins><span class="cx">     ci2d t1, ft1
</span><span class="cx"> .op1NotIntReady:
</span><span class="cx">     loadisFromInstruction(1, t2)
</span><span class="lines">@@ -919,6 +928,9 @@
</span><span class="cx">     # First operand is definitely an int, the second is definitely not.
</span><span class="cx">     loadisFromInstruction(1, t2)
</span><span class="cx">     btqz t1, tagTypeNumber, .slow
</span><ins>+    loadisFromInstruction(4, t3)
+    ori ArithProfileIntNumber, t3
+    storeisToInstruction(t3, 4)
</ins><span class="cx">     ci2d t0, ft0
</span><span class="cx">     addq tagTypeNumber, t1
</span><span class="cx">     fq2d t1, ft1
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserResultTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ResultType.h (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ResultType.h        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/parser/ResultType.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -32,46 +32,48 @@
</span><span class="cx">     private:
</span><span class="cx">         friend struct OperandTypes;
</span><span class="cx"> 
</span><del>-        typedef char Type;
</del><ins>+        typedef uint8_t Type;
</ins><span class="cx">         static const Type TypeInt32 = 1;
</span><del>-        
-        static const Type TypeMaybeNumber = 0x04;
-        static const Type TypeMaybeString = 0x08;
-        static const Type TypeMaybeNull   = 0x10;
-        static const Type TypeMaybeBool   = 0x20;
-        static const Type TypeMaybeOther  = 0x40;
</del><ins>+        static const Type TypeMaybeNumber = 0x02;
+        static const Type TypeMaybeString = 0x04;
+        static const Type TypeMaybeNull   = 0x08;
+        static const Type TypeMaybeBool   = 0x10;
+        static const Type TypeMaybeOther  = 0x20;
</ins><span class="cx"> 
</span><span class="cx">         static const Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther;
</span><span class="cx"> 
</span><ins>+    public:
+        static const int numBitsNeeded = 6;
+        static_assert((TypeBits &amp; ((1 &lt;&lt; numBitsNeeded) - 1)) == TypeBits, &quot;This is necessary for correctness.&quot;);
+
</ins><span class="cx">         explicit ResultType(Type type)
</span><del>-            : m_type(type)
</del><ins>+            : m_bits(type)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-    public:
</del><span class="cx">         bool isInt32() const
</span><span class="cx">         {
</span><del>-            return m_type &amp; TypeInt32;
</del><ins>+            return m_bits &amp; TypeInt32;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         bool definitelyIsNumber() const
</span><span class="cx">         {
</span><del>-            return (m_type &amp; TypeBits) == TypeMaybeNumber;
</del><ins>+            return (m_bits &amp; TypeBits) == TypeMaybeNumber;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         bool definitelyIsString() const
</span><span class="cx">         {
</span><del>-            return (m_type &amp; TypeBits) == TypeMaybeString;
</del><ins>+            return (m_bits &amp; TypeBits) == TypeMaybeString;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         bool definitelyIsBoolean() const
</span><span class="cx">         {
</span><del>-            return (m_type &amp; TypeBits) == TypeMaybeBool;
</del><ins>+            return (m_bits &amp; TypeBits) == TypeMaybeBool;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         bool mightBeNumber() const
</span><span class="cx">         {
</span><del>-            return m_type &amp; TypeMaybeNumber;
</del><ins>+            return m_bits &amp; TypeMaybeNumber;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         bool isNotNumber() const
</span><span class="lines">@@ -141,8 +143,10 @@
</span><span class="cx">             return numberTypeIsInt32();
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        Type bits() const { return m_bits; }
+
</ins><span class="cx">     private:
</span><del>-        Type m_type;
</del><ins>+        Type m_bits;
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     struct OperandTypes
</span><span class="lines">@@ -152,8 +156,8 @@
</span><span class="cx">             // We have to initialize one of the int to ensure that
</span><span class="cx">             // the entire struct is initialized.
</span><span class="cx">             m_u.i = 0;
</span><del>-            m_u.rds.first = first.m_type;
-            m_u.rds.second = second.m_type;
</del><ins>+            m_u.rds.first = first.m_bits;
+            m_u.rds.second = second.m_bits;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         union {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;CommonSlowPaths.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;ArithProfile.h&quot;
</ins><span class="cx"> #include &quot;ArrayConstructor.h&quot;
</span><span class="cx"> #include &quot;BuiltinNames.h&quot;
</span><span class="cx"> #include &quot;CallFrame.h&quot;
</span><span class="lines">@@ -359,22 +360,21 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-static void updateResultProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right)
</del><ins>+static void updateArithProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right)
</ins><span class="cx"> {
</span><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><del>-    unsigned bytecodeOffset = codeBlock-&gt;bytecodeOffset(pc);
-    ResultProfile* profile = codeBlock-&gt;ensureResultProfile(bytecodeOffset);
</del><ins>+    ArithProfile&amp; profile = codeBlock-&gt;arithProfileForPC(pc);
</ins><span class="cx"> 
</span><span class="cx">     if (result.isNumber()) {
</span><span class="cx">         if (!result.isInt32()) {
</span><span class="cx">             if (left.isInt32() &amp;&amp; right.isInt32())
</span><del>-                profile-&gt;setObservedInt32Overflow();
</del><ins>+                profile.setObservedInt32Overflow();
</ins><span class="cx"> 
</span><span class="cx">             double doubleVal = result.asNumber();
</span><span class="cx">             if (!doubleVal &amp;&amp; std::signbit(doubleVal))
</span><del>-                profile-&gt;setObservedNegZeroDouble();
</del><ins>+                profile.setObservedNegZeroDouble();
</ins><span class="cx">             else {
</span><del>-                profile-&gt;setObservedNonNegZeroDouble();
</del><ins>+                profile.setObservedNonNegZeroDouble();
</ins><span class="cx"> 
</span><span class="cx">                 // The Int52 overflow check here intentionally omits 1ll &lt;&lt; 51 as a valid negative Int52 value.
</span><span class="cx">                 // Therefore, we will get a false positive if the result is that value. This is intentionally
</span><span class="lines">@@ -382,14 +382,14 @@
</span><span class="cx">                 static const int64_t int52OverflowPoint = (1ll &lt;&lt; 51);
</span><span class="cx">                 int64_t int64Val = static_cast&lt;int64_t&gt;(std::abs(doubleVal));
</span><span class="cx">                 if (int64Val &gt;= int52OverflowPoint)
</span><del>-                    profile-&gt;setObservedInt52Overflow();
</del><ins>+                    profile.setObservedInt52Overflow();
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     } else
</span><del>-        profile-&gt;setObservedNonNumber();
</del><ins>+        profile.setObservedNonNumber();
</ins><span class="cx"> }
</span><span class="cx"> #else
</span><del>-static void updateResultProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { }
</del><ins>+static void updateArithProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { }
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> SLOW_PATH_DECL(slow_path_to_number)
</span><span class="lines">@@ -407,6 +407,9 @@
</span><span class="cx">     JSValue v2 = OP_C(3).jsValue();
</span><span class="cx">     JSValue result;
</span><span class="cx"> 
</span><ins>+    ArithProfile&amp; arithProfile = exec-&gt;codeBlock()-&gt;arithProfileForPC(pc);
+    arithProfile.observeLHSAndRHS(v1, v2);
+
</ins><span class="cx">     if (v1.isString() &amp;&amp; !v2.isObject())
</span><span class="cx">         result = jsString(exec, asString(v1), v2.toString(exec));
</span><span class="cx">     else if (v1.isNumber() &amp;&amp; v2.isNumber())
</span><span class="lines">@@ -415,7 +418,7 @@
</span><span class="cx">         result = jsAddSlowCase(exec, v1, v2);
</span><span class="cx"> 
</span><span class="cx">     RETURN_WITH_PROFILING(result, {
</span><del>-        updateResultProfileForBinaryArithOp(exec, pc, result, v1, v2);
</del><ins>+        updateArithProfileForBinaryArithOp(exec, pc, result, v1, v2);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -432,7 +435,7 @@
</span><span class="cx">     double b = right.toNumber(exec);
</span><span class="cx">     JSValue result = jsNumber(a * b);
</span><span class="cx">     RETURN_WITH_PROFILING(result, {
</span><del>-        updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
</del><ins>+        updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -445,7 +448,7 @@
</span><span class="cx">     double b = right.toNumber(exec);
</span><span class="cx">     JSValue result = jsNumber(a - b);
</span><span class="cx">     RETURN_WITH_PROFILING(result, {
</span><del>-        updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
</del><ins>+        updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -458,7 +461,7 @@
</span><span class="cx">     double b = right.toNumber(exec);
</span><span class="cx">     JSValue result = jsNumber(a / b);
</span><span class="cx">     RETURN_WITH_PROFILING(result, {
</span><del>-        updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
</del><ins>+        updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressopaddexceptionsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/op-add-exceptions.js (0 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/op-add-exceptions.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/op-add-exceptions.js        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad!&quot;);
+}
+noInline(assert);
+
+function f1() { return &quot;f1&quot;; }
+noInline(f1);
+function f2() { return &quot;f2&quot;; }
+noInline(f2);
+function f3() { return &quot;f3&quot;; }
+noInline(f3);
+
+let oException = {
+    valueOf() { throw new Error(&quot;&quot;); }
+};
+
+function foo(arg1, arg2) {
+    let a = f1();
+    let b = f2();
+    let c = f3();
+    try {
+        arg1 + arg2;
+    } catch(e) {
+        assert(arg1 === oException);
+        assert(arg2 === oException);
+    }
+    assert(a === &quot;f1&quot;);
+    assert(b === &quot;f2&quot;);
+    assert(c === &quot;f3&quot;);
+}
+noInline(foo);
+
+for (let i = 0; i &lt; 1000; i++) {
+    foo(i, {});
+    foo({}, i);
+}
+foo(oException, oException);
+for (let i = 0; i &lt; 10000; i++) {
+    foo(i, {});
+    foo({}, i);
+}
+foo(oException, oException);
+
+
+function ident(x) { return x; }
+noInline(ident);
+
+function bar(arg1, arg2) {
+    let a = f1();
+    let b = f2();
+    let c = f3();
+    let x = ident(arg1);
+    let y = ident(arg2);
+
+    try {
+        arg1 + arg2;
+    } catch(e) {
+        assert(arg1 === oException);
+        assert(arg2 === oException);
+        assert(x === oException);
+        assert(y === oException);
+    }
+    assert(a === &quot;f1&quot;);
+    assert(b === &quot;f2&quot;);
+    assert(c === &quot;f3&quot;);
+}
+noInline(bar);
+
+for (let i = 0; i &lt; 1000; i++) {
+    bar(i, {});
+    bar({}, i);
+}
+bar(oException, oException);
+for (let i = 0; i &lt; 10000; i++) {
+    bar(i, {});
+    bar({}, i);
+}
+bar(oException, oException);
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (203536 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-07-21 23:32:56 UTC (rev 203536)
+++ trunk/Source/WebCore/ChangeLog        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2016-07-21  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        op_add/ValueAdd should be an IC in all JIT tiers
+        https://bugs.webkit.org/show_bug.cgi?id=159649
+
+        Reviewed by Benjamin Poulain.
+
+        * ForwardingHeaders/jit/JITMathICForwards.h: Added.
+
</ins><span class="cx"> 2016-07-21  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Make parameters mandatory for Document.create*() operations
</span></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersjitJITMathICForwardsh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/jit/JITMathICForwards.h (0 => 203537)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/jit/JITMathICForwards.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/jit/JITMathICForwards.h        2016-07-21 23:41:44 UTC (rev 203537)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+#ifndef WebCore_FWD_JITMathICForwards_h
+#define WebCore_FWD_JITMathICForwards_h
+#include &lt;JavaScriptCore/JITMathICForwards.h&gt;
+#endif
</ins></span></pre>
</div>
</div>

</body>
</html>