<!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 "let"
and "const" 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 <saambarati1@gmail.com>
</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 "let"
+ and "const" 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 <saambarati1@gmail.com>
+
</ins><span class="cx"> Implement catch scope using lexical scoping constructs introduced with "let" 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->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<int, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> clonedConstantSymbolTables;
</span><del>- m_symbolTableConstantIndex = unlinkedCodeBlock->symbolTableConstantIndex();
</del><span class="cx"> {
</span><span class="cx"> HashSet<SymbolTable*> clonedSymbolTables;
</span><span class="cx"> for (unsigned i = 0; i < 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<ProfileTypeBytecodeFlag>(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& ident = identifier(pc[4].u.operand);
</span><ins>+ int localScopeDepth = pc[2].u.operand;
</ins><span class="cx"> ResolveType type = static_cast<ResolveType>(pc[5].u.operand);
</span><del>- ResolveOp op = JSScope::abstractResolve(m_globalObject->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 "read"ing from a JSScope.
+ ResolveOp op = JSScope::abstractResolve(m_globalObject->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->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<SymbolTable*>(getConstant(symbolTableIndex));
</ins><span class="cx"> const Identifier& ident = identifier(pc[4].u.operand);
</span><del>- symbolTable = this->symbolTable();
</del><span class="cx"> ConcurrentJITLocker locker(symbolTable->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->prepareForTypeProfiling(locker);
</del><span class="cx"> globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
</span><span class="cx"> globalTypeSet = symbolTable->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->symbolTable();
- ConcurrentJITLocker locker(symbolTable->m_lock);
- globalVariableID = symbolTable->uniqueIDForOffset(locker, VarOffset(profileRegister), *vm());
- globalTypeSet = symbolTable->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<SymbolTable*>(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<Instruction> 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& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); }
</span><span class="cx"> UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->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<SymbolTable> m_symbolTable;
</span><del>- int m_symbolTableConstantIndex { 0 };
</del><span class="cx">
</span><span class="cx"> Vector<unsigned> 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->setUsesNonStrictEval(m_usesNonStrictEval);
</span><span class="cx"> int symbolTableConstantIndex = addConstantValue(functionSymbolTable)->index();
</span><del>- m_codeBlock->setSymbolTableConstantIndex(symbolTableConstantIndex);
</del><span class="cx">
</span><span class="cx"> Vector<Identifier> boundParameterProperties;
</span><span class="cx"> FunctionParameters& parameters = *functionNode->parameters();
</span><span class="lines">@@ -1180,9 +1179,6 @@
</span><span class="cx"> instructions().append(dst->index());
</span><span class="cx"> instructions().append(src->index());
</span><span class="cx">
</span><del>- if (!dst->isTemporary() && vm()->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& startDivot, const JSTextPosition& endDivot)
</span><span class="cx"> {
</span><ins>+ ASSERT(vm()->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->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()->typeProfiler())
+ return;
</ins><span class="cx">
</span><ins>+ if (!registerToProfile)
+ return;
+
+ emitOpcode(op_profile_type);
+ instructions().append(registerToProfile->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& startDivot, const JSTextPosition& endDivot)
+{
+ emitProfileType(registerToProfile, ProfileTypeBytecodeDoesNotHaveGlobalID, startDivot, endDivot);
+}
+
+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
+{
+ if (!vm()->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->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& var, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
+{
+ if (!vm()->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->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()->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()->typeProfiler()) {
+ constantSymbolTable = addConstantValue(symbolTable.get());
+ symbolTableConstantIndex = constantSymbolTable->index();
+ }
</ins><span class="cx"> if (hasCapturedVariables) {
</span><span class="cx"> newScope = newBlockScopeVariable();
</span><span class="cx"> newScope->ref();
</span><del>-
- RegisterID* constantSymbolTable = addConstantValue(!m_codeBlock->vm()->typeProfiler() ? symbolTable->cloneScopePart(*m_vm) : symbolTable.get());
- symbolTableConstantIndex = constantSymbolTable->index();
</del><ins>+ if (!constantSymbolTable) {
+ ASSERT(!vm()->typeProfiler());
+ constantSymbolTable = addConstantValue(symbolTable->cloneScopePart(*m_vm));
+ symbolTableConstantIndex = constantSymbolTable->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& startDivot, const JSTextPosition& 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&, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
+
+ void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
+ // These are not associated with variables and don't have a global id.
+ void emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& 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()->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()->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()->typeProfiler()) {
- generator.emitProfileType(finalDest, var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &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()->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()->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()->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()->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()->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()->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()->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()->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()->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()->typeProfiler()) {
- RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
- ASSERT(dst != localReg);
- RefPtr<RegisterID> 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()->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<RegisterID> 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<RegisterID> 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()->typeProfiler()) {
- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &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()->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()->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()->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()->typeProfiler()) {
- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &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()->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()->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->resultDescriptor()));
</del><ins>+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ generator.emitProfileType(result, divotStart(), divotEnd());
+ return result;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- if (generator.vm()->typeProfiler()
- || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
</del><ins>+ if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
</ins><span class="cx"> RefPtr<RegisterID> 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->resultDescriptor()));
</span><span class="cx"> generator.emitMove(local, result.get());
</span><span class="cx"> generator.invalidateForInContextForLocal(local);
</span><del>- if (generator.vm()->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->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<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
</span><span class="cx"> RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound);
</span><del>- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &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() && 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()->typeProfiler()) {
</del><ins>+ generator.emitProfileType(result, var, divotStart(), divotEnd());
+ } else if (var.isSpecial()) {
</ins><span class="cx"> RefPtr<RegisterID> 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()->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()->typeProfiler()) {
- generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &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()->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()->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()->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()->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<RegisterID> scope = generator.emitResolveScope(nullptr, var);
</span><span class="cx"> RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
</span><del>- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &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()->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<RegisterID> scope = generator.emitResolveScope(nullptr, var);
</span><span class="cx"> RefPtr<RegisterID> 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()->typeProfiler())
- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &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()->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()->typeProfiler())
- generator.emitProfileType(propertyName, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
</del><span class="cx"> }
</span><del>- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
</del><ins>+ generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> if (m_lexpr->isDotAccessorNode()) {
</span><span class="lines">@@ -2329,10 +2241,7 @@
</span><span class="cx"> RegisterID* base = generator.emitNode(assignNode->base());
</span><span class="cx"> generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
</span><span class="cx"> generator.emitPutById(base, ident, propertyName);
</span><del>- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
</del><ins>+ generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> if (m_lexpr->isBracketAccessorNode()) {
</span><span class="lines">@@ -2341,10 +2250,7 @@
</span><span class="cx"> RegisterID* subscript = generator.emitNode(assignNode->subscript());
</span><span class="cx"> generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
</span><span class="cx"> generator.emitPutByVal(base.get(), subscript, propertyName);
</span><del>- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
</del><ins>+ generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->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()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(simpleBinding->divotStart(), simpleBinding->divotEnd());
</del><ins>+ generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->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()->typeProfiler())
- generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
</del><span class="cx"> }
</span><del>- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
</del><ins>+ generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
</ins><span class="cx"> } else if (m_lexpr->isDotAccessorNode()) {
</span><span class="cx"> DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
</span><span class="cx"> const Identifier& ident = assignNode->identifier();
</span><span class="lines">@@ -2559,10 +2461,7 @@
</span><span class="cx">
</span><span class="cx"> generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
</span><span class="cx"> generator.emitPutById(base.get(), ident, value);
</span><del>- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
</del><ins>+ generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
</ins><span class="cx"> } else if (m_lexpr->isBracketAccessorNode()) {
</span><span class="cx"> BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
</span><span class="cx"> RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
</span><span class="lines">@@ -2570,10 +2469,7 @@
</span><span class="cx">
</span><span class="cx"> generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
</span><span class="cx"> generator.emitPutByVal(base.get(), subscript, value);
</span><del>- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
</del><ins>+ generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
</ins><span class="cx"> } else {
</span><span class="cx"> ASSERT(m_lexpr->isDestructuringNode());
</span><span class="cx"> DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(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<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
</span><del>- if (generator.vm()->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()->typeProfiler()) {
</span><span class="cx"> for (size_t i = 0; i < m_parameters->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->at(i).first->isBindingNode())
</span><span class="cx"> continue;
</span><span class="cx"> BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
</span><span class="cx"> RegisterID reg(CallFrame::argumentOffset(i));
</span><del>- generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, nullptr);
- generator.emitTypeProfilerExpressionInfo(parameter->divotStart(), parameter->divotEnd());
</del><ins>+ generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->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()->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() >= 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()->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()->typeProfiler()) {
- generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &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()->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(&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->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->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->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("./driver/driver.js");
+
+let changeFoo;
+let tdzError;
+let scoping;
+let scoping2;
+function noop(){}
+function arr() {
+ return [1, 1.5, "hello", {}];
+}
+
+function wrapper() {
+
+let foo=20;
+changeFoo = function(arg) { foo = arg; }
+
+scoping = function ()
+{
+ let x = "hello";
+ if (true) {
+ let x = 20;
+ const y = true;
+ x = "h"
+ }
+ noop(x);
+}
+
+scoping2 = function()
+{
+ for (const item of arr()) {
+ noop(item);
+ }
+}
+
+}
+wrapper();
+
+// ====== End test cases ======
+
+var types = findTypeForExpression(wrapper, "foo=20;");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain exactly only one item globally");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain exactly only one item on the instruction");
+assert(types.globalTypeSet.displayTypeName === T.Integer, "global display name should be Integer");
+assert(types.instructionTypeSet.displayTypeName === T.Integer, "instruction display name should be Integer");
+
+changeFoo(20.5);
+types = findTypeForExpression(wrapper, "foo=20;");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain STILL only contain exactly one item on the instruction");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Global primitive type names should now still contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Number) !== -1, "Global primitive type names should now contain 'Number'");
+assert(types.globalTypeSet.primitiveTypeNames.length === 2, "Global primitive type names should contain exactly two items globally");
+assert(types.globalTypeSet.displayTypeName === T.Number, "global display name should be Number");
+
+
+scoping();
+types = findTypeForExpression(scoping, "x = 20");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain only one item on the instruction");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.length === 2, "Primitive type names should contain two items: [String, Integer]");
+
+types = findTypeForExpression(scoping, "x)");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, "Global primitive type names should have string.");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, "Global primitive type names should have string.");
+
+types = findTypeForExpression(scoping, "y = true");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Boolean) !== -1, "Global primitive type names should have boolean.");
+assert(types.globalTypeSet.primitiveTypeNames.length === 1, "type only have one item.");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Boolean) !== -1, "Global primitive type names should have boolean.");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "type only have one item.");
+
+
+scoping2();
+types = findTypeForExpression(scoping2, "item)");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Number) !== -1, "Primitive type names should contain 'Number'");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, "Primitive type names should contain 'String'");
+assert(types.instructionTypeSet.structures.length === 1, "should have one structure");
+assert(types.instructionTypeSet.structures[0].constructorName === "Object", "Should be object");
+assert(types.instructionTypeSet.structures[0].fields.length === 0, "Should have no fields");
</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("./driver/driver.js");
+
+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, "dogInstance =");
+assert(types.globalTypeSet.displayTypeName === "Dog", "Should show constructor name");
+assert(types.globalTypeSet.structures[0].constructorName === "Dog", "Should be Dog");
+assert(types.globalTypeSet.structures[0].proto.fields.length === 2, "should have two fields");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("constructor") !== -1, "should have constructor");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("methodB") !== -1, "should have methodB");
+
+types = findTypeForExpression(wrapper, "animalInstance =");
+assert(types.globalTypeSet.displayTypeName === "Animal", "Should show constructor name");
+assert(types.globalTypeSet.structures.length === 1, "should have one structure");
+assert(types.globalTypeSet.structures[0].constructorName === "Animal", "Should be Animal");
+assert(types.globalTypeSet.structures[0].proto.fields.length === 2, "should have two fields");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("constructor") !== -1, "should have constructor");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("methodA") !== -1, "should have methodA");
</ins></span></pre>
</div>
</div>
</body>
</html>