<!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>[178143] 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/178143">178143</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2015-01-08 16:10:01 -0800 (Thu, 08 Jan 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Make the LLINT and Baseline JIT's op_create_arguments and op_get_argument_by_val use their lexicalEnvironment operand.
<https://webkit.org/b/140236>
Reviewed by Geoffrey Garen.
Will change the DFG to use the operand on a subsequent pass. For now,
the DFG uses a temporary thunk (operationCreateArgumentsForDFG()) to
retain the old behavior of getting the lexicalEnviroment from the
ExecState.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitGetArgumentByVal):
(JSC::BytecodeGenerator::createArgumentsIfNecessary):
- When the lexicalEnvironment is not available, pass the invalid VirtualRegister
instead of an empty JSValue as the lexicalEnvironment operand.
* dfg/DFGOperations.cpp:
- Use the lexicalEnvironment from the ExecState for now.
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
- Use the operationCreateArgumentsForDFG() thunk for now.
* interpreter/CallFrame.cpp:
(JSC::CallFrame::lexicalEnvironmentOrNullptr):
* interpreter/CallFrame.h:
- Added this convenience function to return either the
lexicalEnvironment or a nullptr so that we don't need to do a
conditional check on codeBlock->needsActivation() at multiple sites.
* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::Frame::createArguments):
* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_create_arguments):
(JSC::JIT::emitSlow_op_get_argument_by_val):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_create_arguments):
(JSC::JIT::emitSlow_op_get_argument_by_val):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/Arguments.h:
(JSC::Arguments::create):
(JSC::Arguments::finishCreation):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/JSLexicalEnvironment.cpp:
(JSC::JSLexicalEnvironment::argumentsGetter):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.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="#trunkSourceJavaScriptCoreinterpreterCallFramecpp">trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterCallFrameh">trunk/Source/JavaScriptCore/interpreter/CallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterStackVisitorcpp">trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</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="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentsh">trunk/Source/JavaScriptCore/runtime/Arguments.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSLexicalEnvironmentcpp">trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2015-01-08 Mark Lam <mark.lam@apple.com>
+
+ Make the LLINT and Baseline JIT's op_create_arguments and op_get_argument_by_val use their lexicalEnvironment operand.
+ <https://webkit.org/b/140236>
+
+ Reviewed by Geoffrey Garen.
+
+ Will change the DFG to use the operand on a subsequent pass. For now,
+ the DFG uses a temporary thunk (operationCreateArgumentsForDFG()) to
+ retain the old behavior of getting the lexicalEnviroment from the
+ ExecState.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::emitGetArgumentByVal):
+ (JSC::BytecodeGenerator::createArgumentsIfNecessary):
+ - When the lexicalEnvironment is not available, pass the invalid VirtualRegister
+ instead of an empty JSValue as the lexicalEnvironment operand.
+
+ * dfg/DFGOperations.cpp:
+ - Use the lexicalEnvironment from the ExecState for now.
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ - Use the operationCreateArgumentsForDFG() thunk for now.
+
+ * interpreter/CallFrame.cpp:
+ (JSC::CallFrame::lexicalEnvironmentOrNullptr):
+ * interpreter/CallFrame.h:
+ - Added this convenience function to return either the
+ lexicalEnvironment or a nullptr so that we don't need to do a
+ conditional check on codeBlock->needsActivation() at multiple sites.
+
+ * interpreter/StackVisitor.cpp:
+ (JSC::StackVisitor::Frame::createArguments):
+ * jit/JIT.h:
+ * jit/JITInlines.h:
+ (JSC::JIT::callOperation):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_create_arguments):
+ (JSC::JIT::emitSlow_op_get_argument_by_val):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_create_arguments):
+ (JSC::JIT::emitSlow_op_get_argument_by_val):
+ * jit/JITOperations.cpp:
+ * jit/JITOperations.h:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * runtime/Arguments.h:
+ (JSC::Arguments::create):
+ (JSC::Arguments::finishCreation):
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/JSLexicalEnvironment.cpp:
+ (JSC::JSLexicalEnvironment::argumentsGetter):
+
</ins><span class="cx"> 2015-01-08 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><span class="cx"> Web Inspector: Pause Reason Improvements (Breakpoint, Debugger Statement, Pause on Next Statement)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -282,8 +282,7 @@
</span><span class="cx"> if (shouldCreateArgumentsEagerly() || shouldTearOffArgumentsEagerly()) {
</span><span class="cx"> emitOpcode(op_create_arguments);
</span><span class="cx"> instructions().append(argumentsRegister->index());
</span><del>- ASSERT(!m_codeBlock->hasActivationRegister() || m_codeBlock->activationRegister().isValid());
- instructions().append(m_codeBlock->hasActivationRegister() ? m_codeBlock->activationRegister().offset() : addConstantValue(JSValue())->index());
</del><ins>+ instructions().append(m_codeBlock->activationRegister().offset());
</ins><span class="cx">
</span><span class="cx"> if (m_codeBlock->hasActivationRegister()) {
</span><span class="cx"> RegisterID* argumentsRegister = &registerFor(m_codeBlock->argumentsRegister().offset());
</span><span class="lines">@@ -1525,8 +1524,7 @@
</span><span class="cx"> ASSERT(base->virtualRegister() == m_codeBlock->argumentsRegister());
</span><span class="cx"> instructions().append(base->index());
</span><span class="cx"> instructions().append(property->index());
</span><del>- ASSERT(!m_codeBlock->hasActivationRegister() || m_codeBlock->activationRegister().isValid());
- instructions().append(m_codeBlock->hasActivationRegister() ? m_codeBlock->activationRegister().offset() : addConstantValue(JSValue())->index());
</del><ins>+ instructions().append(m_codeBlock->activationRegister().offset());
</ins><span class="cx"> instructions().append(arrayProfile);
</span><span class="cx"> instructions().append(profile);
</span><span class="cx"> return dst;
</span><span class="lines">@@ -1777,8 +1775,7 @@
</span><span class="cx"> emitOpcode(op_create_arguments);
</span><span class="cx"> instructions().append(m_codeBlock->argumentsRegister().offset());
</span><span class="cx"> ASSERT(!hasWatchableVariable(m_codeBlock->argumentsRegister().offset()));
</span><del>- ASSERT(!m_codeBlock->hasActivationRegister() || m_codeBlock->activationRegister().isValid());
- instructions().append(m_codeBlock->hasActivationRegister() ? m_codeBlock->activationRegister().offset() : addConstantValue(JSValue())->index());
</del><ins>+ instructions().append(m_codeBlock->activationRegister().offset());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -796,8 +796,10 @@
</span><span class="cx">
</span><span class="cx"> // If there are no arguments, and we're accessing out of bounds, then we have to create the
</span><span class="cx"> // arguments in case someone has installed a getter on a numeric property.
</span><del>- if (!argumentsValue)
- exec->uncheckedR(argumentsRegister) = argumentsValue = Arguments::create(exec->vm(), exec);
</del><ins>+ if (!argumentsValue) {
+ JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr();
+ exec->uncheckedR(argumentsRegister) = argumentsValue = Arguments::create(exec->vm(), exec, lexicalEnvironment);
+ }
</ins><span class="cx">
</span><span class="cx"> return JSValue::encode(argumentsValue.get(exec, index));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -4225,7 +4225,7 @@
</span><span class="cx"> || !executable->parameterCount()) {
</span><span class="cx"> JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
</span><span class="cx"> addSlowPathGenerator(
</span><del>- slowPathCall(notCreated, this, operationCreateArguments, resultGPR));
</del><ins>+ slowPathCall(notCreated, this, operationCreateArgumentsForDFG, resultGPR));
</ins><span class="cx"> cellResult(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -4235,7 +4235,7 @@
</span><span class="cx"> MacroAssembler::JumpList slowPaths;
</span><span class="cx"> emitAllocateArguments(resultGPR, scratch1GPR, scratch2GPR, slowPaths);
</span><span class="cx"> addSlowPathGenerator(
</span><del>- slowPathCall(slowPaths, this, operationCreateArguments, resultGPR));
</del><ins>+ slowPathCall(slowPaths, this, operationCreateArgumentsForDFG, resultGPR));
</ins><span class="cx">
</span><span class="cx"> alreadyCreated.link(&m_jit);
</span><span class="cx"> cellResult(resultGPR, node);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -4287,7 +4287,7 @@
</span><span class="cx"> || !executable->parameterCount()) {
</span><span class="cx"> JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
</span><span class="cx"> addSlowPathGenerator(
</span><del>- slowPathCall(notCreated, this, operationCreateArguments, resultGPR));
</del><ins>+ slowPathCall(notCreated, this, operationCreateArgumentsForDFG, resultGPR));
</ins><span class="cx"> cellResult(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -4297,7 +4297,7 @@
</span><span class="cx"> MacroAssembler::JumpList slowPaths;
</span><span class="cx"> emitAllocateArguments(resultGPR, scratchGPR1, scratchGPR2, slowPaths);
</span><span class="cx"> addSlowPathGenerator(
</span><del>- slowPathCall(slowPaths, this, operationCreateArguments, resultGPR));
</del><ins>+ slowPathCall(slowPaths, this, operationCreateArgumentsForDFG, resultGPR));
</ins><span class="cx">
</span><span class="cx"> alreadyCreated.link(&m_jit);
</span><span class="cx"> cellResult(resultGPR, node);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -154,6 +154,12 @@
</span><span class="cx"> return registers()[activationRegister.offset()].Register::lexicalEnvironment();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+JSLexicalEnvironment* CallFrame::lexicalEnvironmentOrNullptr() const
+{
+ CodeBlock* codeBlock = this->codeBlock();
+ return codeBlock->needsActivation() ? lexicalEnvironment() : nullptr;
+}
+
</ins><span class="cx"> void CallFrame::setActivation(JSLexicalEnvironment* lexicalEnvironment)
</span><span class="cx"> {
</span><span class="cx"> CodeBlock* codeBlock = this->codeBlock();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.h (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">
</span><span class="cx"> bool hasActivation() const;
</span><span class="cx"> JSLexicalEnvironment* lexicalEnvironment() const;
</span><ins>+ JSLexicalEnvironment* lexicalEnvironmentOrNullptr() const;
</ins><span class="cx"> JSValue uncheckedActivation() const;
</span><span class="cx">
</span><span class="cx"> // Global object in which execution began.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterStackVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -272,7 +272,8 @@
</span><span class="cx"> } else
</span><span class="cx"> #endif
</span><span class="cx"> {
</span><del>- arguments = Arguments::create(vm, physicalFrame, mode);
</del><ins>+ JSLexicalEnvironment* lexicalEnvironment = physicalFrame->lexicalEnvironmentOrNullptr();
+ arguments = Arguments::create(vm, physicalFrame, lexicalEnvironment, mode);
</ins><span class="cx"> arguments->tearOff(physicalFrame);
</span><span class="cx"> }
</span><span class="cx"> return arguments;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -681,6 +681,8 @@
</span><span class="cx">
</span><span class="cx"> MacroAssembler::Call callOperation(C_JITOperation_E);
</span><span class="cx"> MacroAssembler::Call callOperation(C_JITOperation_EO, GPRReg);
</span><ins>+ MacroAssembler::Call callOperation(C_JITOperation_EL, GPRReg);
+ MacroAssembler::Call callOperation(C_JITOperation_EL, TrustedImmPtr);
</ins><span class="cx"> MacroAssembler::Call callOperation(C_JITOperation_ESt, Structure*);
</span><span class="cx"> MacroAssembler::Call callOperation(C_JITOperation_EZ, int32_t);
</span><span class="cx"> MacroAssembler::Call callOperation(F_JITOperation_EJZZ, GPRReg, int32_t, int32_t);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -216,6 +216,18 @@
</span><span class="cx"> return appendCallWithExceptionCheck(operation);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EL operation, GPRReg arg1)
+{
+ setupArgumentsWithExecState(arg1);
+ return appendCallWithExceptionCheck(operation);
+}
+
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EL operation, TrustedImmPtr arg1)
+{
+ setupArgumentsWithExecState(arg1);
+ return appendCallWithExceptionCheck(operation);
+}
+
</ins><span class="cx"> ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EO operation, GPRReg arg)
</span><span class="cx"> {
</span><span class="cx"> setupArgumentsWithExecState(arg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -689,10 +689,15 @@
</span><span class="cx"> void JIT::emit_op_create_arguments(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx"> int dst = currentInstruction[1].u.operand;
</span><ins>+ int lexicalEnvironment = currentInstruction[2].u.operand;
</ins><span class="cx">
</span><span class="cx"> Jump argsCreated = branchTest64(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
</span><span class="cx">
</span><del>- callOperation(operationCreateArguments);
</del><ins>+ if (VirtualRegister(lexicalEnvironment).isValid()) {
+ emitGetVirtualRegister(lexicalEnvironment, regT0);
+ callOperation(operationCreateArguments, regT0);
+ } else
+ callOperation(operationCreateArguments, TrustedImmPtr(nullptr));
</ins><span class="cx"> emitStoreCell(dst, returnValueGPR);
</span><span class="cx"> emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(dst)), returnValueGPR);
</span><span class="cx">
</span><span class="lines">@@ -956,13 +961,18 @@
</span><span class="cx"> int dst = currentInstruction[1].u.operand;
</span><span class="cx"> int arguments = currentInstruction[2].u.operand;
</span><span class="cx"> int property = currentInstruction[3].u.operand;
</span><ins>+ int lexicalEnvironment = currentInstruction[4].u.operand;
</ins><span class="cx">
</span><span class="cx"> linkSlowCase(iter);
</span><span class="cx"> Jump skipArgumentsCreation = jump();
</span><span class="cx">
</span><span class="cx"> linkSlowCase(iter);
</span><span class="cx"> linkSlowCase(iter);
</span><del>- callOperation(operationCreateArguments);
</del><ins>+ if (VirtualRegister(lexicalEnvironment).isValid()) {
+ emitGetVirtualRegister(lexicalEnvironment, regT0);
+ callOperation(operationCreateArguments, regT0);
+ } else
+ callOperation(operationCreateArguments, TrustedImmPtr(nullptr));
</ins><span class="cx"> emitStoreCell(arguments, returnValueGPR);
</span><span class="cx"> emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(arguments)), returnValueGPR);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -918,11 +918,18 @@
</span><span class="cx"> void JIT::emit_op_create_arguments(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx"> int dst = currentInstruction[1].u.operand;
</span><ins>+ int lexicalEnvironment = currentInstruction[2].u.operand;
</ins><span class="cx">
</span><span class="cx"> Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
</span><del>- callOperation(operationCreateArguments);
</del><ins>+
+ if (VirtualRegister(lexicalEnvironment).isValid()) {
+ emitLoadPayload(lexicalEnvironment, regT0);
+ callOperation(operationCreateArguments, regT0);
+ } else
+ callOperation(operationCreateArguments, TrustedImmPtr(nullptr));
</ins><span class="cx"> emitStoreCell(dst, returnValueGPR);
</span><span class="cx"> emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(dst)).offset(), returnValueGPR);
</span><ins>+
</ins><span class="cx"> argsCreated.link(this);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1064,6 +1071,7 @@
</span><span class="cx"> int dst = currentInstruction[1].u.operand;
</span><span class="cx"> int arguments = currentInstruction[2].u.operand;
</span><span class="cx"> int property = currentInstruction[3].u.operand;
</span><ins>+ int lexicalEnvironment = currentInstruction[4].u.operand;
</ins><span class="cx">
</span><span class="cx"> linkSlowCase(iter);
</span><span class="cx"> Jump skipArgumentsCreation = jump();
</span><span class="lines">@@ -1071,7 +1079,11 @@
</span><span class="cx"> linkSlowCase(iter);
</span><span class="cx"> linkSlowCase(iter);
</span><span class="cx">
</span><del>- callOperation(operationCreateArguments);
</del><ins>+ if (VirtualRegister(lexicalEnvironment).isValid()) {
+ emitLoadPayload(lexicalEnvironment, regT0);
+ callOperation(operationCreateArguments, regT0);
+ } else
+ callOperation(operationCreateArguments, TrustedImmPtr(nullptr));
</ins><span class="cx"> emitStoreCell(arguments, returnValueGPR);
</span><span class="cx"> emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(arguments)).offset(), returnValueGPR);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -1402,13 +1402,20 @@
</span><span class="cx"> return lexicalEnvironment;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSCell* JIT_OPERATION operationCreateArguments(ExecState* exec)
</del><ins>+// FIXME: This is a temporary thunk for the DFG until we add the lexicalEnvironment operand to the DFG CreateArguments node.
+JSCell* JIT_OPERATION operationCreateArgumentsForDFG(ExecState* exec)
</ins><span class="cx"> {
</span><ins>+ JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr();
+ return operationCreateArguments(exec, lexicalEnvironment);
+}
+
+JSCell* JIT_OPERATION operationCreateArguments(ExecState* exec, JSLexicalEnvironment* lexicalEnvironment)
+{
</ins><span class="cx"> VM& vm = exec->vm();
</span><span class="cx"> NativeCallFrameTracer tracer(&vm, exec);
</span><span class="cx"> // NB: This needs to be exceedingly careful with top call frame tracking, since it
</span><span class="cx"> // may be called from OSR exit, while the state of the call stack is bizarre.
</span><del>- Arguments* result = Arguments::create(vm, exec);
</del><ins>+ Arguments* result = Arguments::create(vm, exec, lexicalEnvironment);
</ins><span class="cx"> ASSERT(!vm.exception());
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="lines">@@ -1416,7 +1423,8 @@
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateArgumentsDuringOSRExit(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx"> DeferGCForAWhile(exec->vm().heap);
</span><del>- return operationCreateArguments(exec);
</del><ins>+ JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr();
+ return operationCreateArguments(exec, lexicalEnvironment);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx"> Jcp: const JSValue*
</span><span class="cx"> Jsc: JSScope*
</span><span class="cx"> Jss: JSString*
</span><ins>+ L: JSLexicalEnvironment*
</ins><span class="cx"> O: JSObject*
</span><span class="cx"> P: pointer (char*)
</span><span class="cx"> Pc: Instruction* i.e. bytecode PC
</span><span class="lines">@@ -136,6 +137,7 @@
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssSt)(ExecState*, JSString*, Structure*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssJss)(ExecState*, JSString*, JSString*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssJssJss)(ExecState*, JSString*, JSString*, JSString*);
</span><ins>+typedef JSCell* JIT_OPERATION (*C_JITOperation_EL)(ExecState*, JSLexicalEnvironment*);
</ins><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EO)(ExecState*, JSObject*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EOZ)(ExecState*, JSObject*, int32_t);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_ESt)(ExecState*, Structure*);
</span><span class="lines">@@ -294,7 +296,8 @@
</span><span class="cx"> void JIT_OPERATION operationProfileWillCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState*, EncodedJSValue, EncodedJSValue baseVal) WTF_INTERNAL;
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateActivation(ExecState*, JSScope* currentScope, int32_t offset) WTF_INTERNAL;
</span><del>-JSCell* JIT_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL;
</del><ins>+JSCell* JIT_OPERATION operationCreateArgumentsForDFG(ExecState*) WTF_INTERNAL; // FIXME: This is a temporary thunk for the DFG until we add the lexicalEnvironment operand to the DFG CreateArguments node.
+JSCell* JIT_OPERATION operationCreateArguments(ExecState*, JSLexicalEnvironment*) WTF_INTERNAL;
</ins><span class="cx"> JSCell* JIT_OPERATION operationCreateArgumentsDuringOSRExit(ExecState*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -762,7 +762,11 @@
</span><span class="cx"> LLINT_BEGIN();
</span><span class="cx"> JSValue arguments = LLINT_OP(2).jsValue();
</span><span class="cx"> if (!arguments) {
</span><del>- arguments = Arguments::create(vm, exec);
</del><ins>+ int lexicalEnvironmentReg = pc[4].u.operand;
+ JSLexicalEnvironment* lexicalEnvironment = VirtualRegister(lexicalEnvironmentReg).isValid() ?
+ exec->uncheckedR(lexicalEnvironmentReg).lexicalEnvironment() : nullptr;
+ arguments = JSValue(Arguments::create(vm, exec, lexicalEnvironment));
+
</ins><span class="cx"> LLINT_CHECK_EXCEPTION();
</span><span class="cx"> LLINT_OP(2) = arguments;
</span><span class="cx"> exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[2].u.operand)).offset()) = arguments;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.h (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.h        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.h        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -46,10 +46,10 @@
</span><span class="cx"> public:
</span><span class="cx"> typedef JSNonFinalObject Base;
</span><span class="cx">
</span><del>- static Arguments* create(VM& vm, CallFrame* callFrame, ArgumentsMode mode = NormalArgumentsCreationMode)
</del><ins>+ static Arguments* create(VM& vm, CallFrame* callFrame, JSLexicalEnvironment* lexicalEnvironment, ArgumentsMode mode = NormalArgumentsCreationMode)
</ins><span class="cx"> {
</span><span class="cx"> Arguments* arguments = new (NotNull, allocateCell<Arguments>(vm.heap, offsetOfInlineRegisterArray() + registerArraySizeInBytes(callFrame))) Arguments(callFrame);
</span><del>- arguments->finishCreation(callFrame, mode);
</del><ins>+ arguments->finishCreation(callFrame, lexicalEnvironment, mode);
</ins><span class="cx"> return arguments;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -105,7 +105,7 @@
</span><span class="cx"> protected:
</span><span class="cx"> static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSObject::StructureFlags;
</span><span class="cx">
</span><del>- void finishCreation(CallFrame*, ArgumentsMode);
</del><ins>+ void finishCreation(CallFrame*, JSLexicalEnvironment*, ArgumentsMode);
</ins><span class="cx"> void finishCreation(CallFrame*, InlineCallFrame*, ArgumentsMode);
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="lines">@@ -271,7 +271,7 @@
</span><span class="cx"> return m_lexicalEnvironment->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline void Arguments::finishCreation(CallFrame* callFrame, ArgumentsMode mode)
</del><ins>+inline void Arguments::finishCreation(CallFrame* callFrame, JSLexicalEnvironment* lexicalEnvironment, ArgumentsMode mode)
</ins><span class="cx"> {
</span><span class="cx"> Base::finishCreation(callFrame->vm());
</span><span class="cx"> ASSERT(inherits(info()));
</span><span class="lines">@@ -300,8 +300,8 @@
</span><span class="cx"> codeBlock->framePointerOffsetToGetActivationRegisters());
</span><span class="cx"> }
</span><span class="cx"> if (codeBlock->needsActivation()) {
</span><del>- RELEASE_ASSERT(callFrame->lexicalEnvironment());
- m_lexicalEnvironment.set(callFrame->vm(), this, callFrame->lexicalEnvironment());
</del><ins>+ RELEASE_ASSERT(lexicalEnvironment && lexicalEnvironment == callFrame->lexicalEnvironment());
+ m_lexicalEnvironment.set(callFrame->vm(), this, lexicalEnvironment);
</ins><span class="cx"> }
</span><span class="cx"> // The bytecode generator omits op_tear_off_lexical_environment in cases of no
</span><span class="cx"> // declared parameters, so we need to tear off immediately.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -221,7 +221,10 @@
</span><span class="cx"> SLOW_PATH_DECL(slow_path_create_arguments)
</span><span class="cx"> {
</span><span class="cx"> BEGIN();
</span><del>- JSValue arguments = JSValue(Arguments::create(vm, exec));
</del><ins>+ int lexicalEnvironmentReg = pc[2].u.operand;
+ JSLexicalEnvironment* lexicalEnvironment = VirtualRegister(lexicalEnvironmentReg).isValid() ?
+ exec->uncheckedR(lexicalEnvironmentReg).lexicalEnvironment() : nullptr;
+ JSValue arguments = JSValue(Arguments::create(vm, exec, lexicalEnvironment));
</ins><span class="cx"> CHECK_EXCEPTION();
</span><span class="cx"> exec->uncheckedR(pc[1].u.operand) = arguments;
</span><span class="cx"> exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[1].u.operand)).offset()) = arguments;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSLexicalEnvironmentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp (178142 => 178143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp        2015-01-08 23:51:11 UTC (rev 178142)
+++ trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp        2015-01-09 00:10:01 UTC (rev 178143)
</span><span class="lines">@@ -208,7 +208,7 @@
</span><span class="cx"> return JSValue::encode(arguments);
</span><span class="cx"> int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister).offset();
</span><span class="cx">
</span><del>- JSValue arguments = JSValue(Arguments::create(callFrame->vm(), callFrame));
</del><ins>+ JSValue arguments = JSValue(Arguments::create(callFrame->vm(), callFrame, lexicalEnvironment));
</ins><span class="cx"> callFrame->uncheckedR(argumentsRegister.offset()) = arguments;
</span><span class="cx"> callFrame->uncheckedR(realArgumentsRegister) = arguments;
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>