<!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>[187524] 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/187524">187524</a></dd>
<dt>Author</dt> <dd>saambarati1@gmail.com</dd>
<dt>Date</dt> <dd>2015-07-28 15:39:12 -0700 (Tue, 28 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make the type profiler work with lexical scoping and add tests
https://bugs.webkit.org/show_bug.cgi?id=145438

Reviewed by Geoffrey Garen.

op_profile_type now knows how to resolve variables allocated within
the local scope stack. This means it knows how to resolve &quot;let&quot;
and &quot;const&quot; variables. Also, some refactoring was done inside
the BytecodeGenerator to make writing code to support the type
profiler much simpler and clearer.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::symbolTable): Deleted.
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::addExceptionHandler):
(JSC::UnlinkedCodeBlock::exceptionHandler):
(JSC::UnlinkedCodeBlock::vm):
(JSC::UnlinkedCodeBlock::addArrayProfile):
(JSC::UnlinkedCodeBlock::setSymbolTableConstantIndex): Deleted.
(JSC::UnlinkedCodeBlock::symbolTableConstantIndex): Deleted.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitMove):
(JSC::BytecodeGenerator::emitTypeProfilerExpressionInfo):
(JSC::BytecodeGenerator::emitProfileType):
(JSC::BytecodeGenerator::emitProfileControlFlow):
(JSC::BytecodeGenerator::pushLexicalScopeInternal):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitNodeForLeftHandSide):
* bytecompiler/NodesCodegen.cpp:
(JSC::ThisNode::emitBytecode):
(JSC::ResolveNode::emitBytecode):
(JSC::BracketAccessorNode::emitBytecode):
(JSC::DotAccessorNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::FunctionCallBracketNode::emitBytecode):
(JSC::FunctionCallDotNode::emitBytecode):
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
(JSC::PostfixNode::emitResolve):
(JSC::PostfixNode::emitBracket):
(JSC::PostfixNode::emitDot):
(JSC::PrefixNode::emitResolve):
(JSC::PrefixNode::emitBracket):
(JSC::PrefixNode::emitDot):
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::AssignDotNode::emitBytecode):
(JSC::ReadModifyDotNode::emitBytecode):
(JSC::AssignBracketNode::emitBytecode):
(JSC::ReadModifyBracketNode::emitBytecode):
(JSC::EmptyVarExpression::emitBytecode):
(JSC::EmptyLetExpression::emitBytecode):
(JSC::ForInNode::emitLoopHeader):
(JSC::ForOfNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::FunctionNode::emitBytecode):
(JSC::BindingNode::bindValue):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_profile_type):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_profile_type):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* tests/typeProfiler/es6-block-scoping.js: Added.
(noop):
(arr):
(wrapper.changeFoo):
(wrapper.scoping):
(wrapper.scoping2):
(wrapper):
* tests/typeProfiler/es6-classes.js: Added.
(noop):
(wrapper.Animal):
(wrapper.Animal.prototype.methodA):
(wrapper.Dog):
(wrapper.Dog.prototype.methodB):
(wrapper):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</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="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreteststypeProfileres6blockscopingjs">trunk/Source/JavaScriptCore/tests/typeProfiler/es6-block-scoping.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreteststypeProfileres6classesjs">trunk/Source/JavaScriptCore/tests/typeProfiler/es6-classes.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -1,5 +1,93 @@
</span><span class="cx"> 2015-07-28  Saam barati  &lt;saambarati1@gmail.com&gt;
</span><span class="cx"> 
</span><ins>+        Make the type profiler work with lexical scoping and add tests
+        https://bugs.webkit.org/show_bug.cgi?id=145438
+
+        Reviewed by Geoffrey Garen.
+
+        op_profile_type now knows how to resolve variables allocated within
+        the local scope stack. This means it knows how to resolve &quot;let&quot;
+        and &quot;const&quot; variables. Also, some refactoring was done inside
+        the BytecodeGenerator to make writing code to support the type
+        profiler much simpler and clearer.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::symbolTable): Deleted.
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::addExceptionHandler):
+        (JSC::UnlinkedCodeBlock::exceptionHandler):
+        (JSC::UnlinkedCodeBlock::vm):
+        (JSC::UnlinkedCodeBlock::addArrayProfile):
+        (JSC::UnlinkedCodeBlock::setSymbolTableConstantIndex): Deleted.
+        (JSC::UnlinkedCodeBlock::symbolTableConstantIndex): Deleted.
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitMove):
+        (JSC::BytecodeGenerator::emitTypeProfilerExpressionInfo):
+        (JSC::BytecodeGenerator::emitProfileType):
+        (JSC::BytecodeGenerator::emitProfileControlFlow):
+        (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitNodeForLeftHandSide):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ThisNode::emitBytecode):
+        (JSC::ResolveNode::emitBytecode):
+        (JSC::BracketAccessorNode::emitBytecode):
+        (JSC::DotAccessorNode::emitBytecode):
+        (JSC::FunctionCallValueNode::emitBytecode):
+        (JSC::FunctionCallResolveNode::emitBytecode):
+        (JSC::FunctionCallBracketNode::emitBytecode):
+        (JSC::FunctionCallDotNode::emitBytecode):
+        (JSC::CallFunctionCallDotNode::emitBytecode):
+        (JSC::ApplyFunctionCallDotNode::emitBytecode):
+        (JSC::PostfixNode::emitResolve):
+        (JSC::PostfixNode::emitBracket):
+        (JSC::PostfixNode::emitDot):
+        (JSC::PrefixNode::emitResolve):
+        (JSC::PrefixNode::emitBracket):
+        (JSC::PrefixNode::emitDot):
+        (JSC::ReadModifyResolveNode::emitBytecode):
+        (JSC::AssignResolveNode::emitBytecode):
+        (JSC::AssignDotNode::emitBytecode):
+        (JSC::ReadModifyDotNode::emitBytecode):
+        (JSC::AssignBracketNode::emitBytecode):
+        (JSC::ReadModifyBracketNode::emitBytecode):
+        (JSC::EmptyVarExpression::emitBytecode):
+        (JSC::EmptyLetExpression::emitBytecode):
+        (JSC::ForInNode::emitLoopHeader):
+        (JSC::ForOfNode::emitBytecode):
+        (JSC::ReturnNode::emitBytecode):
+        (JSC::FunctionNode::emitBytecode):
+        (JSC::BindingNode::bindValue):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_profile_type):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_profile_type):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * tests/typeProfiler/es6-block-scoping.js: Added.
+        (noop):
+        (arr):
+        (wrapper.changeFoo):
+        (wrapper.scoping):
+        (wrapper.scoping2):
+        (wrapper):
+        * tests/typeProfiler/es6-classes.js: Added.
+        (noop):
+        (wrapper.Animal):
+        (wrapper.Animal.prototype.methodA):
+        (wrapper.Dog):
+        (wrapper.Dog.prototype.methodB):
+        (wrapper):
+
+2015-07-28  Saam barati  &lt;saambarati1@gmail.com&gt;
+
</ins><span class="cx">         Implement catch scope using lexical scoping constructs introduced with &quot;let&quot; scoping patch
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=146979
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -1694,8 +1694,6 @@
</span><span class="cx">     ASSERT(m_heap-&gt;isDeferred());
</span><span class="cx">     ASSERT(m_scopeRegister.isLocal());
</span><span class="cx"> 
</span><del>-    m_symbolTableConstantIndex = other.m_symbolTableConstantIndex;
-
</del><span class="cx">     setNumParameters(other.numParameters());
</span><span class="cx">     optimizeAfterWarmUp();
</span><span class="cx">     jitAfterWarmUp();
</span><span class="lines">@@ -1767,7 +1765,6 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     HashSet&lt;int, WTF::IntHash&lt;int&gt;, WTF::UnsignedWithZeroKeyHashTraits&lt;int&gt;&gt; clonedConstantSymbolTables;
</span><del>-    m_symbolTableConstantIndex = unlinkedCodeBlock-&gt;symbolTableConstantIndex();
</del><span class="cx">     {
</span><span class="cx">         HashSet&lt;SymbolTable*&gt; clonedSymbolTables;
</span><span class="cx">         for (unsigned i = 0; i &lt; m_constantRegisters.size(); i++) {
</span><span class="lines">@@ -2059,17 +2056,16 @@
</span><span class="cx">             VirtualRegister profileRegister(pc[1].u.operand);
</span><span class="cx">             ProfileTypeBytecodeFlag flag = static_cast&lt;ProfileTypeBytecodeFlag&gt;(pc[3].u.operand);
</span><span class="cx">             SymbolTable* symbolTable = nullptr;
</span><del>-            int localScopeDepth = pc[2].u.operand;
</del><span class="cx"> 
</span><span class="cx">             switch (flag) {
</span><del>-            case ProfileTypeBytecodePutToScope:
-            case ProfileTypeBytecodeGetFromScope: {
</del><ins>+            case ProfileTypeBytecodeClosureVar: {
</ins><span class="cx">                 const Identifier&amp; ident = identifier(pc[4].u.operand);
</span><ins>+                int localScopeDepth = pc[2].u.operand;
</ins><span class="cx">                 ResolveType type = static_cast&lt;ResolveType&gt;(pc[5].u.operand);
</span><del>-                ResolveOp op = JSScope::abstractResolve(m_globalObject-&gt;globalExec(), localScopeDepth, scope, ident, (flag == ProfileTypeBytecodeGetFromScope ? Get : Put), type);
</del><ins>+                // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
+                // we're abstractly &quot;read&quot;ing from a JSScope.
+                ResolveOp op = JSScope::abstractResolve(m_globalObject-&gt;globalExec(), localScopeDepth, scope, ident, Get, type);
</ins><span class="cx"> 
</span><del>-                // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
-                // https://bugs.webkit.org/show_bug.cgi?id=135184
</del><span class="cx">                 if (op.type == ClosureVar)
</span><span class="cx">                     symbolTable = op.lexicalEnvironment-&gt;symbolTable();
</span><span class="cx">                 else if (op.type == GlobalVar)
</span><span class="lines">@@ -2086,34 +2082,18 @@
</span><span class="cx"> 
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            case ProfileTypeBytecodePutToLocalScope:
-            case ProfileTypeBytecodeGetFromLocalScope: {
-                if (!m_symbolTableConstantIndex) {
-                    globalVariableID = TypeProfilerNoGlobalIDExists;
-                    break;
-                }
</del><ins>+            case ProfileTypeBytecodeLocallyResolved: {
+                int symbolTableIndex = pc[2].u.operand;
+                RELEASE_ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex));
+                SymbolTable* symbolTable = jsCast&lt;SymbolTable*&gt;(getConstant(symbolTableIndex));
</ins><span class="cx">                 const Identifier&amp; ident = identifier(pc[4].u.operand);
</span><del>-                symbolTable = this-&gt;symbolTable();
</del><span class="cx">                 ConcurrentJITLocker locker(symbolTable-&gt;m_lock);
</span><span class="cx">                 // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
</span><del>-                symbolTable-&gt;prepareForTypeProfiling(locker);
</del><span class="cx">                 globalVariableID = symbolTable-&gt;uniqueIDForVariable(locker, ident.impl(), *vm());
</span><span class="cx">                 globalTypeSet = symbolTable-&gt;globalTypeSetForVariable(locker, ident.impl(), *vm());
</span><span class="cx"> 
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-
-            case ProfileTypeBytecodeHasGlobalID: {
-                if (!m_symbolTableConstantIndex) {
-                    globalVariableID = TypeProfilerNoGlobalIDExists;
-                    break;
-                }
-                symbolTable = this-&gt;symbolTable();
-                ConcurrentJITLocker locker(symbolTable-&gt;m_lock);
-                globalVariableID = symbolTable-&gt;uniqueIDForOffset(locker, VarOffset(profileRegister), *vm());
-                globalTypeSet = symbolTable-&gt;globalTypeSetForOffset(locker, VarOffset(profileRegister), *vm());
-                break;
-            }
</del><span class="cx">             case ProfileTypeBytecodeDoesNotHaveGlobalID: 
</span><span class="cx">             case ProfileTypeBytecodeFunctionArgument: {
</span><span class="cx">                 globalVariableID = TypeProfilerNoGlobalIDExists;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -916,15 +916,6 @@
</span><span class="cx"> private:
</span><span class="cx">     friend class CodeBlockSet;
</span><span class="cx">     
</span><del>-    SymbolTable* symbolTable() const 
-    { 
-        // FIXME: Get rid of this function once the type profiler has a notion of what
-        // symbol table it's reading from.
-        // https://bugs.webkit.org/show_bug.cgi?id=145438
-        RELEASE_ASSERT(m_symbolTableConstantIndex); 
-        return jsCast&lt;SymbolTable*&gt;(getConstant(m_symbolTableConstantIndex));
-    }
-
</del><span class="cx">     CodeBlock* specialOSREntryBlockOrNull();
</span><span class="cx">     
</span><span class="cx">     void noticeIncomingCall(ExecState* callerFrame);
</span><span class="lines">@@ -1006,7 +997,6 @@
</span><span class="cx">     VM* m_vm;
</span><span class="cx"> 
</span><span class="cx">     RefCountedArray&lt;Instruction&gt; m_instructions;
</span><del>-    int m_symbolTableConstantIndex;
</del><span class="cx">     VirtualRegister m_thisRegister;
</span><span class="cx">     VirtualRegister m_scopeRegister;
</span><span class="cx">     VirtualRegister m_lexicalEnvironmentRegister;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -418,9 +418,6 @@
</span><span class="cx">     void addExceptionHandler(const UnlinkedHandlerInfo&amp; handler) { createRareDataIfNecessary(); return m_rareData-&gt;m_exceptionHandlers.append(handler); }
</span><span class="cx">     UnlinkedHandlerInfo&amp; exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData-&gt;m_exceptionHandlers[index]; }
</span><span class="cx"> 
</span><del>-    void setSymbolTableConstantIndex(int index) { m_symbolTableConstantIndex = index; }
-    int symbolTableConstantIndex() const { return m_symbolTableConstantIndex; }
-
</del><span class="cx">     VM* vm() const { return m_vm; }
</span><span class="cx"> 
</span><span class="cx">     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
</span><span class="lines">@@ -563,7 +560,6 @@
</span><span class="cx">     FunctionExpressionVector m_functionExprs;
</span><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;SymbolTable&gt; m_symbolTable;
</span><del>-    int m_symbolTableConstantIndex { 0 };
</del><span class="cx"> 
</span><span class="cx">     Vector&lt;unsigned&gt; m_propertyAccessInstructions;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -207,7 +207,6 @@
</span><span class="cx">     SymbolTable* functionSymbolTable = SymbolTable::create(*m_vm);
</span><span class="cx">     functionSymbolTable-&gt;setUsesNonStrictEval(m_usesNonStrictEval);
</span><span class="cx">     int symbolTableConstantIndex = addConstantValue(functionSymbolTable)-&gt;index();
</span><del>-    m_codeBlock-&gt;setSymbolTableConstantIndex(symbolTableConstantIndex);
</del><span class="cx"> 
</span><span class="cx">     Vector&lt;Identifier&gt; boundParameterProperties;
</span><span class="cx">     FunctionParameters&amp; parameters = *functionNode-&gt;parameters(); 
</span><span class="lines">@@ -1180,9 +1179,6 @@
</span><span class="cx">     instructions().append(dst-&gt;index());
</span><span class="cx">     instructions().append(src-&gt;index());
</span><span class="cx"> 
</span><del>-    if (!dst-&gt;isTemporary() &amp;&amp; vm()-&gt;typeProfiler())
-        emitProfileType(dst, ProfileTypeBytecodeHasGlobalID, nullptr);
-
</del><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1289,26 +1285,87 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::emitTypeProfilerExpressionInfo(const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot)
</span><span class="cx"> {
</span><ins>+    ASSERT(vm()-&gt;typeProfiler());
+
</ins><span class="cx">     unsigned start = startDivot.offset; // Ranges are inclusive of their endpoints, AND 0 indexed.
</span><span class="cx">     unsigned end = endDivot.offset - 1; // End Ranges already go one past the inclusive range, so subtract 1.
</span><span class="cx">     unsigned instructionOffset = instructions().size() - 1;
</span><span class="cx">     m_codeBlock-&gt;addTypeProfilerExpressionInfo(instructionOffset, start, end);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const Identifier* identifier)
</del><ins>+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag)
</ins><span class="cx"> {
</span><del>-    if (flag == ProfileTypeBytecodeGetFromScope || flag == ProfileTypeBytecodePutToScope)
-        RELEASE_ASSERT(identifier);
</del><ins>+    if (!vm()-&gt;typeProfiler())
+        return;
</ins><span class="cx"> 
</span><ins>+    if (!registerToProfile)
+        return;
+
+    emitOpcode(op_profile_type);
+    instructions().append(registerToProfile-&gt;index());
+    instructions().append(0);
+    instructions().append(flag);
+    instructions().append(0);
+    instructions().append(resolveType());
+
+    // Don't emit expression info for this version of profile type. This generally means
+    // we're profiling information for something that isn't in the actual text of a JavaScript
+    // program. For example, implicit return undefined from a function call.
+}
+
+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot)
+{
+    emitProfileType(registerToProfile, ProfileTypeBytecodeDoesNotHaveGlobalID, startDivot, endDivot);
+}
+
+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot)
+{
+    if (!vm()-&gt;typeProfiler())
+        return;
+
+    if (!registerToProfile)
+        return;
+
</ins><span class="cx">     // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
</span><span class="cx">     emitOpcode(op_profile_type);
</span><span class="cx">     instructions().append(registerToProfile-&gt;index());
</span><del>-    instructions().append(localScopeDepth());
</del><ins>+    instructions().append(0);
</ins><span class="cx">     instructions().append(flag);
</span><del>-    instructions().append(identifier ? addConstant(*identifier) : 0);
</del><ins>+    instructions().append(0);
</ins><span class="cx">     instructions().append(resolveType());
</span><ins>+
+    emitTypeProfilerExpressionInfo(startDivot, endDivot);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const Variable&amp; var, const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot)
+{
+    if (!vm()-&gt;typeProfiler())
+        return;
+
+    if (!registerToProfile)
+        return;
+
+    ProfileTypeBytecodeFlag flag;
+    int symbolTableOrScopeDepth;
+    if (var.local() || var.offset().isScope()) {
+        flag = ProfileTypeBytecodeLocallyResolved;
+        symbolTableOrScopeDepth = var.symbolTableConstantIndex();
+    } else {
+        flag = ProfileTypeBytecodeClosureVar;
+        symbolTableOrScopeDepth = localScopeDepth();
+    }
+
+    // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
+    emitOpcode(op_profile_type);
+    instructions().append(registerToProfile-&gt;index());
+    instructions().append(symbolTableOrScopeDepth);
+    instructions().append(flag);
+    instructions().append(addConstant(var.ident()));
+    instructions().append(resolveType());
+
+    emitTypeProfilerExpressionInfo(startDivot, endDivot);
+}
+
</ins><span class="cx"> void BytecodeGenerator::emitProfileControlFlow(int textOffset)
</span><span class="cx"> {
</span><span class="cx">     if (vm()-&gt;controlFlowProfiler()) {
</span><span class="lines">@@ -1408,13 +1465,20 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RegisterID* newScope = nullptr;
</span><ins>+    RegisterID* constantSymbolTable = nullptr;
</ins><span class="cx">     int symbolTableConstantIndex = 0;
</span><ins>+    if (vm()-&gt;typeProfiler()) {
+        constantSymbolTable = addConstantValue(symbolTable.get());
+        symbolTableConstantIndex = constantSymbolTable-&gt;index();
+    }
</ins><span class="cx">     if (hasCapturedVariables) {
</span><span class="cx">         newScope = newBlockScopeVariable();
</span><span class="cx">         newScope-&gt;ref();
</span><del>-
-        RegisterID* constantSymbolTable = addConstantValue(!m_codeBlock-&gt;vm()-&gt;typeProfiler() ? symbolTable-&gt;cloneScopePart(*m_vm) : symbolTable.get());
-        symbolTableConstantIndex = constantSymbolTable-&gt;index();
</del><ins>+        if (!constantSymbolTable) {
+            ASSERT(!vm()-&gt;typeProfiler());
+            constantSymbolTable = addConstantValue(symbolTable-&gt;cloneScopePart(*m_vm));
+            symbolTableConstantIndex = constantSymbolTable-&gt;index();
+        }
</ins><span class="cx">         if (constantSymbolTableResult)
</span><span class="cx">             *constantSymbolTableResult = constantSymbolTable;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -252,11 +252,8 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     enum ProfileTypeBytecodeFlag {
</span><del>-        ProfileTypeBytecodePutToScope,
-        ProfileTypeBytecodeGetFromScope,
-        ProfileTypeBytecodePutToLocalScope,
-        ProfileTypeBytecodeGetFromLocalScope,
-        ProfileTypeBytecodeHasGlobalID,
</del><ins>+        ProfileTypeBytecodeClosureVar,
+        ProfileTypeBytecodeLocallyResolved,
</ins><span class="cx">         ProfileTypeBytecodeDoesNotHaveGlobalID,
</span><span class="cx">         ProfileTypeBytecodeFunctionArgument,
</span><span class="cx">         ProfileTypeBytecodeFunctionReturnStatement
</span><span class="lines">@@ -447,9 +444,19 @@
</span><span class="cx">             return emitNode(n);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+    private:
</ins><span class="cx">         void emitTypeProfilerExpressionInfo(const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot);
</span><del>-        void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const Identifier*);
</del><ins>+    public:
</ins><span class="cx"> 
</span><ins>+        // This doesn't emit expression info. If using this, make sure you shouldn't be emitting text offset.
+        void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag); 
+        // These variables are associated with variables in a program. They could be Locals, LocalClosureVar, or ClosureVar.
+        void emitProfileType(RegisterID* registerToProfile, const Variable&amp;, const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot);
+
+        void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot);
+        // These are not associated with variables and don't have a global id.
+        void emitProfileType(RegisterID* registerToProfile, const JSTextPosition&amp; startDivot, const JSTextPosition&amp; endDivot);
+
</ins><span class="cx">         void emitProfileControlFlow(int);
</span><span class="cx"> 
</span><span class="cx">         RegisterID* emitLoad(RegisterID* dst, bool);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -153,11 +153,8 @@
</span><span class="cx">         return 0;
</span><span class="cx"> 
</span><span class="cx">     RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(generator.thisRegister(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        static const unsigned thisLength = 4;
-        generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + thisLength, -1));
-    }
</del><ins>+    static const unsigned thisLength = 4;
+    generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -209,10 +206,8 @@
</span><span class="cx">         generator.emitTDZCheckIfNecessary(var, local, nullptr);
</span><span class="cx">         if (dst == generator.ignoredResult())
</span><span class="cx">             return nullptr;
</span><del>-        if (generator.vm()-&gt;typeProfiler()) {
-            generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
-            generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
-        }
</del><ins>+
+        generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
</ins><span class="cx">         return generator.moveToDestinationIfNeeded(dst, local);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -222,10 +217,7 @@
</span><span class="cx">     RegisterID* finalDest = generator.finalDestination(dst);
</span><span class="cx">     RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
</span><span class="cx">     generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(finalDest, var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &amp;m_ident);
-        generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
-    }
</del><ins>+    generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -623,10 +615,7 @@
</span><span class="cx"> 
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx"> 
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(finalDest, divotStart(), divotEnd());
</ins><span class="cx">     return ret;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -638,10 +627,7 @@
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     RegisterID* finalDest = generator.finalDestination(dst);
</span><span class="cx">     RegisterID* ret = generator.emitGetById(finalDest, base.get(), m_ident);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(finalDest, divotStart(), divotEnd());
</ins><span class="cx">     return ret;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -734,10 +720,7 @@
</span><span class="cx">     }
</span><span class="cx">     generator.emitLoad(callArguments.thisRegister(), jsUndefined());
</span><span class="cx">     RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
</ins><span class="cx">     return ret;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -757,10 +740,7 @@
</span><span class="cx">         // This passes NoExpectedFunction because we expect that if the function is in a
</span><span class="cx">         // local variable, then it's not one of our built-in constructors.
</span><span class="cx">         RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><del>-        if (generator.vm()-&gt;typeProfiler()) {
-            generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-            generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-        }
</del><ins>+        generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
</ins><span class="cx">         return ret;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -776,10 +756,7 @@
</span><span class="cx">     generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
</span><span class="cx">     generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
</span><span class="cx">     RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
</ins><span class="cx">     return ret;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -847,10 +824,7 @@
</span><span class="cx">     else
</span><span class="cx">         generator.emitMove(callArguments.thisRegister(), base.get());
</span><span class="cx">     RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
</ins><span class="cx">     return ret;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -869,10 +843,7 @@
</span><span class="cx">     generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
</span><span class="cx">     generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
</span><span class="cx">     RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
</ins><span class="cx">     return ret;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -927,10 +898,7 @@
</span><span class="cx">         }
</span><span class="cx">         generator.emitLabel(end.get());
</span><span class="cx">     }
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
</ins><span class="cx">     return returnValue.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1038,10 +1006,7 @@
</span><span class="cx">         generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><span class="cx">         generator.emitLabel(end.get());
</span><span class="cx">     }
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
</ins><span class="cx">     return returnValue.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1077,19 +1042,10 @@
</span><span class="cx">         if (var.isReadOnly()) {
</span><span class="cx">             generator.emitReadOnlyExceptionIfNeeded(var);
</span><span class="cx">             localReg = generator.emitMove(generator.tempDestination(dst), local);
</span><del>-        } else if (generator.vm()-&gt;typeProfiler()) {
-            RefPtr&lt;RegisterID&gt; tempDst = generator.finalDestination(dst);
-            ASSERT(dst != localReg);
-            RefPtr&lt;RegisterID&gt; tempDstSrc = generator.newTemporary();
-            generator.emitToNumber(tempDst.get(), localReg.get());
-            generator.emitMove(tempDstSrc.get(), localReg.get());
-            emitIncOrDec(generator, tempDstSrc.get(), m_operator);
-            generator.emitMove(localReg.get(), tempDstSrc.get());
-            if (generator.vm()-&gt;typeProfiler())
-                generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-            return tempDst.get();
</del><span class="cx">         }
</span><del>-        return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
</del><ins>+        RefPtr&lt;RegisterID&gt; oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
+        generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
+        return oldValue.get();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="lines">@@ -1103,10 +1059,7 @@
</span><span class="cx">     }
</span><span class="cx">     RefPtr&lt;RegisterID&gt; oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
</span><span class="cx">     generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &amp;ident);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
</ins><span class="cx"> 
</span><span class="cx">     return oldValue.get();
</span><span class="cx"> }
</span><span class="lines">@@ -1129,10 +1082,7 @@
</span><span class="cx">     RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     generator.emitPutByVal(base.get(), property.get(), value.get());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(value.get(), divotStart(), divotEnd());
</ins><span class="cx">     return generator.moveToDestinationIfNeeded(dst, oldValue);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1153,10 +1103,7 @@
</span><span class="cx">     RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     generator.emitPutById(base.get(), ident, value.get());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(value.get(), divotStart(), divotEnd());
</ins><span class="cx">     return generator.moveToDestinationIfNeeded(dst, oldValue);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1291,8 +1238,7 @@
</span><span class="cx">             generator.emitMove(tempDst.get(), localReg.get());
</span><span class="cx">             emitIncOrDec(generator, tempDst.get(), m_operator);
</span><span class="cx">             generator.emitMove(localReg.get(), tempDst.get());
</span><del>-            if (generator.vm()-&gt;typeProfiler())
-                generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</del><ins>+            generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
</ins><span class="cx">             return generator.moveToDestinationIfNeeded(dst, tempDst.get());
</span><span class="cx">         }
</span><span class="cx">         emitIncOrDec(generator, localReg.get(), m_operator);
</span><span class="lines">@@ -1311,10 +1257,7 @@
</span><span class="cx"> 
</span><span class="cx">     emitIncOrDec(generator, value.get(), m_operator);
</span><span class="cx">     generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &amp;ident);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
</ins><span class="cx">     return generator.moveToDestinationIfNeeded(dst, value.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1334,10 +1277,7 @@
</span><span class="cx">     emitIncOrDec(generator, value, m_operator);
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     generator.emitPutByVal(base.get(), property.get(), value);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(value, divotStart(), divotEnd());
</ins><span class="cx">     return generator.moveToDestinationIfNeeded(dst, propDst.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1356,10 +1296,7 @@
</span><span class="cx">     emitIncOrDec(generator, value, m_operator);
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     generator.emitPutById(base.get(), ident, value);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(value, divotStart(), divotEnd());
</ins><span class="cx">     return generator.moveToDestinationIfNeeded(dst, propDst.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1809,23 +1746,24 @@
</span><span class="cx">         generator.emitTDZCheckIfNecessary(var, local, nullptr);
</span><span class="cx">         if (var.isReadOnly()) {
</span><span class="cx">             generator.emitReadOnlyExceptionIfNeeded(var);
</span><del>-            return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right-&gt;resultDescriptor()));
</del><ins>+            RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right-&gt;resultDescriptor()));
+            generator.emitProfileType(result, divotStart(), divotEnd());
+            return result;
</ins><span class="cx">         }
</span><span class="cx">         
</span><del>-        if (generator.vm()-&gt;typeProfiler()
-            || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right-&gt;isPure(generator))) {
</del><ins>+        if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right-&gt;isPure(generator))) {
</ins><span class="cx">             RefPtr&lt;RegisterID&gt; result = generator.newTemporary();
</span><span class="cx">             generator.emitMove(result.get(), local);
</span><span class="cx">             emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right-&gt;resultDescriptor()));
</span><span class="cx">             generator.emitMove(local, result.get());
</span><span class="cx">             generator.invalidateForInContextForLocal(local);
</span><del>-            if (generator.vm()-&gt;typeProfiler())
-                generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</del><ins>+            generator.emitProfileType(local, divotStart(), divotEnd());
</ins><span class="cx">             return generator.moveToDestinationIfNeeded(dst, result.get());
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right-&gt;resultDescriptor()));
</span><span class="cx">         generator.invalidateForInContextForLocal(local);
</span><ins>+        generator.emitProfileType(result, divotStart(), divotEnd());
</ins><span class="cx">         return generator.moveToDestinationIfNeeded(dst, result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1840,10 +1778,7 @@
</span><span class="cx">     }
</span><span class="cx">     RefPtr&lt;RegisterID&gt; result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right-&gt;resultDescriptor()), this);
</span><span class="cx">     RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &amp;m_ident);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
</ins><span class="cx">     return returnResult;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1860,16 +1795,17 @@
</span><span class="cx">         if (var.isReadOnly() &amp;&amp; m_assignmentContext != AssignmentContext::ConstDeclarationStatement) {
</span><span class="cx">             result = generator.emitNode(dst, m_right); // Execute side effects first.
</span><span class="cx">             generator.emitReadOnlyExceptionIfNeeded(var);
</span><del>-        } else if (var.isSpecial() || generator.vm()-&gt;typeProfiler()) {
</del><ins>+            generator.emitProfileType(result, var, divotStart(), divotEnd());
+        } else if (var.isSpecial()) {
</ins><span class="cx">             RefPtr&lt;RegisterID&gt; tempDst = generator.tempDestination(dst);
</span><span class="cx">             generator.emitNode(tempDst.get(), m_right);
</span><span class="cx">             generator.emitMove(local, tempDst.get());
</span><ins>+            generator.emitProfileType(local, var, divotStart(), divotEnd());
</ins><span class="cx">             generator.invalidateForInContextForLocal(local);
</span><del>-            if (generator.vm()-&gt;typeProfiler())
-                generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</del><span class="cx">             result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
</span><span class="cx">         } else {
</span><span class="cx">             RegisterID* right = generator.emitNode(local, m_right);
</span><ins>+            generator.emitProfileType(right, var, divotStart(), divotEnd());
</ins><span class="cx">             generator.invalidateForInContextForLocal(local);
</span><span class="cx">             result = generator.moveToDestinationIfNeeded(dst, right);
</span><span class="cx">         }
</span><span class="lines">@@ -1895,10 +1831,7 @@
</span><span class="cx">     }
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &amp;m_ident);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
</ins><span class="cx"> 
</span><span class="cx">     if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
</span><span class="cx">         generator.liftTDZCheckIfPossible(var);
</span><span class="lines">@@ -1915,10 +1848,7 @@
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
</span><span class="cx">     generator.emitPutById(base.get(), m_ident, forwardResult);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(forwardResult, divotStart(), divotEnd());
</ins><span class="cx">     return generator.moveToDestinationIfNeeded(dst, forwardResult);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1934,10 +1864,7 @@
</span><span class="cx"> 
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(updatedValue, divotStart(), divotEnd());
</ins><span class="cx">     return ret;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1965,10 +1892,7 @@
</span><span class="cx">     else
</span><span class="cx">         generator.emitPutByVal(base.get(), property.get(), forwardResult);
</span><span class="cx"> 
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(forwardResult, divotStart(), divotEnd());
</ins><span class="cx">     return generator.moveToDestinationIfNeeded(dst, forwardResult);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1985,10 +1909,7 @@
</span><span class="cx"> 
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     generator.emitPutByVal(base.get(), property.get(), updatedValue);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(updatedValue, divotStart(), divotEnd());
</ins><span class="cx"> 
</span><span class="cx">     return updatedValue;
</span><span class="cx"> }
</span><span class="lines">@@ -2080,15 +2001,13 @@
</span><span class="cx"> 
</span><span class="cx">     Variable var = generator.variable(m_ident);
</span><span class="cx">     if (RegisterID* local = var.local())
</span><del>-        generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
</del><ins>+        generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
</ins><span class="cx">     else {
</span><span class="cx">         RefPtr&lt;RegisterID&gt; scope = generator.emitResolveScope(nullptr, var);
</span><span class="cx">         RefPtr&lt;RegisterID&gt; value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
</span><del>-        generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &amp;m_ident);
</del><ins>+        generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
-
</del><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2101,17 +2020,13 @@
</span><span class="cx">     Variable var = generator.variable(m_ident);
</span><span class="cx">     if (RegisterID* local = var.local()) {
</span><span class="cx">         generator.emitLoad(local, jsUndefined());
</span><del>-        if (generator.vm()-&gt;typeProfiler())
-            generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
</del><ins>+        generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
</ins><span class="cx">     } else {
</span><span class="cx">         RefPtr&lt;RegisterID&gt; scope = generator.emitResolveScope(nullptr, var);
</span><span class="cx">         RefPtr&lt;RegisterID&gt; value = generator.emitLoad(nullptr, jsUndefined());
</span><span class="cx">         generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
</span><del>-        if (generator.vm()-&gt;typeProfiler())
-            generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &amp;m_ident);
</del><ins>+        generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1)); 
</ins><span class="cx">     }
</span><del>-    if (generator.vm()-&gt;typeProfiler())
-        generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
</del><span class="cx"> 
</span><span class="cx">     // It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
</span><span class="cx">     return nullptr;
</span><span class="lines">@@ -2316,11 +2231,8 @@
</span><span class="cx">             RegisterID* scope = generator.emitResolveScope(nullptr, var);
</span><span class="cx">             generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">             generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
</span><del>-            if (generator.vm()-&gt;typeProfiler())
-                generator.emitProfileType(propertyName, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &amp;ident);
</del><span class="cx">         }
</span><del>-        if (generator.vm()-&gt;typeProfiler())
-            generator.emitTypeProfilerExpressionInfo(m_lexpr-&gt;position(), JSTextPosition(-1, m_lexpr-&gt;position().offset + ident.length(), -1));
</del><ins>+        generator.emitProfileType(propertyName, var, m_lexpr-&gt;position(), JSTextPosition(-1, m_lexpr-&gt;position().offset + ident.length(), -1));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     if (m_lexpr-&gt;isDotAccessorNode()) {
</span><span class="lines">@@ -2329,10 +2241,7 @@
</span><span class="cx">         RegisterID* base = generator.emitNode(assignNode-&gt;base());
</span><span class="cx">         generator.emitExpressionInfo(assignNode-&gt;divot(), assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</span><span class="cx">         generator.emitPutById(base, ident, propertyName);
</span><del>-        if (generator.vm()-&gt;typeProfiler()) {
-            generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-            generator.emitTypeProfilerExpressionInfo(assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
-        }
</del><ins>+        generator.emitProfileType(propertyName, assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     if (m_lexpr-&gt;isBracketAccessorNode()) {
</span><span class="lines">@@ -2341,10 +2250,7 @@
</span><span class="cx">         RegisterID* subscript = generator.emitNode(assignNode-&gt;subscript());
</span><span class="cx">         generator.emitExpressionInfo(assignNode-&gt;divot(), assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</span><span class="cx">         generator.emitPutByVal(base.get(), subscript, propertyName);
</span><del>-        if (generator.vm()-&gt;typeProfiler()) {
-            generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-            generator.emitTypeProfilerExpressionInfo(assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
-        }
</del><ins>+        generator.emitProfileType(propertyName, assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2364,8 +2270,7 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         generator.emitMove(var.local(), propertyName);
</span><del>-        if (generator.vm()-&gt;typeProfiler())
-            generator.emitTypeProfilerExpressionInfo(simpleBinding-&gt;divotStart(), simpleBinding-&gt;divotEnd());
</del><ins>+        generator.emitProfileType(propertyName, var, simpleBinding-&gt;divotStart(), simpleBinding-&gt;divotEnd());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2547,11 +2452,8 @@
</span><span class="cx">                 RegisterID* scope = generator.emitResolveScope(nullptr, var);
</span><span class="cx">                 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">                 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
</span><del>-                if (generator.vm()-&gt;typeProfiler())
-                    generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &amp;ident);
</del><span class="cx">             }
</span><del>-            if (generator.vm()-&gt;typeProfiler())
-                generator.emitTypeProfilerExpressionInfo(m_lexpr-&gt;position(), JSTextPosition(-1, m_lexpr-&gt;position().offset + ident.length(), -1));
</del><ins>+            generator.emitProfileType(value, var, m_lexpr-&gt;position(), JSTextPosition(-1, m_lexpr-&gt;position().offset + ident.length(), -1));
</ins><span class="cx">         } else if (m_lexpr-&gt;isDotAccessorNode()) {
</span><span class="cx">             DotAccessorNode* assignNode = static_cast&lt;DotAccessorNode*&gt;(m_lexpr);
</span><span class="cx">             const Identifier&amp; ident = assignNode-&gt;identifier();
</span><span class="lines">@@ -2559,10 +2461,7 @@
</span><span class="cx">             
</span><span class="cx">             generator.emitExpressionInfo(assignNode-&gt;divot(), assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</span><span class="cx">             generator.emitPutById(base.get(), ident, value);
</span><del>-            if (generator.vm()-&gt;typeProfiler()) {
-                generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-                generator.emitTypeProfilerExpressionInfo(assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
-            }
</del><ins>+            generator.emitProfileType(value, assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</ins><span class="cx">         } else if (m_lexpr-&gt;isBracketAccessorNode()) {
</span><span class="cx">             BracketAccessorNode* assignNode = static_cast&lt;BracketAccessorNode*&gt;(m_lexpr);
</span><span class="cx">             RefPtr&lt;RegisterID&gt; base = generator.emitNode(assignNode-&gt;base());
</span><span class="lines">@@ -2570,10 +2469,7 @@
</span><span class="cx">             
</span><span class="cx">             generator.emitExpressionInfo(assignNode-&gt;divot(), assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</span><span class="cx">             generator.emitPutByVal(base.get(), subscript, value);
</span><del>-            if (generator.vm()-&gt;typeProfiler()) {
-                generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
-                generator.emitTypeProfilerExpressionInfo(assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
-            }
</del><ins>+            generator.emitProfileType(value, assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</ins><span class="cx">         } else {
</span><span class="cx">             ASSERT(m_lexpr-&gt;isDestructuringNode());
</span><span class="cx">             DestructuringAssignmentNode* assignNode = static_cast&lt;DestructuringAssignmentNode*&gt;(m_lexpr);
</span><span class="lines">@@ -2656,10 +2552,7 @@
</span><span class="cx">         dst = 0;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;RegisterID&gt; returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, nullptr);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
</ins><span class="cx">     if (generator.labelScopeDepth()) {
</span><span class="cx">         returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
</span><span class="cx">         generator.emitPopScopes(generator.scopeRegister(), 0);
</span><span class="lines">@@ -3019,13 +2912,12 @@
</span><span class="cx"> {
</span><span class="cx">     if (generator.vm()-&gt;typeProfiler()) {
</span><span class="cx">         for (size_t i = 0; i &lt; m_parameters-&gt;size(); i++) {
</span><del>-            // FIXME: Handle Destructuring assignments into arguments.
</del><ins>+            // Destructuring parameters are handled in destructuring nodes.
</ins><span class="cx">             if (!m_parameters-&gt;at(i).first-&gt;isBindingNode())
</span><span class="cx">                 continue;
</span><span class="cx">             BindingNode* parameter = static_cast&lt;BindingNode*&gt;(m_parameters-&gt;at(i).first);
</span><span class="cx">             RegisterID reg(CallFrame::argumentOffset(i));
</span><del>-            generator.emitProfileType(&amp;reg, ProfileTypeBytecodeFunctionArgument, nullptr);
-            generator.emitTypeProfilerExpressionInfo(parameter-&gt;divotStart(), parameter-&gt;divotEnd());
</del><ins>+            generator.emitProfileType(&amp;reg, ProfileTypeBytecodeFunctionArgument, parameter-&gt;divotStart(), parameter-&gt;divotEnd());
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -3046,8 +2938,7 @@
</span><span class="cx">     // If there is no return we must automatically insert one.
</span><span class="cx">     if (!returnNode) {
</span><span class="cx">         RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
</span><del>-        if (generator.vm()-&gt;typeProfiler())
-            generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement, nullptr); // Do not emit expression info for this profile because it's not in the user's source code.
</del><ins>+        generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
</ins><span class="cx">         ASSERT(startOffset() &gt;= lineStartOffset());
</span><span class="cx">         generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
</span><span class="cx">         generator.emitReturn(r0);
</span><span class="lines">@@ -3367,8 +3258,7 @@
</span><span class="cx">                 return;
</span><span class="cx">         }
</span><span class="cx">         generator.emitMove(local, value);
</span><del>-        if (generator.vm()-&gt;typeProfiler())
-            generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</del><ins>+        generator.emitProfileType(local, var, divotStart(), divotEnd());
</ins><span class="cx">         if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
</span><span class="cx">             generator.liftTDZCheckIfPossible(var);
</span><span class="cx">         return;
</span><span class="lines">@@ -3385,10 +3275,7 @@
</span><span class="cx">             return;
</span><span class="cx">     }
</span><span class="cx">     generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
</span><del>-    if (generator.vm()-&gt;typeProfiler()) {
-        generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &amp;m_boundProperty);
-        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
-    }
</del><ins>+    generator.emitProfileType(value, var, divotStart(), divotEnd());
</ins><span class="cx">     if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
</span><span class="cx">         generator.liftTDZCheckIfPossible(var);
</span><span class="cx">     return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -4580,6 +4580,8 @@
</span><span class="cx">         GPRReg scratch2GPR = scratch2.gpr();
</span><span class="cx">         GPRReg scratch3GPR = scratch3.gpr();
</span><span class="cx"> 
</span><ins>+        JITCompiler::Jump isTDZValue = m_jit.branch32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::EmptyValueTag));
+
</ins><span class="cx">         // Load the TypeProfilerLog into Scratch2.
</span><span class="cx">         TypeProfilerLog* cachedTypeProfilerLog = m_jit.vm()-&gt;typeProfilerLog();
</span><span class="cx">         m_jit.move(TrustedImmPtr(cachedTypeProfilerLog), scratch2GPR);
</span><span class="lines">@@ -4612,6 +4614,8 @@
</span><span class="cx">         addSlowPathGenerator(
</span><span class="cx">             slowPathCall(clearLog, this, operationProcessTypeProfilerLogDFG, NoResult));
</span><span class="cx"> 
</span><ins>+        isTDZValue.link(&amp;m_jit);
+
</ins><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -4609,6 +4609,8 @@
</span><span class="cx"> 
</span><span class="cx">         MacroAssembler::JumpList jumpToEnd;
</span><span class="cx"> 
</span><ins>+        jumpToEnd.append(m_jit.branchTest64(JITCompiler::Zero, valueGPR));
+
</ins><span class="cx">         TypeLocation* cachedTypeLocation = node-&gt;typeLocation();
</span><span class="cx">         // Compile in a predictive type check, if possible, to see if we can skip writing to the log.
</span><span class="cx">         // These typechecks are inlined to match those of the 64-bit JSValue type checks.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -1239,6 +1239,8 @@
</span><span class="cx"> 
</span><span class="cx">     JumpList jumpToEnd;
</span><span class="cx"> 
</span><ins>+    jumpToEnd.append(branchTest64(Zero, regT0));
+
</ins><span class="cx">     // Compile in a predictive type check, if possible, to see if we can skip writing to the log.
</span><span class="cx">     // These typechecks are inlined to match those of the 64-bit JSValue type checks.
</span><span class="cx">     if (cachedTypeLocation-&gt;m_lastSeenType == TypeUndefined)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -1244,6 +1244,8 @@
</span><span class="cx"> 
</span><span class="cx">     JumpList jumpToEnd;
</span><span class="cx"> 
</span><ins>+    jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::EmptyValueTag)));
+
</ins><span class="cx">     // Compile in a predictive type check, if possible, to see if we can skip writing to the log.
</span><span class="cx">     // These typechecks are inlined to match those of the 32-bit JSValue type checks.
</span><span class="cx">     if (cachedTypeLocation-&gt;m_lastSeenType == TypeUndefined)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -2342,6 +2342,8 @@
</span><span class="cx">     loadisFromInstruction(1, t2)
</span><span class="cx">     loadConstantOrVariable(t2, t4, t0)
</span><span class="cx"> 
</span><ins>+    bieq t4, EmptyValueTag, .opProfileTypeDone
+
</ins><span class="cx">     # t2 is holding the pointer to the current log entry.
</span><span class="cx">     loadp TypeProfilerLog::m_currentLogEntryPtr[t1], t2
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (187523 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -2200,6 +2200,7 @@
</span><span class="cx">     loadisFromInstruction(1, t3)
</span><span class="cx">     loadConstantOrVariable(t3, t0)
</span><span class="cx"> 
</span><ins>+    bqeq t0, ValueEmpty, .opProfileTypeDone
</ins><span class="cx">     # Store the JSValue onto the log entry.
</span><span class="cx">     storeq t0, TypeProfilerLog::LogEntry::value[t2]
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreteststypeProfileres6blockscopingjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/typeProfiler/es6-block-scoping.js (0 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/typeProfiler/es6-block-scoping.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/typeProfiler/es6-block-scoping.js        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+load(&quot;./driver/driver.js&quot;);
+
+let changeFoo;
+let tdzError;
+let scoping;
+let scoping2;
+function noop(){}
+function arr() {
+    return [1, 1.5, &quot;hello&quot;, {}];
+}
+
+function wrapper() {
+
+let foo=20;
+changeFoo = function(arg) { foo = arg; }
+
+scoping = function ()
+{
+    let x = &quot;hello&quot;;
+    if (true) {
+        let x = 20;
+        const y = true;
+        x = &quot;h&quot;
+    }
+    noop(x);
+}
+
+scoping2 = function() 
+{
+    for (const item of arr()) {
+        noop(item);
+    }
+}
+
+}
+wrapper();
+
+// ====== End test cases ======
+
+var types = findTypeForExpression(wrapper, &quot;foo=20;&quot;); 
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, &quot;Primitive type names should contain 'Integer'&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, &quot;Primitive type names should contain 'Integer'&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.length === 1, &quot;Primitive type names should contain exactly only one item globally&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, &quot;Primitive type names should contain exactly only one item on the instruction&quot;);
+assert(types.globalTypeSet.displayTypeName === T.Integer, &quot;global display name should be Integer&quot;);
+assert(types.instructionTypeSet.displayTypeName === T.Integer, &quot;instruction display name should be Integer&quot;);
+
+changeFoo(20.5);
+types = findTypeForExpression(wrapper, &quot;foo=20;&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, &quot;Primitive type names should contain 'Integer'&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, &quot;Primitive type names should contain STILL only contain exactly one item on the instruction&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, &quot;Global primitive type names should now still contain 'Integer'&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Number) !== -1, &quot;Global primitive type names should now contain 'Number'&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.length === 2, &quot;Global primitive type names should contain exactly two items globally&quot;);
+assert(types.globalTypeSet.displayTypeName === T.Number, &quot;global display name should be Number&quot;);
+
+
+scoping();
+types = findTypeForExpression(scoping, &quot;x = 20&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, &quot;Primitive type names should contain 'Integer'&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, &quot;Primitive type names should contain only one item on the instruction&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, &quot;Primitive type names should contain 'Integer'&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.length === 2, &quot;Primitive type names should contain two items: [String, Integer]&quot;);
+
+types = findTypeForExpression(scoping, &quot;x)&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, &quot;Global primitive type names should have string.&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, &quot;Global primitive type names should have string.&quot;);
+
+types = findTypeForExpression(scoping, &quot;y = true&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Boolean) !== -1, &quot;Global primitive type names should have boolean.&quot;);
+assert(types.globalTypeSet.primitiveTypeNames.length === 1, &quot;type only have one item.&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Boolean) !== -1, &quot;Global primitive type names should have boolean.&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, &quot;type only have one item.&quot;);
+
+
+scoping2();
+types = findTypeForExpression(scoping2, &quot;item)&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, &quot;Primitive type names should contain 'Integer'&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Number) !== -1, &quot;Primitive type names should contain 'Number'&quot;);
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, &quot;Primitive type names should contain 'String'&quot;);
+assert(types.instructionTypeSet.structures.length === 1, &quot;should have one structure&quot;);
+assert(types.instructionTypeSet.structures[0].constructorName === &quot;Object&quot;, &quot;Should be object&quot;);
+assert(types.instructionTypeSet.structures[0].fields.length === 0, &quot;Should have no fields&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreteststypeProfileres6classesjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/typeProfiler/es6-classes.js (0 => 187524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/typeProfiler/es6-classes.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/typeProfiler/es6-classes.js        2015-07-28 22:39:12 UTC (rev 187524)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+load(&quot;./driver/driver.js&quot;);
+
+let changeFoo;
+let tdzError;
+let scoping;
+let scoping2;
+function noop(){}
+
+function wrapper() {
+    class Animal {
+        constructor() { }
+        methodA() {}
+    }
+    class Dog extends Animal {
+        constructor() { super() }
+        methodB() {}
+    }
+
+    let dogInstance = new Dog;
+    const animalInstance = new Animal;
+}
+wrapper();
+
+// ====== End test cases ======
+
+var types = findTypeForExpression(wrapper, &quot;dogInstance =&quot;);
+assert(types.globalTypeSet.displayTypeName === &quot;Dog&quot;, &quot;Should show constructor name&quot;);
+assert(types.globalTypeSet.structures[0].constructorName === &quot;Dog&quot;, &quot;Should be Dog&quot;);
+assert(types.globalTypeSet.structures[0].proto.fields.length === 2, &quot;should have two fields&quot;);
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf(&quot;constructor&quot;) !== -1, &quot;should have constructor&quot;);
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf(&quot;methodB&quot;) !== -1, &quot;should have methodB&quot;);
+
+types = findTypeForExpression(wrapper, &quot;animalInstance =&quot;);
+assert(types.globalTypeSet.displayTypeName === &quot;Animal&quot;, &quot;Should show constructor name&quot;);
+assert(types.globalTypeSet.structures.length === 1, &quot;should have one structure&quot;);
+assert(types.globalTypeSet.structures[0].constructorName === &quot;Animal&quot;, &quot;Should be Animal&quot;);
+assert(types.globalTypeSet.structures[0].proto.fields.length === 2, &quot;should have two fields&quot;);
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf(&quot;constructor&quot;) !== -1, &quot;should have constructor&quot;);
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf(&quot;methodA&quot;) !== -1, &quot;should have methodA&quot;);
</ins></span></pre>
</div>
</div>

</body>
</html>