<!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>[183724] trunk/Source/JavaScriptCore</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/183724">183724</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-05-02 17:15:27 -0700 (Sat, 02 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>TypeOf should be fast
https://bugs.webkit.org/show_bug.cgi?id=144396

Reviewed by Geoffrey Garen.
        
Adds comprehensive support for fast typeof to the optimizing JITs. Calls into the runtime
are only used for very exotic objects - they must have either the MasqueradesAsUndefined or
TypeOfShouldCallGetCallData type flags set. All other cases are handled inline.
        
This means optimizing IsObjectOrNull, IsFunction, and TypeOf - all node types that used to
rely heavily on C++ calls to fulfill their function.
        
Because TypeOf is now so fast, we no longer need to do any speculations on this node.
        
In the FTL, we take this further by querying AI for each branch in the TypeOf decision tree.
This means that if the TypeOf is dominated by any type checks, we will automatically prune
out cases that are redundant.
        
This patch anticipates the addition of SwitchTypeOf or something like that. So, the TypeOf
code generation is designed to be reusable.
        
This is a speed-up on most typeof benchmarks. But, it is a slow-down on benchmarks that take
the exotic call trap hook. That hook is now in a deeper slow path than before.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize): TypeOf was pure all along, but we failed to realize this.
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGHeapLocation.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileIsObjectOrNull):
(JSC::DFG::SpeculativeJIT::compileIsFunction):
(JSC::DFG::SpeculativeJIT::compileTypeOf):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::blessedBooleanResult):
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileIsObjectOrNull):
(JSC::FTL::LowerDFGToLLVM::compileIsFunction):
(JSC::FTL::LowerDFGToLLVM::compileTypeOf):
(JSC::FTL::LowerDFGToLLVM::buildTypeOf): Reusable TypeOf building for the FTL.
(JSC::FTL::LowerDFGToLLVM::isExoticForTypeof):
* ftl/FTLSwitchCase.h:
(JSC::FTL::SwitchCase::SwitchCase):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::branchIfNotEqual):
(JSC::AssemblyHelpers::branchIfEqual):
(JSC::AssemblyHelpers::branchIfNumber):
(JSC::AssemblyHelpers::branchIfNotNumber):
(JSC::AssemblyHelpers::branchIfBoolean):
(JSC::AssemblyHelpers::branchIfNotBoolean):
(JSC::AssemblyHelpers::boxBooleanPayload):
(JSC::AssemblyHelpers::boxBoolean):
(JSC::AssemblyHelpers::emitTypeOf): Reusable TypeOf building for assembly JITs.
* jit/JITOperations.h:
* runtime/SmallStrings.h:
(JSC::SmallStrings::typeString):
* runtime/TypeofType.cpp: Added.
(WTF::printInternal):
* runtime/TypeofType.h: Added.
* tests/stress/type-of-functions-and-objects.js: Modified this test to give more comprehensive feedback.</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="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGHeapLocationcpp">trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGHeapLocationh">trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLIntrinsicRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLSwitchCaseh">trunk/Source/JavaScriptCore/ftl/FTLSwitchCase.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSmallStringsh">trunk/Source/JavaScriptCore/runtime/SmallStrings.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypeoffunctionsandobjectsjs">trunk/Source/JavaScriptCore/tests/stress/type-of-functions-and-objects.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreruntimeTypeofTypecpp">trunk/Source/JavaScriptCore/runtime/TypeofType.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeTypeofTypeh">trunk/Source/JavaScriptCore/runtime/TypeofType.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 (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -581,6 +581,7 @@
</span><span class="cx">     runtime/TypeSet.cpp
</span><span class="cx">     runtime/TypedArrayController.cpp
</span><span class="cx">     runtime/TypedArrayType.cpp
</span><ins>+    runtime/TypeofType.cpp
</ins><span class="cx">     runtime/VM.cpp
</span><span class="cx">     runtime/VMEntryScope.cpp
</span><span class="cx">     runtime/VarOffset.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -1,3 +1,82 @@
</span><ins>+2015-05-01  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        TypeOf should be fast
+        https://bugs.webkit.org/show_bug.cgi?id=144396
+
+        Reviewed by Geoffrey Garen.
+        
+        Adds comprehensive support for fast typeof to the optimizing JITs. Calls into the runtime
+        are only used for very exotic objects - they must have either the MasqueradesAsUndefined or
+        TypeOfShouldCallGetCallData type flags set. All other cases are handled inline.
+        
+        This means optimizing IsObjectOrNull, IsFunction, and TypeOf - all node types that used to
+        rely heavily on C++ calls to fulfill their function.
+        
+        Because TypeOf is now so fast, we no longer need to do any speculations on this node.
+        
+        In the FTL, we take this further by querying AI for each branch in the TypeOf decision tree.
+        This means that if the TypeOf is dominated by any type checks, we will automatically prune
+        out cases that are redundant.
+        
+        This patch anticipates the addition of SwitchTypeOf or something like that. So, the TypeOf
+        code generation is designed to be reusable.
+        
+        This is a speed-up on most typeof benchmarks. But, it is a slow-down on benchmarks that take
+        the exotic call trap hook. That hook is now in a deeper slow path than before.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize): TypeOf was pure all along, but we failed to realize this.
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGHeapLocation.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileIsObjectOrNull):
+        (JSC::DFG::SpeculativeJIT::compileIsFunction):
+        (JSC::DFG::SpeculativeJIT::compileTypeOf):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::blessedBooleanResult):
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileIsObjectOrNull):
+        (JSC::FTL::LowerDFGToLLVM::compileIsFunction):
+        (JSC::FTL::LowerDFGToLLVM::compileTypeOf):
+        (JSC::FTL::LowerDFGToLLVM::buildTypeOf): Reusable TypeOf building for the FTL.
+        (JSC::FTL::LowerDFGToLLVM::isExoticForTypeof):
+        * ftl/FTLSwitchCase.h:
+        (JSC::FTL::SwitchCase::SwitchCase):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::branchIfNotEqual):
+        (JSC::AssemblyHelpers::branchIfEqual):
+        (JSC::AssemblyHelpers::branchIfNumber):
+        (JSC::AssemblyHelpers::branchIfNotNumber):
+        (JSC::AssemblyHelpers::branchIfBoolean):
+        (JSC::AssemblyHelpers::branchIfNotBoolean):
+        (JSC::AssemblyHelpers::boxBooleanPayload):
+        (JSC::AssemblyHelpers::boxBoolean):
+        (JSC::AssemblyHelpers::emitTypeOf): Reusable TypeOf building for assembly JITs.
+        * jit/JITOperations.h:
+        * runtime/SmallStrings.h:
+        (JSC::SmallStrings::typeString):
+        * runtime/TypeofType.cpp: Added.
+        (WTF::printInternal):
+        * runtime/TypeofType.h: Added.
+        * tests/stress/type-of-functions-and-objects.js: Modified this test to give more comprehensive feedback.
+
</ins><span class="cx"> 2015-05-02  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, add a FIXME referencing https://bugs.webkit.org/show_bug.cgi?id=144527.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -841,6 +841,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\TestRunnerUtils.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\TypedArrayController.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\TypedArrayType.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\runtime\TypeofType.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\TypeLocationCache.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\TypeProfiler.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\TypeProfilerLog.cpp&quot; /&gt;
</span><span class="lines">@@ -1688,6 +1689,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\TypedArrayController.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\TypedArrayInlines.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\TypedArrayType.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\runtime\TypeofType.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\TypeLocationCache.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\TypeProfiler.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\TypeProfilerLog.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -726,6 +726,8 @@
</span><span class="cx">                 0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
</span><span class="cx">                 0FFA549716B8835000B3A982 /* A64DOpcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 652A3A221651C69700A80AFE /* A64DOpcode.cpp */; };
</span><span class="cx">                 0FFA549816B8835300B3A982 /* A64DOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 652A3A231651C69700A80AFE /* A64DOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0FFB6C381AF48DDC00DB1BF7 /* TypeofType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */; };
+                0FFB6C391AF48DDC00DB1BF7 /* TypeofType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0FFB921816D02EB20055A5DB /* DFGAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51916B62772003F696B /* DFGAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FFB921A16D02EC50055A5DB /* DFGBasicBlockInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD5652216AB780A00197653 /* DFGBasicBlockInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FFB921B16D02F010055A5DB /* DFGNodeAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51F16B62772003F696B /* DFGNodeAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2462,6 +2464,8 @@
</span><span class="cx">                 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = &quot;compiled.mach-o.executable&quot;; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
</span><ins>+                0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4451,9 +4455,9 @@
</span><span class="cx">                                 BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */,
</span><span class="cx">                                 BC11667A0E199C05008066DD /* InternalFunction.h */,
</span><span class="cx">                                 86BF642A148DB2B5004DE36A /* Intrinsic.h */,
</span><ins>+                                FE4D55B71AE716CA0052E459 /* IterationStatus.h */,
</ins><span class="cx">                                 70113D491A8DB093003848C4 /* IteratorOperations.cpp */,
</span><span class="cx">                                 70113D4A1A8DB093003848C4 /* IteratorOperations.h */,
</span><del>-                                FE4D55B71AE716CA0052E459 /* IterationStatus.h */,
</del><span class="cx">                                 93ADFCE60CCBD7AC00D30B08 /* JSArray.cpp */,
</span><span class="cx">                                 938772E5038BFE19008635CE /* JSArray.h */,
</span><span class="cx">                                 0F2B66B417B6B5AB00A7AE3F /* JSArrayBuffer.cpp */,
</span><span class="lines">@@ -4739,6 +4743,8 @@
</span><span class="cx">                                 0F2B66DD17B6B5AB00A7AE3F /* TypedArrayType.h */,
</span><span class="cx">                                 52B310FE1975B4240080857C /* TypeLocationCache.cpp */,
</span><span class="cx">                                 52B311001975B4670080857C /* TypeLocationCache.h */,
</span><ins>+                                0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */,
+                                0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */,
</ins><span class="cx">                                 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */,
</span><span class="cx">                                 52C952B619A289850069B386 /* TypeProfiler.h */,
</span><span class="cx">                                 0F2D4DDF19832D91007D4B19 /* TypeProfilerLog.cpp */,
</span><span class="lines">@@ -5711,6 +5717,7 @@
</span><span class="cx">                                 BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */,
</span><span class="cx">                                 0FDB2CEA174896C7007B3C1B /* ConcurrentJITLock.h in Headers */,
</span><span class="cx">                                 BC18C3F50E16F5CD00B34460 /* config.h in Headers */,
</span><ins>+                                0FFB6C391AF48DDC00DB1BF7 /* TypeofType.h in Headers */,
</ins><span class="cx">                                 144836E7132DA7BE005BE785 /* ConservativeRoots.h in Headers */,
</span><span class="cx">                                 A5FD007A189B051000633231 /* ConsoleMessage.h in Headers */,
</span><span class="cx">                                 A5FD0074189B038C00633231 /* ConsoleTypes.h in Headers */,
</span><span class="lines">@@ -7361,6 +7368,7 @@
</span><span class="cx">                                 147F39D4107EC37600427A48 /* JSObject.cpp in Sources */,
</span><span class="cx">                                 1482B7E40A43076000517CFC /* JSObjectRef.cpp in Sources */,
</span><span class="cx">                                 A7F993600FD7325100A0B2D0 /* JSONObject.cpp in Sources */,
</span><ins>+                                0FFB6C381AF48DDC00DB1BF7 /* TypeofType.cpp in Sources */,
</ins><span class="cx">                                 95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */,
</span><span class="cx">                                 7C184E1A17BEDBD3007CB63A /* JSPromise.cpp in Sources */,
</span><span class="cx">                                 7C184E2217BEE240007CB63A /* JSPromiseConstructor.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -159,6 +159,7 @@
</span><span class="cx">     case ValueToInt32:
</span><span class="cx">     case GetExecutable:
</span><span class="cx">     case BottomValue:
</span><ins>+    case TypeOf:
</ins><span class="cx">         def(PureValue(node));
</span><span class="cx">         return;
</span><span class="cx">         
</span><span class="lines">@@ -362,11 +363,6 @@
</span><span class="cx">         def(HeapLocation(IsFunctionLoc, MiscFields, node-&gt;child1()), node);
</span><span class="cx">         return;
</span><span class="cx">         
</span><del>-    case TypeOf:
-        read(MiscFields);
-        def(HeapLocation(TypeOfLoc, MiscFields, node-&gt;child1()), node);
-        return;
-
</del><span class="cx">     case GetById:
</span><span class="cx">     case GetByIdFlush:
</span><span class="cx">     case PutById:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -346,14 +346,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><del>-        case TypeOf: {
-            if (node-&gt;child1()-&gt;shouldSpeculateString())
-                fixEdge&lt;StringUse&gt;(node-&gt;child1());
-            else if (node-&gt;child1()-&gt;shouldSpeculateCell())
-                fixEdge&lt;CellUse&gt;(node-&gt;child1());
-            break;
-        }
-            
</del><span class="cx">         case CompareEqConstant: {
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -1241,6 +1233,7 @@
</span><span class="cx">         case MovHint:
</span><span class="cx">         case ZombieHint:
</span><span class="cx">         case BottomValue:
</span><ins>+        case TypeOf:
</ins><span class="cx">             break;
</span><span class="cx"> #else
</span><span class="cx">         default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGHeapLocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -68,10 +68,6 @@
</span><span class="cx">         out.print(&quot;IsFunctionLoc&quot;);
</span><span class="cx">         return;
</span><span class="cx">         
</span><del>-    case TypeOfLoc:
-        out.print(&quot;TypeOfLoc&quot;);
-        return;
-        
</del><span class="cx">     case GetterLoc:
</span><span class="cx">         out.print(&quot;GetterLoc&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGHeapLocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -53,7 +53,6 @@
</span><span class="cx">     NamedPropertyLoc,
</span><span class="cx">     SetterLoc,
</span><span class="cx">     StructureLoc,
</span><del>-    TypeOfLoc,
</del><span class="cx">     TypedArrayByteOffsetLoc,
</span><span class="cx">     VarInjectionWatchpointLoc,
</span><span class="cx">     StackLoc,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -860,23 +860,86 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-size_t JIT_OPERATION operationIsObjectOrNull(ExecState* exec, EncodedJSValue value)
</del><ins>+size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
</ins><span class="cx"> {
</span><del>-    return jsIsObjectTypeOrNull(exec, JSValue::decode(value));
</del><ins>+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+
+    ASSERT(jsDynamicCast&lt;JSObject*&gt;(object));
+    
+    if (object-&gt;structure(vm)-&gt;masqueradesAsUndefined(globalObject))
+        return false;
+    if (object-&gt;type() == JSFunctionType)
+        return false;
+    if (object-&gt;inlineTypeFlags() &amp; TypeOfShouldCallGetCallData) {
+        CallData callData;
+        if (object-&gt;methodTable(vm)-&gt;getCallData(object, callData) != CallTypeNone)
+            return false;
+    }
+    
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-size_t JIT_OPERATION operationIsFunction(EncodedJSValue value)
</del><ins>+size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
</ins><span class="cx"> {
</span><del>-    return jsIsFunctionType(JSValue::decode(value));
</del><ins>+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+
+    ASSERT(jsDynamicCast&lt;JSObject*&gt;(object));
+    
+    if (object-&gt;structure(vm)-&gt;masqueradesAsUndefined(globalObject))
+        return false;
+    if (object-&gt;type() == JSFunctionType)
+        return true;
+    if (object-&gt;inlineTypeFlags() &amp; TypeOfShouldCallGetCallData) {
+        CallData callData;
+        if (object-&gt;methodTable(vm)-&gt;getCallData(object, callData) != CallTypeNone)
+            return true;
+    }
+    
+    return false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSCell* JIT_OPERATION operationTypeOf(ExecState* exec, JSCell* value)
</del><ins>+JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><del>-    return jsTypeStringForValue(exec, JSValue(value)).asCell();
</del><ins>+
+    ASSERT(jsDynamicCast&lt;JSObject*&gt;(object));
+    
+    if (object-&gt;structure(vm)-&gt;masqueradesAsUndefined(globalObject))
+        return vm.smallStrings.undefinedString();
+    if (object-&gt;type() == JSFunctionType)
+        return vm.smallStrings.functionString();
+    if (object-&gt;inlineTypeFlags() &amp; TypeOfShouldCallGetCallData) {
+        CallData callData;
+        if (object-&gt;methodTable(vm)-&gt;getCallData(object, callData) != CallTypeNone)
+            return vm.smallStrings.functionString();
+    }
+    
+    return vm.smallStrings.objectString();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+
+    ASSERT(jsDynamicCast&lt;JSObject*&gt;(object));
+    
+    if (object-&gt;structure(vm)-&gt;masqueradesAsUndefined(globalObject))
+        return static_cast&lt;int32_t&gt;(TypeofType::Undefined);
+    if (object-&gt;type() == JSFunctionType)
+        return static_cast&lt;int32_t&gt;(TypeofType::Function);
+    if (object-&gt;inlineTypeFlags() &amp; TypeOfShouldCallGetCallData) {
+        CallData callData;
+        if (object-&gt;methodTable(vm)-&gt;getCallData(object, callData) != CallTypeNone)
+            return static_cast&lt;int32_t&gt;(TypeofType::Function);
+    }
+    
+    return static_cast&lt;int32_t&gt;(TypeofType::Object);
+}
+
</ins><span class="cx"> char* JIT_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -103,9 +103,10 @@
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount);
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee);
</span><span class="cx"> double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
</span><del>-size_t JIT_OPERATION operationIsObjectOrNull(ExecState*, EncodedJSValue) WTF_INTERNAL;
-size_t JIT_OPERATION operationIsFunction(EncodedJSValue) WTF_INTERNAL;
-JSCell* JIT_OPERATION operationTypeOf(ExecState*, JSCell*) WTF_INTERNAL;
</del><ins>+size_t JIT_OPERATION operationObjectIsObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
+size_t JIT_OPERATION operationObjectIsFunction(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationTypeOfObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
+int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
</ins><span class="cx"> char* JIT_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationAllocatePropertyStorage(ExecState*, size_t newSize) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState*, JSObject*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -4815,6 +4815,118 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileIsObjectOrNull(Node* node)
+{
+    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node-&gt;origin.semantic);
+    
+    JSValueOperand value(this, node-&gt;child1());
+    JSValueRegs valueRegs = value.jsValueRegs();
+    
+    GPRTemporary result(this);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::Jump isCell = m_jit.branchIfCell(valueRegs);
+    
+    JITCompiler::Jump isNull = m_jit.branchIfEqual(valueRegs, jsNull());
+    JITCompiler::Jump isNonNullNonCell = m_jit.jump();
+    
+    isCell.link(&amp;m_jit);
+    JITCompiler::Jump isFunction = m_jit.branchIfFunction(valueRegs.payloadGPR());
+    JITCompiler::Jump notObject = m_jit.branchIfNotObject(valueRegs.payloadGPR());
+    
+    JITCompiler::Jump slowPath = m_jit.branchTest8(
+        JITCompiler::NonZero,
+        JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoFlagsOffset()),
+        TrustedImm32(MasqueradesAsUndefined | TypeOfShouldCallGetCallData));
+    
+    isNull.link(&amp;m_jit);
+    m_jit.move(TrustedImm32(1), resultGPR);
+    JITCompiler::Jump done = m_jit.jump();
+    
+    isNonNullNonCell.link(&amp;m_jit);
+    isFunction.link(&amp;m_jit);
+    notObject.link(&amp;m_jit);
+    m_jit.move(TrustedImm32(0), resultGPR);
+    
+    addSlowPathGenerator(
+        slowPathCall(
+            slowPath, this, operationObjectIsObject, resultGPR, globalObject,
+            valueRegs.payloadGPR()));
+    
+    done.link(&amp;m_jit);
+    
+    unblessedBooleanResult(resultGPR, node);
+}
+
+void SpeculativeJIT::compileIsFunction(Node* node)
+{
+    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node-&gt;origin.semantic);
+    
+    JSValueOperand value(this, node-&gt;child1());
+    JSValueRegs valueRegs = value.jsValueRegs();
+    
+    GPRTemporary result(this);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::Jump notCell = m_jit.branchIfNotCell(valueRegs);
+    JITCompiler::Jump isFunction = m_jit.branchIfFunction(valueRegs.payloadGPR());
+    JITCompiler::Jump notObject = m_jit.branchIfNotObject(valueRegs.payloadGPR());
+    
+    JITCompiler::Jump slowPath = m_jit.branchTest8(
+        JITCompiler::NonZero,
+        JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoFlagsOffset()),
+        TrustedImm32(MasqueradesAsUndefined | TypeOfShouldCallGetCallData));
+    
+    notCell.link(&amp;m_jit);
+    notObject.link(&amp;m_jit);
+    m_jit.move(TrustedImm32(0), resultGPR);
+    JITCompiler::Jump done = m_jit.jump();
+    
+    isFunction.link(&amp;m_jit);
+    m_jit.move(TrustedImm32(1), resultGPR);
+    
+    addSlowPathGenerator(
+        slowPathCall(
+            slowPath, this, operationObjectIsFunction, resultGPR, globalObject,
+            valueRegs.payloadGPR()));
+    
+    done.link(&amp;m_jit);
+    
+    unblessedBooleanResult(resultGPR, node);
+}
+
+void SpeculativeJIT::compileTypeOf(Node* node)
+{
+    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node-&gt;origin.semantic);
+    
+    JSValueOperand value(this, node-&gt;child1());
+    JSValueRegs valueRegs = value.jsValueRegs();
+    
+    GPRTemporary result(this);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::JumpList done;
+    JITCompiler::Jump slowPath;
+    m_jit.emitTypeOf(
+        valueRegs, resultGPR,
+        [&amp;] (TypeofType type, bool fallsThrough) {
+            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.typeString(type)), resultGPR);
+            if (!fallsThrough)
+                done.append(m_jit.jump());
+        },
+        [&amp;] (JITCompiler::Jump theSlowPath) {
+            slowPath = theSlowPath;
+        });
+    done.link(&amp;m_jit);
+
+    addSlowPathGenerator(
+        slowPathCall(
+            slowPath, this, operationTypeOfObject, resultGPR, globalObject,
+            valueRegs.payloadGPR()));
+    
+    cellResult(resultGPR, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
</span><span class="cx"> {
</span><span class="cx">     if (node-&gt;transition()-&gt;previous-&gt;couldHaveIndexingHeader()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -792,13 +792,7 @@
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         jsValueResult(reg, node, DataFormatJSBoolean, mode);
</span><span class="cx"> #else
</span><del>-        if (mode == CallUseChildren)
-            useChildren(node);
-
-        VirtualRegister virtualRegister = node-&gt;virtualRegister();
-        m_gprs.retain(reg, virtualRegister, SpillOrderBoolean);
-        GenerationInfo&amp; info = generationInfoFromVirtualRegister(virtualRegister);
-        info.initBoolean(node, node-&gt;refCount(), reg);
</del><ins>+        booleanResult(reg, node, mode);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     void unblessedBooleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
</span><span class="lines">@@ -1060,6 +1054,18 @@
</span><span class="cx">         return appendCallWithExceptionCheckSetResult(operation, result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    JITCompiler::Call callOperation(S_JITOperation_EGC operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+
+    JITCompiler::Call callOperation(C_JITOperation_EGC operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+
</ins><span class="cx">     JITCompiler::Call callOperation(Jss_JITOperation_EZ operation, GPRReg result, GPRReg arg1)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1);
</span><span class="lines">@@ -2214,6 +2220,9 @@
</span><span class="cx">     void compileCreateClonedArguments(Node*);
</span><span class="cx">     void compileNotifyWrite(Node*);
</span><span class="cx">     bool compileRegExpExec(Node*);
</span><ins>+    void compileIsObjectOrNull(Node*);
+    void compileIsFunction(Node*);
+    void compileTypeOf(Node*);
</ins><span class="cx">     
</span><span class="cx">     void moveTrueTo(GPRReg);
</span><span class="cx">     void moveFalseTo(GPRReg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -4107,86 +4107,16 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case IsObjectOrNull: {
</span><del>-        JSValueOperand value(this, node-&gt;child1());
-        GPRReg valueTagGPR = value.tagGPR();
-        GPRReg valuePayloadGPR = value.payloadGPR();
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-        flushRegisters();
-        callOperation(operationIsObjectOrNull, resultGPR, valueTagGPR, valuePayloadGPR);
-        booleanResult(result.gpr(), node);
</del><ins>+        compileIsObjectOrNull(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case IsFunction: {
</span><del>-        JSValueOperand value(this, node-&gt;child1());
-        GPRReg valueTagGPR = value.tagGPR();
-        GPRReg valuePayloadGPR = value.payloadGPR();
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-        flushRegisters();
-        callOperation(operationIsFunction, resultGPR, valueTagGPR, valuePayloadGPR);
-        booleanResult(result.gpr(), node);
</del><ins>+        compileIsFunction(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     case TypeOf: {
</span><del>-        JSValueOperand value(this, node-&gt;child1(), ManualOperandSpeculation);
-        GPRReg tagGPR = value.tagGPR();
-        GPRReg payloadGPR = value.payloadGPR();
-        GPRTemporary temp(this);
-        GPRReg tempGPR = temp.gpr();
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-        JITCompiler::JumpList doneJumps;
-
-        flushRegisters();
-
-        ASSERT(node-&gt;child1().useKind() == UntypedUse || node-&gt;child1().useKind() == CellUse || node-&gt;child1().useKind() == StringUse);
-
-        JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(value.jsValueRegs());
-        if (node-&gt;child1().useKind() != UntypedUse)
-            DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node-&gt;child1(), SpecCell, isNotCell);
-
-        if (!node-&gt;child1()-&gt;shouldSpeculateObject() || node-&gt;child1().useKind() == StringUse) {
-            JITCompiler::Jump notString = m_jit.branchIfNotString(payloadGPR);
-            if (node-&gt;child1().useKind() == StringUse)
-                DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node-&gt;child1(), SpecString, notString);
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.stringString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            if (node-&gt;child1().useKind() != StringUse) {
-                notString.link(&amp;m_jit);
-                callOperation(operationTypeOf, resultGPR, payloadGPR);
-                doneJumps.append(m_jit.jump());
-            }
-        } else {
-            callOperation(operationTypeOf, resultGPR, payloadGPR);
-            doneJumps.append(m_jit.jump());
-        }
-
-        if (node-&gt;child1().useKind() == UntypedUse) {
-            isNotCell.link(&amp;m_jit);
-
-            m_jit.add32(TrustedImm32(1), tagGPR, tempGPR);
-            JITCompiler::Jump notNumber = m_jit.branch32(JITCompiler::AboveOrEqual, tempGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1));
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.numberString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            notNumber.link(&amp;m_jit);
-
-            JITCompiler::Jump notUndefined = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::UndefinedTag));
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.undefinedString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            notUndefined.link(&amp;m_jit);
-
-            JITCompiler::Jump notNull = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::NullTag));
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.objectString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            notNull.link(&amp;m_jit);
-
-            // Only boolean left
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.booleanString()), resultGPR);
-        }
-        doneJumps.link(&amp;m_jit);
-        cellResult(resultGPR, node);
</del><ins>+        compileTypeOf(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -4148,82 +4148,17 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case IsObjectOrNull: {
</span><del>-        JSValueOperand value(this, node-&gt;child1());
-        GPRReg valueGPR = value.gpr();
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-        flushRegisters();
-        callOperation(operationIsObjectOrNull, resultGPR, valueGPR);
-        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
-        jsValueResult(result.gpr(), node, DataFormatJSBoolean);
</del><ins>+        compileIsObjectOrNull(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case IsFunction: {
</span><del>-        JSValueOperand value(this, node-&gt;child1());
-        GPRReg valueGPR = value.gpr();
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-        flushRegisters();
-        callOperation(operationIsFunction, resultGPR, valueGPR);
-        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
-        jsValueResult(result.gpr(), node, DataFormatJSBoolean);
</del><ins>+        compileIsFunction(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case TypeOf: {
</span><del>-        JSValueOperand value(this, node-&gt;child1(), ManualOperandSpeculation);
-        GPRReg valueGPR = value.gpr();
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-        JITCompiler::JumpList doneJumps;
-
-        flushRegisters();
-        
-        ASSERT(node-&gt;child1().useKind() == UntypedUse || node-&gt;child1().useKind() == CellUse || node-&gt;child1().useKind() == StringUse);
-
-        JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
-        if (node-&gt;child1().useKind() != UntypedUse)
-            DFG_TYPE_CHECK(JSValueSource(valueGPR), node-&gt;child1(), SpecCell, isNotCell);
-
-        if (!node-&gt;child1()-&gt;shouldSpeculateObject() || node-&gt;child1().useKind() == StringUse) {
-            JITCompiler::Jump notString = m_jit.branchIfNotString(valueGPR);
-            if (node-&gt;child1().useKind() == StringUse)
-                DFG_TYPE_CHECK(JSValueSource(valueGPR), node-&gt;child1(), SpecString, notString);
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.stringString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            if (node-&gt;child1().useKind() != StringUse) {
-                notString.link(&amp;m_jit);
-                callOperation(operationTypeOf, resultGPR, valueGPR);
-                doneJumps.append(m_jit.jump());
-            }
-        } else {
-            callOperation(operationTypeOf, resultGPR, valueGPR);
-            doneJumps.append(m_jit.jump());
-        }
-
-        if (node-&gt;child1().useKind() == UntypedUse) {
-            isNotCell.link(&amp;m_jit);
-            JITCompiler::Jump notNumber = m_jit.branchTest64(JITCompiler::Zero, valueGPR, GPRInfo::tagTypeNumberRegister);
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.numberString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            notNumber.link(&amp;m_jit);
-
-            JITCompiler::Jump notUndefined = m_jit.branch64(JITCompiler::NotEqual, valueGPR, JITCompiler::TrustedImm64(ValueUndefined));
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.undefinedString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            notUndefined.link(&amp;m_jit);
-
-            JITCompiler::Jump notNull = m_jit.branch64(JITCompiler::NotEqual, valueGPR, JITCompiler::TrustedImm64(ValueNull));
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.objectString()), resultGPR);
-            doneJumps.append(m_jit.jump());
-            notNull.link(&amp;m_jit);
-
-            // Only boolean left
-            m_jit.move(TrustedImmPtr(m_jit.vm()-&gt;smallStrings.booleanString()), resultGPR);
-        }
-        doneJumps.link(&amp;m_jit);
-        cellResult(resultGPR, node);
</del><ins>+        compileTypeOf(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -189,6 +189,7 @@
</span><span class="cx">     case GetMyArgumentByVal:
</span><span class="cx">     case ForwardVarargs:
</span><span class="cx">     case Switch:
</span><ins>+    case TypeOf:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><span class="cx">     case Identity:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLIntrinsicRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -60,6 +60,7 @@
</span><span class="cx">     macro(C_JITOperation_EC, functionType(intPtr, intPtr, intPtr)) \
</span><span class="cx">     macro(C_JITOperation_ECZ, functionType(intPtr, intPtr, intPtr, int32)) \
</span><span class="cx">     macro(C_JITOperation_ECZC, functionType(intPtr, intPtr, intPtr, int32, intPtr)) \
</span><ins>+    macro(C_JITOperation_EGC, functionType(intPtr, intPtr, intPtr, intPtr)) \
</ins><span class="cx">     macro(C_JITOperation_EJ, functionType(intPtr, intPtr, int64)) \
</span><span class="cx">     macro(C_JITOperation_EJssJss, functionType(intPtr, intPtr, intPtr, intPtr)) \
</span><span class="cx">     macro(C_JITOperation_EJssJssJss, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
</span><span class="lines">@@ -97,6 +98,7 @@
</span><span class="cx">     macro(P_JITOperation_EStZ, functionType(intPtr, intPtr, intPtr, int32)) \
</span><span class="cx">     macro(Q_JITOperation_D, functionType(int64, doubleType)) \
</span><span class="cx">     macro(Q_JITOperation_J, functionType(int64, int64)) \
</span><ins>+    macro(S_JITOperation_EGC, functionType(intPtr, intPtr, intPtr, intPtr)) \
</ins><span class="cx">     macro(S_JITOperation_EJ, functionType(intPtr, intPtr, int64)) \
</span><span class="cx">     macro(S_JITOperation_EJJ, functionType(intPtr, intPtr, int64, int64)) \
</span><span class="cx">     macro(S_JITOperation_J, functionType(intPtr, int64)) \
</span><span class="lines">@@ -112,6 +114,7 @@
</span><span class="cx">     macro(V_JITOperation_Z, functionType(voidType, int32)) \
</span><span class="cx">     macro(Z_JITOperation_D, functionType(int32, doubleType)) \
</span><span class="cx">     macro(Z_JITOperation_EC, functionType(int32, intPtr, intPtr)) \
</span><ins>+    macro(Z_JITOperation_EGC, functionType(int32, intPtr, intPtr, intPtr)) \
</ins><span class="cx">     macro(Z_JITOperation_EJZ, functionType(int32, intPtr, int64, int32)) \
</span><span class="cx">     macro(Z_JITOperation_ESJss, functionType(int32, intPtr, intPtr, int64)) \
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -796,6 +796,9 @@
</span><span class="cx">         case IsFunction:
</span><span class="cx">             compileIsFunction();
</span><span class="cx">             break;
</span><ins>+        case TypeOf:
+            compileTypeOf();
+            break;
</ins><span class="cx">         case CheckHasInstance:
</span><span class="cx">             compileCheckHasInstance();
</span><span class="cx">             break;
</span><span class="lines">@@ -4623,18 +4626,119 @@
</span><span class="cx"> 
</span><span class="cx">     void compileIsObjectOrNull()
</span><span class="cx">     {
</span><del>-        LValue pointerResult = vmCall(
-            m_out.operation(operationIsObjectOrNull), m_callFrame, lowJSValue(m_node-&gt;child1()));
-        setBoolean(m_out.notNull(pointerResult));
</del><ins>+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node-&gt;origin.semantic);
+        
+        Edge child = m_node-&gt;child1();
+        LValue value = lowJSValue(child);
+        
+        LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;IsObjectOrNull cell case&quot;));
+        LBasicBlock notFunctionCase = FTL_NEW_BLOCK(m_out, (&quot;IsObjectOrNull not function case&quot;));
+        LBasicBlock objectCase = FTL_NEW_BLOCK(m_out, (&quot;IsObjectOrNull object case&quot;));
+        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;IsObjectOrNull slow path&quot;));
+        LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, (&quot;IsObjectOrNull not cell case&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;IsObjectOrNull continuation&quot;));
+        
+        m_out.branch(isCell(value, provenType(child)), unsure(cellCase), unsure(notCellCase));
+        
+        LBasicBlock lastNext = m_out.appendTo(cellCase, notFunctionCase);
+        ValueFromBlock isFunctionResult = m_out.anchor(m_out.booleanFalse);
+        m_out.branch(
+            isFunction(value, provenType(child)),
+            unsure(continuation), unsure(notFunctionCase));
+        
+        m_out.appendTo(notFunctionCase, objectCase);
+        ValueFromBlock notObjectResult = m_out.anchor(m_out.booleanFalse);
+        m_out.branch(
+            isObject(value, provenType(child)),
+            unsure(objectCase), unsure(continuation));
+        
+        m_out.appendTo(objectCase, slowPath);
+        ValueFromBlock objectResult = m_out.anchor(m_out.booleanTrue);
+        m_out.branch(
+            isExoticForTypeof(value, provenType(child)),
+            rarely(slowPath), usually(continuation));
+        
+        m_out.appendTo(slowPath, notCellCase);
+        LValue slowResultValue = vmCall(
+            m_out.operation(operationObjectIsObject), m_callFrame, weakPointer(globalObject),
+            value);
+        ValueFromBlock slowResult = m_out.anchor(m_out.notNull(slowResultValue));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(notCellCase, continuation);
+        LValue notCellResultValue = m_out.equal(value, m_out.constInt64(JSValue::encode(jsNull())));
+        ValueFromBlock notCellResult = m_out.anchor(notCellResultValue);
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        LValue result = m_out.phi(
+            m_out.boolean,
+            isFunctionResult, notObjectResult, objectResult, slowResult, notCellResult);
+        setBoolean(result);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileIsFunction()
</span><span class="cx">     {
</span><del>-        LValue pointerResult = vmCall(
-            m_out.operation(operationIsFunction), lowJSValue(m_node-&gt;child1()));
-        setBoolean(m_out.notNull(pointerResult));
</del><ins>+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node-&gt;origin.semantic);
+        
+        Edge child = m_node-&gt;child1();
+        LValue value = lowJSValue(child);
+        
+        LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;IsFunction cell case&quot;));
+        LBasicBlock notFunctionCase = FTL_NEW_BLOCK(m_out, (&quot;IsFunction not function case&quot;));
+        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;IsFunction slow path&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;IsFunction continuation&quot;));
+        
+        ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
+        m_out.branch(
+            isCell(value, provenType(child)), unsure(cellCase), unsure(continuation));
+        
+        LBasicBlock lastNext = m_out.appendTo(cellCase, notFunctionCase);
+        ValueFromBlock functionResult = m_out.anchor(m_out.booleanTrue);
+        m_out.branch(
+            isFunction(value, provenType(child)),
+            unsure(continuation), unsure(notFunctionCase));
+        
+        m_out.appendTo(notFunctionCase, slowPath);
+        ValueFromBlock objectResult = m_out.anchor(m_out.booleanFalse);
+        m_out.branch(
+            isExoticForTypeof(value, provenType(child)),
+            rarely(slowPath), usually(continuation));
+        
+        m_out.appendTo(slowPath, continuation);
+        LValue slowResultValue = vmCall(
+            m_out.operation(operationObjectIsFunction), m_callFrame, weakPointer(globalObject),
+            value);
+        ValueFromBlock slowResult = m_out.anchor(m_out.notNull(slowResultValue));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        LValue result = m_out.phi(
+            m_out.boolean, notCellResult, functionResult, objectResult, slowResult);
+        setBoolean(result);
</ins><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileTypeOf()
+    {
+        Edge child = m_node-&gt;child1();
+        LValue value = lowJSValue(child);
+        
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;TypeOf continuation&quot;));
+        LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
+        
+        Vector&lt;ValueFromBlock&gt; results;
+        
+        buildTypeOf(
+            child, value,
+            [&amp;] (TypeofType type) {
+                results.append(m_out.anchor(weakPointer(vm().smallStrings.typeString(type))));
+                m_out.jump(continuation);
+            });
+        
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(m_out.int64, results));
+    }
+    
</ins><span class="cx">     void compileIn()
</span><span class="cx">     {
</span><span class="cx">         Edge base = m_node-&gt;child2();
</span><span class="lines">@@ -6356,6 +6460,143 @@
</span><span class="cx">             Weight(data-&gt;fallThrough.count));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // Calls the functor at the point of code generation where we know what the result type is.
+    // You can emit whatever code you like at that point. Expects you to terminate the basic block.
+    // When buildTypeOf() returns, it will have terminated all basic blocks that it created. So, if
+    // you aren't using this as the terminator of a high-level block, you should create your own
+    // contination and set it as the nextBlock (m_out.insertNewBlocksBefore(continuation)) before
+    // calling this. For example:
+    //
+    // LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;My continuation&quot;));
+    // LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
+    // buildTypeOf(
+    //     child, value,
+    //     [&amp;] (TypeofType type) {
+    //          do things;
+    //          m_out.jump(continuation);
+    //     });
+    // m_out.appendTo(continuation, lastNext);
+    template&lt;typename Functor&gt;
+    void buildTypeOf(Edge child, LValue value, const Functor&amp; functor)
+    {
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node-&gt;origin.semantic);
+        
+        // Implements the following branching structure:
+        //
+        // if (is cell) {
+        //     if (is object) {
+        //         if (is function) {
+        //             return function;
+        //         } else if (doesn't have call trap and doesn't masquerade as undefined) {
+        //             return object
+        //         } else {
+        //             return slowPath();
+        //         }
+        //     } else if (is string) {
+        //         return string
+        //     } else {
+        //         return symbol
+        //     }
+        // } else if (is number) {
+        //     return number
+        // } else if (is null) {
+        //     return object
+        // } else if (is boolean) {
+        //     return boolean
+        // } else {
+        //     return undefined
+        // }
+        
+        LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf cell case&quot;));
+        LBasicBlock objectCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf object case&quot;));
+        LBasicBlock functionCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf function case&quot;));
+        LBasicBlock notFunctionCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf not function case&quot;));
+        LBasicBlock reallyObjectCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf really object case&quot;));
+        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf slow path&quot;));
+        LBasicBlock unreachable = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf unreachable&quot;));
+        LBasicBlock notObjectCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf not object case&quot;));
+        LBasicBlock stringCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf string case&quot;));
+        LBasicBlock symbolCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf symbol case&quot;));
+        LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf not cell case&quot;));
+        LBasicBlock numberCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf number case&quot;));
+        LBasicBlock notNumberCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf not number case&quot;));
+        LBasicBlock notNullCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf not null case&quot;));
+        LBasicBlock booleanCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf boolean case&quot;));
+        LBasicBlock undefinedCase = FTL_NEW_BLOCK(m_out, (&quot;buildTypeOf undefined case&quot;));
+        
+        m_out.branch(isCell(value, provenType(child)), unsure(cellCase), unsure(notCellCase));
+        
+        LBasicBlock lastNext = m_out.appendTo(cellCase, objectCase);
+        m_out.branch(isObject(value, provenType(child)), unsure(objectCase), unsure(notObjectCase));
+        
+        m_out.appendTo(objectCase, functionCase);
+        m_out.branch(
+            isFunction(value, provenType(child) &amp; SpecObject),
+            unsure(functionCase), unsure(notFunctionCase));
+        
+        m_out.appendTo(functionCase, notFunctionCase);
+        functor(TypeofType::Function);
+        
+        m_out.appendTo(notFunctionCase, reallyObjectCase);
+        m_out.branch(
+            isExoticForTypeof(value, provenType(child) &amp; (SpecObject - SpecFunction)),
+            rarely(slowPath), usually(reallyObjectCase));
+        
+        m_out.appendTo(reallyObjectCase, slowPath);
+        functor(TypeofType::Object);
+        
+        m_out.appendTo(slowPath, unreachable);
+        LValue result = vmCall(
+            m_out.operation(operationTypeOfObjectAsTypeofType), m_callFrame,
+            weakPointer(globalObject), value);
+        Vector&lt;SwitchCase, 3&gt; cases;
+        cases.append(SwitchCase(m_out.constInt32(static_cast&lt;int32_t&gt;(TypeofType::Undefined)), undefinedCase));
+        cases.append(SwitchCase(m_out.constInt32(static_cast&lt;int32_t&gt;(TypeofType::Object)), reallyObjectCase));
+        cases.append(SwitchCase(m_out.constInt32(static_cast&lt;int32_t&gt;(TypeofType::Function)), functionCase));
+        m_out.switchInstruction(result, cases, unreachable, Weight());
+        
+        m_out.appendTo(unreachable, notObjectCase);
+        m_out.unreachable();
+        
+        m_out.appendTo(notObjectCase, stringCase);
+        m_out.branch(
+            isString(value, provenType(child) &amp; (SpecCell - SpecObject)),
+            unsure(stringCase), unsure(symbolCase));
+        
+        m_out.appendTo(stringCase, symbolCase);
+        functor(TypeofType::String);
+        
+        m_out.appendTo(symbolCase, notCellCase);
+        functor(TypeofType::Symbol);
+        
+        m_out.appendTo(notCellCase, numberCase);
+        m_out.branch(
+            isNumber(value, provenType(child) &amp; ~SpecCell),
+            unsure(numberCase), unsure(notNumberCase));
+        
+        m_out.appendTo(numberCase, notNumberCase);
+        functor(TypeofType::Number);
+        
+        m_out.appendTo(notNumberCase, notNullCase);
+        LValue isNull;
+        if (provenType(child) &amp; SpecOther)
+            isNull = m_out.equal(value, m_out.constInt64(ValueNull));
+        else
+            isNull = m_out.booleanFalse;
+        m_out.branch(isNull, unsure(reallyObjectCase), unsure(notNullCase));
+        
+        m_out.appendTo(notNullCase, booleanCase);
+        m_out.branch(
+            isBoolean(value, provenType(child) &amp; ~(SpecCell | SpecFullNumber)),
+            unsure(booleanCase), unsure(undefinedCase));
+        
+        m_out.appendTo(booleanCase, undefinedCase);
+        functor(TypeofType::Boolean);
+        
+        m_out.appendTo(undefinedCase, lastNext);
+        functor(TypeofType::Undefined);
+    }
+    
</ins><span class="cx">     LValue doubleToInt32(LValue doubleValue, double low, double high, bool isSigned = true)
</span><span class="cx">     {
</span><span class="cx">         LBasicBlock greatEnough = FTL_NEW_BLOCK(m_out, (&quot;doubleToInt32 greatEnough&quot;));
</span><span class="lines">@@ -7177,6 +7418,15 @@
</span><span class="cx">             return proven;
</span><span class="cx">         return isNotType(cell, JSFunctionType);
</span><span class="cx">     }
</span><ins>+            
+    LValue isExoticForTypeof(LValue cell, SpeculatedType type = SpecFullTop)
+    {
+        if (!(type &amp; SpecObjectOther))
+            return m_out.booleanFalse;
+        return m_out.testNonZero8(
+            m_out.load8(cell, m_heaps.JSCell_typeInfoFlags),
+            m_out.constInt8(MasqueradesAsUndefined | TypeOfShouldCallGetCallData));
+    }
</ins><span class="cx">     
</span><span class="cx">     LValue isType(LValue cell, JSType type)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLSwitchCaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLSwitchCase.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLSwitchCase.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/ftl/FTLSwitchCase.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    SwitchCase(LValue value, LBasicBlock target, Weight weight)
</del><ins>+    SwitchCase(LValue value, LBasicBlock target, Weight weight = Weight())
</ins><span class="cx">         : m_value(value)
</span><span class="cx">         , m_target(target)
</span><span class="cx">         , m_weight(weight)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><span class="cx"> #include &quot;JITCode.h&quot;
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><ins>+#include &quot;TypeofType.h&quot;
</ins><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -367,6 +368,36 @@
</span><span class="cx">         storePtr(tag, Address(stackPointerRegister, entry * static_cast&lt;ptrdiff_t&gt;(sizeof(Register)) - prologueStackPointerDelta() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><ins>+    
+    JumpList branchIfNotEqual(JSValueRegs regs, JSValue value)
+    {
+#if USE(JSVALUE64)
+        return branch64(NotEqual, regs.gpr(), TrustedImm64(JSValue::encode(value)));
+#else
+        JumpList result;
+        result.append(branch32(NotEqual, regs.tagGPR(), TrustedImm32(value.tag())));
+        if (value.isEmpty() || value.isUndefinedOrNull())
+            return result; // These don't have anything interesting in the payload.
+        result.append(branch32(NotEqual, regs.payloadGPR(), TrustedImm32(value.payload())));
+        return result;
+#endif
+    }
+    
+    Jump branchIfEqual(JSValueRegs regs, JSValue value)
+    {
+#if USE(JSVALUE64)
+        return branch64(Equal, regs.gpr(), TrustedImm64(JSValue::encode(value)));
+#else
+        Jump notEqual;
+        // These don't have anything interesting in the payload.
+        if (!value.isEmpty() &amp;&amp; !value.isUndefinedOrNull())
+            notEqual = branch32(NotEqual, regs.payloadGPR(), TrustedImm32(value.payload()));
+        Jump result = branch32(Equal, regs.tagGPR(), TrustedImm32(value.tag()));
+        if (notEqual.isSet())
+            notEqual.link(this);
+        return result;
+#endif
+    }
</ins><span class="cx"> 
</span><span class="cx">     Jump branchIfNotCell(GPRReg reg)
</span><span class="cx">     {
</span><span class="lines">@@ -426,6 +457,56 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // Note that the tempGPR is not used in 64-bit mode.
+    Jump branchIfNumber(JSValueRegs regs, GPRReg tempGPR)
+    {
+#if USE(JSVALUE64)
+        UNUSED_PARAM(tempGPR);
+        return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+#else
+        add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
+        return branch32(Below, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
+#endif
+    }
+    
+    // Note that the tempGPR is not used in 64-bit mode.
+    Jump branchIfNotNumber(JSValueRegs regs, GPRReg tempGPR)
+    {
+#if USE(JSVALUE64)
+        UNUSED_PARAM(tempGPR);
+        return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+#else
+        add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
+        return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
+#endif
+    }
+
+    // Note that the tempGPR is not used in 32-bit mode.
+    Jump branchIfBoolean(JSValueRegs regs, GPRReg tempGPR)
+    {
+#if USE(JSVALUE64)
+        move(regs.gpr(), tempGPR);
+        xor64(TrustedImm32(static_cast&lt;int32_t&gt;(ValueFalse)), tempGPR);
+        return branchTest64(Zero, tempGPR, TrustedImm32(static_cast&lt;int32_t&gt;(~1)));
+#else
+        UNUSED_PARAM(tempGPR);
+        return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::BooleanTag));
+#endif
+    }
+    
+    // Note that the tempGPR is not used in 32-bit mode.
+    Jump branchIfNotBoolean(JSValueRegs regs, GPRReg tempGPR)
+    {
+#if USE(JSVALUE64)
+        move(regs.gpr(), tempGPR);
+        xor64(TrustedImm32(static_cast&lt;int32_t&gt;(ValueFalse)), tempGPR);
+        return branchTest64(NonZero, tempGPR, TrustedImm32(static_cast&lt;int32_t&gt;(~1)));
+#else
+        UNUSED_PARAM(tempGPR);
+        return branch32(NotEqual, regs.tagGPR(), TrustedImm32(JSValue::BooleanTag));
+#endif
+    }
+    
</ins><span class="cx">     Jump branchIfObject(GPRReg cellGPR)
</span><span class="cx">     {
</span><span class="cx">         return branch8(
</span><span class="lines">@@ -707,6 +788,23 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     
</span><ins>+    void boxBooleanPayload(GPRReg boolGPR, GPRReg payloadGPR)
+    {
+#if USE(JSVALUE64)
+        add32(TrustedImm32(ValueFalse), boolGPR, payloadGPR);
+#else
+        move(boolGPR, payloadGPR);
+#endif
+    }
+
+    void boxBoolean(GPRReg boolGPR, JSValueRegs boxedRegs)
+    {
+        boxBooleanPayload(boolGPR, boxedRegs.payloadGPR());
+#if USE(JSVALUE32_64)
+        move(TrustedImm32(JSValue::BooleanTag), boxedRegs.tagGPR());
+#endif
+    }
+    
</ins><span class="cx">     void callExceptionFuzz();
</span><span class="cx">     
</span><span class="cx">     enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck };
</span><span class="lines">@@ -843,7 +941,83 @@
</span><span class="cx">         uint8_t* address = reinterpret_cast&lt;uint8_t*&gt;(cell) + JSCell::gcDataOffset();
</span><span class="cx">         return branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(address));
</span><span class="cx">     }
</span><ins>+    
+    // Emits the branch structure for typeof. The code emitted by this doesn't fall through. The
+    // functor is called at those points where we have pinpointed a type. One way to use this is to
+    // have the functor emit the code to put the type string into an appropriate register and then
+    // jump out. A secondary functor is used for the call trap and masquerades-as-undefined slow
+    // case. It is passed the unlinked jump to the slow case.
+    template&lt;typename Functor, typename SlowPathFunctor&gt;
+    void emitTypeOf(
+        JSValueRegs regs, GPRReg tempGPR, const Functor&amp; functor,
+        const SlowPathFunctor&amp; slowPathFunctor)
+    {
+        // Implements the following branching structure:
+        //
+        // if (is cell) {
+        //     if (is object) {
+        //         if (is function) {
+        //             return function;
+        //         } else if (doesn't have call trap and doesn't masquerade as undefined) {
+        //             return object
+        //         } else {
+        //             return slowPath();
+        //         }
+        //     } else if (is string) {
+        //         return string
+        //     } else {
+        //         return symbol
+        //     }
+        // } else if (is number) {
+        //     return number
+        // } else if (is null) {
+        //     return object
+        // } else if (is boolean) {
+        //     return boolean
+        // } else {
+        //     return undefined
+        // }
+        
+        Jump notCell = branchIfNotCell(regs);
+        
+        GPRReg cellGPR = regs.payloadGPR();
+        Jump notObject = branchIfNotObject(cellGPR);
+        
+        Jump notFunction = branchIfNotFunction(cellGPR);
+        functor(TypeofType::Function, false);
+        
+        notFunction.link(this);
+        slowPathFunctor(
+            branchTest8(
+                NonZero,
+                Address(cellGPR, JSCell::typeInfoFlagsOffset()),
+                TrustedImm32(MasqueradesAsUndefined | TypeOfShouldCallGetCallData)));
+        functor(TypeofType::Object, false);
+        
+        notObject.link(this);
+        
+        Jump notString = branchIfNotString(cellGPR);
+        functor(TypeofType::String, false);
+        notString.link(this);
+        functor(TypeofType::Symbol, false);
+        
+        notCell.link(this);
</ins><span class="cx"> 
</span><ins>+        Jump notNumber = branchIfNotNumber(regs, tempGPR);
+        functor(TypeofType::Number, false);
+        notNumber.link(this);
+        
+        JumpList notNull = branchIfNotEqual(regs, jsNull());
+        functor(TypeofType::Object, false);
+        notNull.link(this);
+        
+        Jump notBoolean = branchIfNotBoolean(regs, tempGPR);
+        functor(TypeofType::Boolean, false);
+        notBoolean.link(this);
+        
+        functor(TypeofType::Undefined, true);
+    }
+
</ins><span class="cx">     Vector&lt;BytecodeAndMachineOffset&gt;&amp; decodedCodeMapFor(CodeBlock*);
</span><span class="cx">     
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx">     D: double
</span><span class="cx">     E: ExecState*
</span><span class="cx">     F: CallFrame*
</span><ins>+    G: JSGlobalObject*
</ins><span class="cx">     I: StringImpl*
</span><span class="cx">     Icf: InlineCallFrame*
</span><span class="cx">     Idc: const Identifier*
</span><span class="lines">@@ -127,6 +128,7 @@
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_ECZC)(ExecState*, JSCell*, int32_t, JSCell*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
</span><ins>+typedef JSCell* JIT_OPERATION (*C_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
</ins><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EIcf)(ExecState*, InlineCallFrame*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJsc)(ExecState*, JSScope*);
</span><span class="lines">@@ -157,10 +159,12 @@
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_D)(double);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_E)(ExecState*);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_EC)(ExecState*, JSCell*);
</span><ins>+typedef int32_t JIT_OPERATION (*Z_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
</ins><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_ESJss)(ExecState*, size_t, JSString*);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
</span><ins>+typedef size_t JIT_OPERATION (*S_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
</ins><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EOJss)(ExecState*, JSObject*, JSString*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSmallStringsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SmallStrings.h (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SmallStrings.h        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/runtime/SmallStrings.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008, 2009, 2015 Apple Inc. All Rights Reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef SmallStrings_h
</span><span class="cx"> #define SmallStrings_h
</span><span class="cx"> 
</span><ins>+#include &quot;TypeofType.h&quot;
</ins><span class="cx"> #include &quot;WriteBarrier.h&quot;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -85,6 +86,29 @@
</span><span class="cx">     }
</span><span class="cx">     JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ACCESSOR_DEFINITION)
</span><span class="cx"> #undef JSC_COMMON_STRINGS_ACCESSOR_DEFINITION
</span><ins>+    
+    JSString* typeString(TypeofType type) const
+    {
+        switch (type) {
+        case TypeofType::Undefined:
+            return undefinedString();
+        case TypeofType::Boolean:
+            return booleanString();
+        case TypeofType::Number:
+            return numberString();
+        case TypeofType::String:
+            return stringString();
+        case TypeofType::Symbol:
+            return symbolString();
+        case TypeofType::Object:
+            return objectString();
+        case TypeofType::Function:
+            return functionString();
+        }
+        
+        RELEASE_ASSERT_NOT_REACHED();
+        return nullptr;
+    }
</ins><span class="cx"> 
</span><span class="cx">     JSString* nullObjectString() const { return m_nullObjectString; }
</span><span class="cx">     JSString* undefinedObjectString() const { return m_undefinedObjectString; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeTypeofTypecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/TypeofType.cpp (0 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/TypeofType.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/TypeofType.cpp        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -0,0 +1,63 @@
</span><ins>+/*
+ * Copyright (C) 2015 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;TypeofType.h&quot;
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream&amp; out, TypeofType type)
+{
+    switch (type) {
+    case TypeofType::Undefined:
+        out.print(&quot;undefined&quot;);
+        return;
+    case TypeofType::Boolean:
+        out.print(&quot;boolean&quot;);
+        return;
+    case TypeofType::Number:
+        out.print(&quot;number&quot;);
+        return;
+    case TypeofType::String:
+        out.print(&quot;string&quot;);
+        return;
+    case TypeofType::Symbol:
+        out.print(&quot;symbol&quot;);
+        return;
+    case TypeofType::Object:
+        out.print(&quot;object&quot;);
+        return;
+    case TypeofType::Function:
+        out.print(&quot;function&quot;);
+        return;
+    }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeTypeofTypeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/TypeofType.h (0 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/TypeofType.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/TypeofType.h        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef TypeofType_h
+#define TypeofType_h
+
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace JSC {
+
+enum class TypeofType {
+    Undefined,
+    Boolean,
+    Number,
+    String,
+    Symbol,
+    Object,
+    Function    
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+void printInternal(PrintStream&amp; out, JSC::TypeofType);
+
+} // namespace WTF
+
+#endif // TypeofType_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypeoffunctionsandobjectsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/type-of-functions-and-objects.js (183723 => 183724)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/type-of-functions-and-objects.js        2015-05-02 23:06:08 UTC (rev 183723)
+++ trunk/Source/JavaScriptCore/tests/stress/type-of-functions-and-objects.js        2015-05-03 00:15:27 UTC (rev 183724)
</span><span class="lines">@@ -26,48 +26,61 @@
</span><span class="cx"> noInline(baz);
</span><span class="cx"> noInline(fuzz);
</span><span class="cx"> 
</span><del>-function expect(f, v, expected) {
-    var result = f(v);
-    if (result != expected)
-        throw &quot;Error: &quot; + f.name + &quot;(&quot; + v + &quot;) returned &quot; + result + &quot; instead of &quot; + expected;
-}
</del><ins>+function test() {
+    var errors = [];
</ins><span class="cx"> 
</span><del>-function test(v, expected) {
-    switch (expected) {
-    case &quot;function&quot;:
-        expect(foo, v, &quot;function&quot;);
-        expect(bar, v, 2);
-        expect(baz, v, true);
-        expect(fuzz, v, false);
-        break;
-    case &quot;object&quot;:
-        expect(foo, v, &quot;object&quot;);
-        expect(bar, v, 1);
-        expect(baz, v, false);
-        expect(fuzz, v, true);
-        break;
-    case &quot;other&quot;:
-        var result = foo(v);
-        if (result == &quot;object&quot; || result == &quot;function&quot;)
-            throw &quot;Error: foo(&quot; + v + &quot;) returned &quot; + result + &quot; but expected something other than object or function&quot;;
-        expect(bar, v, 3);
-        expect(baz, v, false);
-        expect(fuzz, v, false);
-        break;
-    default:
-        throw &quot;Bad expected case&quot;;
</del><ins>+    function testValue(v, expected) {
+        function expect(f, expected) {
+            var result = f(v);
+            if (result != expected)
+                errors.push(f.name + &quot;(&quot; + v + &quot;) returned &quot; + result + &quot; instead of &quot; + expected);
+        }
+
+        switch (expected) {
+        case &quot;function&quot;:
+            expect(foo, &quot;function&quot;);
+            expect(bar, 2);
+            expect(baz, true);
+            expect(fuzz, false);
+            break;
+        case &quot;object&quot;:
+            expect(foo, &quot;object&quot;);
+            expect(bar, 1);
+            expect(baz, false);
+            expect(fuzz, true);
+            break;
+        case &quot;other&quot;:
+            var result = foo(v);
+            if (result == &quot;object&quot; || result == &quot;function&quot;)
+                errors.push(&quot;foo(&quot; + v + &quot;) returned &quot; + result + &quot; but expected something other than object or function&quot;);
+            expect(bar, 3);
+            expect(baz, false);
+            expect(fuzz, false);
+            break;
+        default:
+            throw &quot;Bad expected case&quot;;
+        }
</ins><span class="cx">     }
</span><ins>+    
+    testValue({}, &quot;object&quot;);
+    testValue(function() { }, &quot;function&quot;);
+    testValue(&quot;hello&quot;, &quot;other&quot;);
+    testValue(42, &quot;other&quot;);
+    testValue(null, &quot;object&quot;);
+    testValue(void 0, &quot;other&quot;);
+    testValue(42.5, &quot;other&quot;);
+    testValue(Map, &quot;function&quot;);
+    testValue(Date, &quot;function&quot;);
+    testValue(Map.prototype, &quot;object&quot;);
+    
+    if (!errors.length)
+        return;
+    
+    for (var i = 0; i &lt; errors.length; ++i)
+        print(&quot;Error: &quot; + errors[i]);
+    throw &quot;Encountered errors during test run.&quot;;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-for (var i = 0; i &lt; 10000; ++i) {
-    test({}, &quot;object&quot;);
-    test(function() { }, &quot;function&quot;);
-    test(&quot;hello&quot;, &quot;other&quot;);
-    test(42, &quot;other&quot;);
-    test(null, &quot;object&quot;);
-    test(void 0, &quot;other&quot;);
-    test(42.5, &quot;other&quot;);
-    test(Map, &quot;function&quot;);
-    test(Date, &quot;function&quot;);
-    test(Map.prototype, &quot;object&quot;);
-}
</del><ins>+for (var i = 0; i &lt; 10000; ++i)
+    test();
+
</ins></span></pre>
</div>
</div>

</body>
</html>