<!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>[37670] trunk/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/37670">37670</a></dd>
<dt>Author</dt> <dd>barraclough@apple.com</dd>
<dt>Date</dt> <dd>2008-10-17 19:51:52 -0700 (Fri, 17 Oct 2008)</dd>
</dl>

<h3>Log Message</h3>
<pre>2008-10-17  Gavin Barraclough  &lt;barraclough@apple.com&gt;

        Optimize op_call by allowing call sites to be directly linked to callees.

        For the hot path of op_call, CTI now generates a check (initially for an impossible
        value), and the first time the call is executed we attempt to link the call directly
        to the callee.  WWe can currently only do so if the arity of the caller and callee
        match.  The (optimized) setup for the call on the hot path is linked directly to
        the ctiCode for the callee, without indirection.
        
        Two forms of the slow case of the call are generated, the first will be executed the
        first time the call is reached.  As well as this path attempting to link the call to
        a callee, it also relinks the slow case to a second slow case, which will not continue
        to attempt relinking the call.  (This policy could be changed in future, but for not
        this is intended to prevent thrashing).

        If a callee that the caller has been linked to is garbage collected, then the link
        in the caller's JIt code will be reset back to a value that cannot match - to prevent
        any false positive matches.

        ~20% progression on deltablue &amp; richards, &gt;12% overall reduction in v8-tests
        runtime, one or two percent progression on sunspider.

        Reviewed by Oliver Hunt.

        * VM/CTI.cpp:
        (JSC::):
        (JSC::CTI::emitNakedCall):
        (JSC::unreachable):
        (JSC::CTI::compileOpCallInitializeCallFrame):
        (JSC::CTI::compileOpCallSetupArgs):
        (JSC::CTI::compileOpCall):
        (JSC::CTI::privateCompileMainPass):
        (JSC::CTI::privateCompileSlowCases):
        (JSC::CTI::privateCompile):
        (JSC::CTI::unlinkCall):
        (JSC::CTI::linkCall):
        * VM/CTI.h:
        * VM/CodeBlock.cpp:
        (JSC::CodeBlock::~CodeBlock):
        (JSC::CodeBlock::unlinkCallers):
        (JSC::CodeBlock::derefStructureIDs):
        * VM/CodeBlock.h:
        (JSC::StructureStubInfo::StructureStubInfo):
        (JSC::CallLinkInfo::CallLinkInfo):
        (JSC::CodeBlock::addCaller):
        (JSC::CodeBlock::removeCaller):
        (JSC::CodeBlock::getStubInfo):
        * VM/CodeGenerator.cpp:
        (JSC::CodeGenerator::emitCall):
        (JSC::CodeGenerator::emitConstruct):
        * VM/Machine.cpp:
        (JSC::Machine::cti_op_call_profiler):
        (JSC::Machine::cti_op_call_JSFunction):
        (JSC::Machine::cti_vm_lazyLinkCall):
        (JSC::Machine::cti_op_construct_JSConstructFast):
        (JSC::Machine::cti_op_construct_JSConstruct):
        (JSC::Machine::cti_op_construct_NotJSConstruct):
        * VM/Machine.h:
        * kjs/JSFunction.cpp:
        (JSC::JSFunction::~JSFunction):
        * kjs/JSFunction.h:
        * kjs/nodes.h:
        (JSC::FunctionBodyNode::):
        * masm/X86Assembler.h:
        (JSC::X86Assembler::getDifferenceBetweenLabels):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreChangeLog">trunk/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkJavaScriptCoreVMCTIcpp">trunk/JavaScriptCore/VM/CTI.cpp</a></li>
<li><a href="#trunkJavaScriptCoreVMCTIh">trunk/JavaScriptCore/VM/CTI.h</a></li>
<li><a href="#trunkJavaScriptCoreVMCodeBlockcpp">trunk/JavaScriptCore/VM/CodeBlock.cpp</a></li>
<li><a href="#trunkJavaScriptCoreVMCodeBlockh">trunk/JavaScriptCore/VM/CodeBlock.h</a></li>
<li><a href="#trunkJavaScriptCoreVMCodeGeneratorcpp">trunk/JavaScriptCore/VM/CodeGenerator.cpp</a></li>
<li><a href="#trunkJavaScriptCoreVMMachinecpp">trunk/JavaScriptCore/VM/Machine.cpp</a></li>
<li><a href="#trunkJavaScriptCoreVMMachineh">trunk/JavaScriptCore/VM/Machine.h</a></li>
<li><a href="#trunkJavaScriptCorekjsJSFunctioncpp">trunk/JavaScriptCore/kjs/JSFunction.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsJSFunctionh">trunk/JavaScriptCore/kjs/JSFunction.h</a></li>
<li><a href="#trunkJavaScriptCorekjsnodesh">trunk/JavaScriptCore/kjs/nodes.h</a></li>
<li><a href="#trunkJavaScriptCoremasmX86Assemblerh">trunk/JavaScriptCore/masm/X86Assembler.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/ChangeLog (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/ChangeLog        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/ChangeLog        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -1,3 +1,70 @@
</span><ins>+2008-10-17  Gavin Barraclough  &lt;barraclough@apple.com&gt;
+
+        Optimize op_call by allowing call sites to be directly linked to callees.
+
+        For the hot path of op_call, CTI now generates a check (initially for an impossible
+        value), and the first time the call is executed we attempt to link the call directly
+        to the callee.  WWe can currently only do so if the arity of the caller and callee
+        match.  The (optimized) setup for the call on the hot path is linked directly to
+        the ctiCode for the callee, without indirection.
+        
+        Two forms of the slow case of the call are generated, the first will be executed the
+        first time the call is reached.  As well as this path attempting to link the call to
+        a callee, it also relinks the slow case to a second slow case, which will not continue
+        to attempt relinking the call.  (This policy could be changed in future, but for not
+        this is intended to prevent thrashing).
+
+        If a callee that the caller has been linked to is garbage collected, then the link
+        in the caller's JIt code will be reset back to a value that cannot match - to prevent
+        any false positive matches.
+
+        ~20% progression on deltablue &amp; richards, &gt;12% overall reduction in v8-tests
+        runtime, one or two percent progression on sunspider.
+
+        Reviewed by Oliver Hunt.
+
+        * VM/CTI.cpp:
+        (JSC::):
+        (JSC::CTI::emitNakedCall):
+        (JSC::unreachable):
+        (JSC::CTI::compileOpCallInitializeCallFrame):
+        (JSC::CTI::compileOpCallSetupArgs):
+        (JSC::CTI::compileOpCall):
+        (JSC::CTI::privateCompileMainPass):
+        (JSC::CTI::privateCompileSlowCases):
+        (JSC::CTI::privateCompile):
+        (JSC::CTI::unlinkCall):
+        (JSC::CTI::linkCall):
+        * VM/CTI.h:
+        * VM/CodeBlock.cpp:
+        (JSC::CodeBlock::~CodeBlock):
+        (JSC::CodeBlock::unlinkCallers):
+        (JSC::CodeBlock::derefStructureIDs):
+        * VM/CodeBlock.h:
+        (JSC::StructureStubInfo::StructureStubInfo):
+        (JSC::CallLinkInfo::CallLinkInfo):
+        (JSC::CodeBlock::addCaller):
+        (JSC::CodeBlock::removeCaller):
+        (JSC::CodeBlock::getStubInfo):
+        * VM/CodeGenerator.cpp:
+        (JSC::CodeGenerator::emitCall):
+        (JSC::CodeGenerator::emitConstruct):
+        * VM/Machine.cpp:
+        (JSC::Machine::cti_op_call_profiler):
+        (JSC::Machine::cti_op_call_JSFunction):
+        (JSC::Machine::cti_vm_lazyLinkCall):
+        (JSC::Machine::cti_op_construct_JSConstructFast):
+        (JSC::Machine::cti_op_construct_JSConstruct):
+        (JSC::Machine::cti_op_construct_NotJSConstruct):
+        * VM/Machine.h:
+        * kjs/JSFunction.cpp:
+        (JSC::JSFunction::~JSFunction):
+        * kjs/JSFunction.h:
+        * kjs/nodes.h:
+        (JSC::FunctionBodyNode::):
+        * masm/X86Assembler.h:
+        (JSC::X86Assembler::getDifferenceBetweenLabels):
+
</ins><span class="cx"> 2008-10-17  Maciej Stachowiak  &lt;mjs@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoff Garen.
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCTIcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CTI.cpp (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CTI.cpp        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/VM/CTI.cpp        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -95,11 +95,13 @@
</span><span class="cx"> SYMBOL_STRING(ctiTrampoline) &quot;:&quot; &quot;\n&quot;
</span><span class="cx">     &quot;pushl %esi&quot; &quot;\n&quot;
</span><span class="cx">     &quot;pushl %edi&quot; &quot;\n&quot;
</span><del>-    &quot;subl $0x24, %esp&quot; &quot;\n&quot;
</del><ins>+    &quot;pushl %ebx&quot; &quot;\n&quot;
+    &quot;subl $0x20, %esp&quot; &quot;\n&quot;
</ins><span class="cx">     &quot;movl $512, %esi&quot; &quot;\n&quot;
</span><span class="cx">     &quot;movl 0x38(%esp), %edi&quot; &quot;\n&quot; // Ox38 = 0x0E * 4, 0x0E = CTI_ARGS_callFrame (see assertion above)
</span><span class="cx">     &quot;call *0x30(%esp)&quot; &quot;\n&quot; // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
</span><del>-    &quot;addl $0x24, %esp&quot; &quot;\n&quot;
</del><ins>+    &quot;addl $0x20, %esp&quot; &quot;\n&quot;
+    &quot;popl %ebx&quot; &quot;\n&quot;
</ins><span class="cx">     &quot;popl %edi&quot; &quot;\n&quot;
</span><span class="cx">     &quot;popl %esi&quot; &quot;\n&quot;
</span><span class="cx">     &quot;ret&quot; &quot;\n&quot;
</span><span class="lines">@@ -118,7 +120,8 @@
</span><span class="cx"> #else
</span><span class="cx">     &quot;call &quot; SYMBOL_STRING(_ZN3JSC7Machine12cti_vm_throwEPvz) &quot;\n&quot;
</span><span class="cx"> #endif
</span><del>-    &quot;addl $0x24, %esp&quot; &quot;\n&quot;
</del><ins>+    &quot;addl $0x20, %esp&quot; &quot;\n&quot;
+    &quot;popl %ebx&quot; &quot;\n&quot;
</ins><span class="cx">     &quot;popl %edi&quot; &quot;\n&quot;
</span><span class="cx">     &quot;popl %esi&quot; &quot;\n&quot;
</span><span class="cx">     &quot;ret&quot; &quot;\n&quot;
</span><span class="lines">@@ -133,12 +136,14 @@
</span><span class="cx">         __asm {
</span><span class="cx">             push esi;
</span><span class="cx">             push edi;
</span><del>-            sub esp, 0x24;
</del><ins>+            push ebx;
+            sub esp, 0x20;
</ins><span class="cx">             mov esi, 512;
</span><span class="cx">             mov ecx, esp;
</span><span class="cx">             mov edi, [esp + 0x38];
</span><span class="cx">             call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
</span><del>-            add esp, 0x24;
</del><ins>+            add esp, 0x20;
+            pop ebx;
</ins><span class="cx">             pop edi;
</span><span class="cx">             pop esi;
</span><span class="cx">             ret;
</span><span class="lines">@@ -150,7 +155,8 @@
</span><span class="cx">         __asm {
</span><span class="cx">             mov ecx, esp;
</span><span class="cx">             call JSC::Machine::cti_vm_throw;
</span><del>-            add esp, 0x24;
</del><ins>+            add esp, 0x20;
+            pop ebx;
</ins><span class="cx">             pop edi;
</span><span class="cx">             pop esi;
</span><span class="cx">             ret;
</span><span class="lines">@@ -303,15 +309,21 @@
</span><span class="cx"> 
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, X86::RegisterID r)
</del><ins>+ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitNakedCall(unsigned opcodeIndex, X86::RegisterID r)
</ins><span class="cx"> {
</span><del>-    m_jit.emitRestoreArgumentReference();
</del><span class="cx">     X86Assembler::JmpSrc call = m_jit.emitCall(r);
</span><span class="cx">     m_calls.append(CallRecord(call, opcodeIndex));
</span><span class="cx"> 
</span><span class="cx">     return call;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE  X86Assembler::JmpSrc CTI::emitNakedCall(unsigned opcodeIndex, void(*function)())
+{
+    X86Assembler::JmpSrc call = m_jit.emitCall();
+    m_calls.append(CallRecord(call, reinterpret_cast&lt;CTIHelper_v&gt;(function), opcodeIndex));
+    return call;
+}
+
</ins><span class="cx"> ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(unsigned opcodeIndex, CTIHelper_j helper)
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(SAMPLING_TOOL)
</span><span class="lines">@@ -511,6 +523,12 @@
</span><span class="cx"> OpcodeID currentOpcodeID = static_cast&lt;OpcodeID&gt;(-1);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+static void unreachable()
+{
+    ASSERT_NOT_REACHED();
+    exit(1);
+}
+
</ins><span class="cx"> void CTI::compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount)
</span><span class="cx"> {
</span><span class="cx">     emitGetArg(callee, X86::ecx); // Load callee JSFunction into ecx
</span><span class="lines">@@ -518,92 +536,103 @@
</span><span class="cx">     m_jit.movl_i32m(reinterpret_cast&lt;unsigned&gt;(nullJSValue), RegisterFile::OptionalCalleeArguments * static_cast&lt;int&gt;(sizeof(Register)), X86::edx);
</span><span class="cx">     m_jit.movl_rm(X86::ecx, RegisterFile::Callee * static_cast&lt;int&gt;(sizeof(Register)), X86::edx);
</span><span class="cx"> 
</span><del>-    m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeChain, m_node), X86::ecx, X86::ecx); // newScopeChain
</del><ins>+    m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeChain, m_node), X86::ecx, X86::ebx); // newScopeChain
</ins><span class="cx">     m_jit.movl_i32m(argCount, RegisterFile::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)), X86::edx);
</span><span class="cx">     m_jit.movl_rm(X86::edi, RegisterFile::CallerFrame * static_cast&lt;int&gt;(sizeof(Register)), X86::edx);
</span><del>-    m_jit.movl_rm(X86::ecx, RegisterFile::ScopeChain * static_cast&lt;int&gt;(sizeof(Register)), X86::edx);
</del><ins>+    m_jit.movl_rm(X86::ebx, RegisterFile::ScopeChain * static_cast&lt;int&gt;(sizeof(Register)), X86::edx);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CTI::compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type)
</del><ins>+void CTI::compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval)
</ins><span class="cx"> {
</span><del>-    int dst = instruction[i + 1].u.operand;
-    int callee = instruction[i + 2].u.operand;
-    int firstArg = instruction[i + 4].u.operand;
-    int argCount = instruction[i + 5].u.operand;
-    int registerOffset = instruction[i + 6].u.operand;
</del><ins>+    int firstArg = instruction[4].u.operand;
+    int argCount = instruction[5].u.operand;
+    int registerOffset = instruction[6].u.operand;
</ins><span class="cx"> 
</span><del>-    if (type == OpCallEval)
-        emitGetPutArg(instruction[i + 3].u.operand, 16, X86::ecx);
</del><ins>+    emitPutArg(X86::ecx, 0);
+    emitPutArgConstant(registerOffset, 4);
+    emitPutArgConstant(argCount, 8);
+    emitPutArgConstant(reinterpret_cast&lt;unsigned&gt;(instruction), 12);
+    if (isConstruct) {
+        emitGetPutArg(instruction[3].u.operand, 16, X86::eax);
+        emitPutArgConstant(firstArg, 20);
+    } else if (isEval)
+        emitGetPutArg(instruction[3].u.operand, 16, X86::eax);
+}
</ins><span class="cx"> 
</span><del>-    if (type == OpConstruct) {
-        emitPutArgConstant(reinterpret_cast&lt;unsigned&gt;(instruction + i), 20);
-        emitPutArgConstant(argCount, 16);
-        emitPutArgConstant(registerOffset, 12);
-        emitPutArgConstant(firstArg, 8);
-        emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
-    } else {
-        emitPutArgConstant(reinterpret_cast&lt;unsigned&gt;(instruction + i), 12);
-        emitPutArgConstant(argCount, 8);
-        emitPutArgConstant(registerOffset, 4);
</del><ins>+void CTI::compileOpCall(Instruction* instruction, unsigned i, unsigned structureIDInstructionIndex, CompileOpCallType type)
+{
+    int dst = instruction[1].u.operand;
+    int callee = instruction[2].u.operand;
+    int firstArg = instruction[4].u.operand;
+    int argCount = instruction[5].u.operand;
+    int registerOffset = instruction[6].u.operand;
</ins><span class="cx"> 
</span><del>-        int thisVal = instruction[i + 3].u.operand;
</del><ins>+    // Setup this value as the first argument (does not apply to constructors)
+    if (type != OpConstruct) {
+        int thisVal = instruction[3].u.operand;
</ins><span class="cx">         if (thisVal == missingThisObjectMarker()) {
</span><span class="cx">             // FIXME: should this be loaded dynamically off m_callFrame?
</span><span class="cx">             m_jit.movl_i32m(reinterpret_cast&lt;unsigned&gt;(m_callFrame-&gt;globalThisValue()), firstArg * sizeof(Register), X86::edi);
</span><span class="cx">         } else {
</span><del>-            emitGetArg(thisVal, X86::ecx);
-            emitPutResult(firstArg, X86::ecx);
</del><ins>+            emitGetArg(thisVal, X86::eax);
+            emitPutResult(firstArg);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Handle eval
</ins><span class="cx">     X86Assembler::JmpSrc wasEval;
</span><span class="cx">     if (type == OpCallEval) {
</span><del>-        emitGetPutArg(callee, 0, X86::ecx);
</del><ins>+        emitGetArg(callee, X86::ecx);
+        compileOpCallSetupArgs(instruction, false, true);
+
</ins><span class="cx">         emitCTICall(i, Machine::cti_op_call_eval);
</span><del>-
</del><span class="cx">         m_jit.cmpl_i32r(reinterpret_cast&lt;unsigned&gt;(JSImmediate::impossibleValue()), X86::eax);
</span><span class="cx">         wasEval = m_jit.emitUnlinkedJne();
</span><del>-
-        // this sets up the first arg to op_cti_call (func), and explicitly leaves the value in ecx (checked just below).
-        emitGetArg(callee, X86::ecx);
-    } else {
-        // this sets up the first arg to op_cti_call (func), and explicitly leaves the value in ecx (checked just below).
-        emitGetPutArg(callee, 0, X86::ecx);
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Fast check for JS function.
-    m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx);
-    X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne();
-    m_jit.cmpl_i32m(reinterpret_cast&lt;unsigned&gt;(m_machine-&gt;m_jsFunctionVptr), X86::ecx);
-    X86Assembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe();
-    m_jit.link(isNotObject, m_jit.label());
</del><ins>+    // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
+    // This deliberately leaves the callee in ecx, used when setting up the stack frame below
+    emitGetArg(callee, X86::ecx);
+    m_jit.cmpl_i32r(reinterpret_cast&lt;unsigned&gt;(JSImmediate::impossibleValue()), X86::ecx);
+    X86Assembler::JmpDst addressOfLinkedFunctionCheck = m_jit.label();
+    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+    ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck, m_jit.label()) == repatchOffsetOpCallCall);
+    m_structureStubCompilationInfo[structureIDInstructionIndex].hotPathBegin = addressOfLinkedFunctionCheck;
</ins><span class="cx"> 
</span><del>-    // This handles host functions
-    emitCTICall(i, ((type == OpConstruct) ? Machine::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction));
</del><ins>+    // The following is the fast case, only used whan a callee can be linked.
</ins><span class="cx"> 
</span><del>-    X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp();
-    m_jit.link(isJSFunction, m_jit.label());
</del><ins>+    emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
+    m_jit.cmpl_i32m(0, X86::eax);
+    X86Assembler::JmpSrc noProfile = m_jit.emitUnlinkedJe();
+    emitPutArg(X86::ecx, 0);
+    emitCTICall(i, Machine::cti_op_call_profiler);
+    emitGetArg(callee, X86::ecx);
+    m_jit.link(noProfile, m_jit.label());
</ins><span class="cx"> 
</span><del>-    // This handles JSFunctions
-    emitCTICall(i, (type == OpConstruct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction);
</del><ins>+    // In the case of OpConstruct, call oout to a cti_ function to create the new object.
+    if (type == OpConstruct) {
+        emitPutArg(X86::ecx, 0);
+        emitGetPutArg(instruction[3].u.operand, 4, X86::eax);
+        emitCTICall(i, Machine::cti_op_construct_JSConstructFast);
+        emitPutResult(instruction[4].u.operand);
+        emitGetArg(callee, X86::ecx);
+    }
</ins><span class="cx"> 
</span><del>-    compileOpCallInitializeCallFrame(callee, argCount);
</del><ins>+    // Fast version of stack frame initialization, directly relative to edi.
+    // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
+    m_jit.movl_i32m(reinterpret_cast&lt;unsigned&gt;(nullJSValue), (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast&lt;int&gt;(sizeof(Register)), X86::edi);
+    m_jit.movl_rm(X86::ecx, (registerOffset + RegisterFile::Callee) * static_cast&lt;int&gt;(sizeof(Register)), X86::edi);
+    m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeChain, m_node), X86::ecx, X86::edx); // newScopeChain
+    m_jit.movl_i32m(argCount, (registerOffset + RegisterFile::ArgumentCount) * static_cast&lt;int&gt;(sizeof(Register)), X86::edi);
+    m_jit.movl_rm(X86::edi, (registerOffset + RegisterFile::CallerFrame) * static_cast&lt;int&gt;(sizeof(Register)), X86::edi);
+    m_jit.movl_rm(X86::edx, (registerOffset + RegisterFile::ScopeChain) * static_cast&lt;int&gt;(sizeof(Register)), X86::edi);
+    m_jit.addl_i32r(registerOffset * sizeof(Register), X86::edi);
</ins><span class="cx"> 
</span><del>-    // load ctiCode from the new codeBlock.
-    m_jit.movl_mr(OBJECT_OFFSET(CodeBlock, ctiCode), X86::eax, X86::eax);
-
-    // Put the new value of 'callFrame' into edi and onto the stack, too.
-    m_jit.movl_rr(X86::edx, X86::edi);
-
-    // Check the ctiCode has been generated - if not, this is handled in a slow case.
-    m_jit.testl_rr(X86::eax, X86::eax);
-    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i));
-    emitCall(i, X86::eax);
</del><ins>+    // Call to the callee
+    m_structureStubCompilationInfo[structureIDInstructionIndex].hotPathOther = emitNakedCall(i, unreachable);
</ins><span class="cx">     
</span><del>-    X86Assembler::JmpDst end = m_jit.label();
-    m_jit.link(wasNotJSFunction, end);
</del><span class="cx">     if (type == OpCallEval)
</span><del>-        m_jit.link(wasEval, end);
</del><ins>+        m_jit.link(wasEval, m_jit.label());
</ins><span class="cx"> 
</span><span class="cx">     // Put the return value in dst. In the interpreter, op_ret does this.
</span><span class="cx">     emitPutResult(dst);
</span><span class="lines">@@ -1214,7 +1243,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_call: {
</span><del>-            compileOpCall(instruction, i);
</del><ins>+            compileOpCall(instruction + i, i, structureIDInstructionIndex++);
</ins><span class="cx">             i += 7;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -1321,7 +1350,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_construct: {
</span><del>-            compileOpCall(instruction, i, OpConstruct);
</del><ins>+            compileOpCall(instruction + i, i, structureIDInstructionIndex++, OpConstruct);
</ins><span class="cx">             i += 7;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -1754,14 +1783,15 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_call_eval: {
</span><del>-            compileOpCall(instruction, i, OpCallEval);
</del><ins>+            compileOpCall(instruction + i, i, structureIDInstructionIndex++, OpCallEval);
</ins><span class="cx">             i += 7;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_throw: {
</span><span class="cx">             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
</span><span class="cx">             emitCTICall(i, Machine::cti_op_throw);
</span><del>-            m_jit.addl_i8r(0x24, X86::esp);
</del><ins>+            m_jit.addl_i8r(0x20, X86::esp);
+            m_jit.popl_r(X86::ebx);
</ins><span class="cx">             m_jit.popl_r(X86::edi);
</span><span class="cx">             m_jit.popl_r(X86::esi);
</span><span class="cx">             m_jit.ret();
</span><span class="lines">@@ -2112,7 +2142,7 @@
</span><span class="cx">     Instruction* instruction = m_codeBlock-&gt;instructions.begin();
</span><span class="cx">     for (Vector&lt;SlowCaseEntry&gt;::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
</span><span class="cx">         unsigned i = iter-&gt;to;
</span><del>-        switch (m_machine-&gt;getOpcodeID(instruction[i].u.opcode)) {
</del><ins>+        switch (OpcodeID opcodeID = m_machine-&gt;getOpcodeID(instruction[i].u.opcode)) {
</ins><span class="cx">         case op_convert_this: {
</span><span class="cx">             m_jit.link(iter-&gt;from, m_jit.label());
</span><span class="cx">             m_jit.link((++iter)-&gt;from, m_jit.label());
</span><span class="lines">@@ -2577,16 +2607,97 @@
</span><span class="cx">         case op_call:
</span><span class="cx">         case op_call_eval:
</span><span class="cx">         case op_construct: {
</span><ins>+            int dst = instruction[i + 1].u.operand;
+            int callee = instruction[i + 2].u.operand;
+            int argCount = instruction[i + 5].u.operand;
+
</ins><span class="cx">             m_jit.link(iter-&gt;from, m_jit.label());
</span><span class="cx"> 
</span><del>-            // We jump to this slow case if the ctiCode for the codeBlock has not yet been generated; compile it now.
</del><ins>+            // The arguments have been set up on the hot path for op_call_eval
+            if (opcodeID != op_call_eval)
+                compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false);
+
+            // Fast check for JS function.
+            m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx);
+            X86Assembler::JmpSrc callLinkFailNotObject = m_jit.emitUnlinkedJne();
+            m_jit.cmpl_i32m(reinterpret_cast&lt;unsigned&gt;(m_machine-&gt;m_jsFunctionVptr), X86::ecx);
+            X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJne();
+
+            // This handles JSFunctions
+            emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
+            m_jit.cmpl_i32m(0, X86::eax);
+            X86Assembler::JmpSrc noProfile1 = m_jit.emitUnlinkedJe();
+            emitCTICall(i, Machine::cti_op_call_profiler);
+            m_jit.link(noProfile1, m_jit.label());
+
+            emitCTICall(i, (opcodeID == op_construct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction);
+            // initialize the new call frame (pointed to by edx, after the last call), then set edi to point to it.
+            compileOpCallInitializeCallFrame(callee, argCount);
+            m_jit.movl_rr(X86::edx, X86::edi);
+
+            // Try to link &amp; repatch this call.
+            m_structureStubCompilationInfo[structureIDInstructionIndex].callReturnLocation =
+                emitCTICall(i, Machine::cti_vm_lazyLinkCall);
+            emitNakedCall(i, X86::eax);
+            X86Assembler::JmpSrc storeResultForFirstRun = m_jit.emitUnlinkedJmp();
+
+            // This is the address for the cold path *after* the first run (which tries to link the call).
+            m_structureStubCompilationInfo[structureIDInstructionIndex].coldPathOther = m_jit.label();
+
+            // The arguments have been set up on the hot path for op_call_eval
+            if (opcodeID != op_call_eval)
+                compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false);
+
+            // Check for JSFunctions.
+            m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx);
+            X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne();
+            m_jit.cmpl_i32m(reinterpret_cast&lt;unsigned&gt;(m_machine-&gt;m_jsFunctionVptr), X86::ecx);
+            X86Assembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe();
+
+            // This handles host functions
+            X86Assembler::JmpDst notJSFunctionlabel = m_jit.label();
+            m_jit.link(isNotObject, notJSFunctionlabel);
+            m_jit.link(callLinkFailNotObject, notJSFunctionlabel);
+            m_jit.link(callLinkFailNotJSFunction, notJSFunctionlabel);
+            emitCTICall(i, ((opcodeID == op_construct) ? Machine::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction));
+            X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp();
+
+            // Next, handle JSFunctions...
+            m_jit.link(isJSFunction, m_jit.label());
+
+            // Profiler check
+            emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
+            m_jit.cmpl_i32m(0, X86::eax);
+            X86Assembler::JmpSrc noProfile = m_jit.emitUnlinkedJe();
+            emitCTICall(i, Machine::cti_op_call_profiler);
+            m_jit.link(noProfile, m_jit.label());
+
+            emitCTICall(i, (opcodeID == op_construct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction);
+            // initialize the new call frame (pointed to by edx, after the last call).
+            compileOpCallInitializeCallFrame(callee, argCount);
+            m_jit.movl_rr(X86::edx, X86::edi);
+
+            // load ctiCode from the new codeBlock.
+            m_jit.movl_mr(OBJECT_OFFSET(CodeBlock, ctiCode), X86::eax, X86::eax);
+
+            // Move the new callframe into edi.
+            m_jit.movl_rr(X86::edx, X86::edi);
+
+            // Check the ctiCode has been generated (if not compile it now), and make the call.
+            m_jit.testl_rr(X86::eax, X86::eax);
+            X86Assembler::JmpSrc hasCode = m_jit.emitUnlinkedJne();
</ins><span class="cx">             emitCTICall(i, Machine::cti_vm_compile);
</span><del>-            emitCall(i, X86::eax);
</del><ins>+            m_jit.link(hasCode, m_jit.label());
</ins><span class="cx"> 
</span><del>-            // Instead of checking for 0 we could initialize the CodeBlock::ctiCode to point to a trampoline that would trigger the translation.
</del><ins>+            emitNakedCall(i, X86::eax);
</ins><span class="cx"> 
</span><span class="cx">             // Put the return value in dst. In the interpreter, op_ret does this.
</span><del>-            emitPutResult(instruction[i + 1].u.operand);
</del><ins>+            X86Assembler::JmpDst storeResult = m_jit.label();
+            m_jit.link(wasNotJSFunction, storeResult);
+            m_jit.link(storeResultForFirstRun, storeResult);
+            emitPutResult(dst);
+
+            ++structureIDInstructionIndex;
</ins><span class="cx">             i += 7;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -2622,6 +2733,9 @@
</span><span class="cx">     X86Assembler::JmpSrc slowRegisterFileCheck;
</span><span class="cx">     X86Assembler::JmpDst afterRegisterFileCheck;
</span><span class="cx">     if (m_codeBlock-&gt;codeType == FunctionCode) {
</span><ins>+        // In the case of a fast linked call, we do not set this up in the caller.
+        m_jit.movl_i32m(reinterpret_cast&lt;unsigned&gt;(m_codeBlock), RegisterFile::CodeBlock * static_cast&lt;int&gt;(sizeof(Register)), X86::edi);
+
</ins><span class="cx">         emitGetCTIParam(CTI_ARGS_registerFile, X86::eax);
</span><span class="cx">         m_jit.leal_mr(m_codeBlock-&gt;numCalleeRegisters * sizeof(Register), X86::edi, X86::edx);
</span><span class="cx">         m_jit.cmpl_mr(OBJECT_OFFSET(RegisterFile, m_end), X86::eax, X86::edx);
</span><span class="lines">@@ -2690,6 +2804,8 @@
</span><span class="cx">         StructureStubInfo&amp; info = m_codeBlock-&gt;structureIDInstructions[i];
</span><span class="cx">         info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].callReturnLocation);
</span><span class="cx">         info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].hotPathBegin);
</span><ins>+        info.hotPathOther = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].hotPathOther);
+        info.coldPathOther = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].coldPathOther);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_codeBlock-&gt;ctiCode = code;
</span><span class="lines">@@ -2972,6 +3088,33 @@
</span><span class="cx">     ctiRepatchCallByReturnAddress(returnAddress, code);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CTI::unlinkCall(StructureStubInfo* structureStubInfo)
+{
+    // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid
+    // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive
+    // match).  Reset the check so it no longer matches.
+    reinterpret_cast&lt;void**&gt;(structureStubInfo-&gt;hotPathBegin)[-1] = JSImmediate::impossibleValue();
+}
+
+void CTI::linkCall(CodeBlock* callerCodeBlock, JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, void* returnAddress, int callerArgCount)
+{
+    StructureStubInfo&amp; stubInfo = callerCodeBlock-&gt;getStubInfo(returnAddress);
+
+    // Currently we only link calls with the exact number of arguments.
+    if (callerArgCount == calleeCodeBlock-&gt;numParameters) {
+        ASSERT(!stubInfo.linkInfoPtr);
+    
+        calleeCodeBlock-&gt;addCaller(&amp;stubInfo);
+    
+        reinterpret_cast&lt;void**&gt;(stubInfo.hotPathBegin)[-1] = callee;
+        ctiRepatchCallByReturnAddress(stubInfo.hotPathOther, ctiCode);
+    }
+
+    // repatch the instruction that jumps out to the cold path, so that we only try to link once.
+    void* repatchCheck = reinterpret_cast&lt;void*&gt;(reinterpret_cast&lt;ptrdiff_t&gt;(stubInfo.hotPathBegin) + repatchOffsetOpCallCall);
+    ctiRepatchCallByReturnAddress(repatchCheck, stubInfo.coldPathOther);
+}
+
</ins><span class="cx"> void* CTI::privateCompileArrayLengthTrampoline()
</span><span class="cx"> {
</span><span class="cx">     // Check eax is an array
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCTIh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CTI.h (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CTI.h        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/VM/CTI.h        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -66,6 +66,7 @@
</span><span class="cx"> #define ARG_int3 ((int)((ARGS)[3]))
</span><span class="cx"> #define ARG_int4 ((int)((ARGS)[4]))
</span><span class="cx"> #define ARG_int5 ((int)((ARGS)[5]))
</span><ins>+#define ARG_int6 ((int)((ARGS)[6]))
</ins><span class="cx"> #define ARG_func1 ((FuncDeclNode*)((ARGS)[1]))
</span><span class="cx"> #define ARG_funcexp1 ((FuncExprNode*)((ARGS)[1]))
</span><span class="cx"> #define ARG_registers1 ((Register*)((ARGS)[1]))
</span><span class="lines">@@ -94,6 +95,7 @@
</span><span class="cx">     class StructureIDChain;
</span><span class="cx">     struct Instruction;
</span><span class="cx">     struct OperandTypes;
</span><ins>+    struct StructureStubInfo;
</ins><span class="cx"> 
</span><span class="cx">     typedef JSValue* (SFX_CALL *CTIHelper_j)(CTI_ARGS);
</span><span class="cx">     typedef JSPropertyNameIterator* (SFX_CALL *CTIHelper_p)(CTI_ARGS);
</span><span class="lines">@@ -222,6 +224,8 @@
</span><span class="cx">     struct StructureStubCompilationInfo {
</span><span class="cx">         X86Assembler::JmpSrc callReturnLocation;
</span><span class="cx">         X86Assembler::JmpDst hotPathBegin;
</span><ins>+        X86Assembler::JmpSrc hotPathOther;
+        X86Assembler::JmpDst coldPathOther;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     extern &quot;C&quot; {
</span><span class="lines">@@ -257,6 +261,7 @@
</span><span class="cx"> #else
</span><span class="cx">         static const int repatchOffsetGetByIdSlowCaseCall = 17 + 4 + ctiArgumentInitSize;
</span><span class="cx"> #endif
</span><ins>+        static const int repatchOffsetOpCallCall = 6;
</ins><span class="cx"> 
</span><span class="cx">     public:
</span><span class="cx">         static void compile(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock)
</span><span class="lines">@@ -320,6 +325,9 @@
</span><span class="cx">             return cti.privateCompilePatchGetArrayLength(returnAddress);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        static void linkCall(CodeBlock* callerCodeBlock, JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, void* returnAddress, int callerArgCount);
+        static void unlinkCall(StructureStubInfo*);
+
</ins><span class="cx">         inline static JSValue* execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue** exception)
</span><span class="cx">         {
</span><span class="cx">             return ctiTrampoline(code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData);
</span><span class="lines">@@ -346,8 +354,9 @@
</span><span class="cx">         void privateCompilePatchGetArrayLength(void* returnAddress);
</span><span class="cx"> 
</span><span class="cx">         enum CompileOpCallType { OpCallNormal, OpCallEval, OpConstruct };
</span><del>-        void compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type = OpCallNormal);
</del><ins>+        void compileOpCall(Instruction* instruction, unsigned i, unsigned structureIDInstructionIndex, CompileOpCallType type = OpCallNormal);
</ins><span class="cx">         void compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount);
</span><ins>+        void compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval);
</ins><span class="cx">         enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
</span><span class="cx">         void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type);
</span><span class="cx">         void putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell,  X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2);
</span><span class="lines">@@ -388,7 +397,8 @@
</span><span class="cx"> 
</span><span class="cx">         void emitTagAsBoolImmediate(X86Assembler::RegisterID reg);
</span><span class="cx"> 
</span><del>-        X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, X86::RegisterID);
</del><ins>+        X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, X86::RegisterID);
+        X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, void(*function)());
</ins><span class="cx">         X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_j);
</span><span class="cx">         X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_p);
</span><span class="cx">         X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_v);
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CodeBlock.cpp (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CodeBlock.cpp        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/VM/CodeBlock.cpp        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CTI.h&quot;
</ins><span class="cx"> #include &quot;JSValue.h&quot;
</span><span class="cx"> #include &quot;Machine.h&quot;
</span><span class="cx"> #include &quot;debugger.h&quot;
</span><span class="lines">@@ -931,13 +932,34 @@
</span><span class="cx">         derefStructureIDs(&amp;instructions[structureIDInstructions[i].opcodeIndex]);
</span><span class="cx">         if (structureIDInstructions[i].stubRoutine)
</span><span class="cx">             fastFree(structureIDInstructions[i].stubRoutine);
</span><ins>+        if (CallLinkInfo* callLinkInfo = structureIDInstructions[i].linkInfoPtr) {
+            callLinkInfo-&gt;callee-&gt;removeCaller(callLinkInfo);
+            delete callLinkInfo;
+        }
</ins><span class="cx">     }
</span><del>-#if ENABLE(CTI)
</del><ins>+
+#if ENABLE(CTI) 
+    unlinkCallers();
+
</ins><span class="cx">     if (ctiCode)
</span><span class="cx">         fastFree(ctiCode);
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(CTI) 
+void CodeBlock::unlinkCallers()
+{
+    size_t size = linkedCallerList.size();
+    for (size_t i = 0; i &lt; size; ++i) {
+        CallLinkInfo* currentCaller = linkedCallerList[i];
+        CTI::unlinkCall(currentCaller-&gt;callerStructureStubInfo);
+        currentCaller-&gt;callerStructureStubInfo-&gt;linkInfoPtr = 0;
+        delete currentCaller;
+    }
+    linkedCallerList.clear();
+}
+#endif
+
</ins><span class="cx"> void CodeBlock::derefStructureIDs(Instruction* vPC) const
</span><span class="cx"> {
</span><span class="cx">     Machine* machine = globalData-&gt;machine;
</span><span class="lines">@@ -973,7 +995,8 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // These instructions don't ref their StructureIDs.
</span><del>-    ASSERT(vPC[0].u.opcode == machine-&gt;getOpcode(op_get_by_id) || vPC[0].u.opcode == machine-&gt;getOpcode(op_put_by_id) || vPC[0].u.opcode == machine-&gt;getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == machine-&gt;getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == machine-&gt;getOpcode(op_get_array_length) || vPC[0].u.opcode == machine-&gt;getOpcode(op_get_string_length));
</del><ins>+    ASSERT(vPC[0].u.opcode == machine-&gt;getOpcode(op_get_by_id) || vPC[0].u.opcode == machine-&gt;getOpcode(op_put_by_id) || vPC[0].u.opcode == machine-&gt;getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == machine-&gt;getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == machine-&gt;getOpcode(op_get_array_length) || vPC[0].u.opcode == machine-&gt;getOpcode(op_get_string_length)
+        || vPC[0].u.opcode == machine-&gt;getOpcode(op_call_eval) || vPC[0].u.opcode == machine-&gt;getOpcode(op_call) || vPC[0].u.opcode == machine-&gt;getOpcode(op_construct));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::refStructureIDs(Instruction* vPC) const
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CodeBlock.h (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CodeBlock.h        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/VM/CodeBlock.h        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -78,12 +78,17 @@
</span><span class="cx"> #endif
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    struct CallLinkInfo;
+
</ins><span class="cx">     struct StructureStubInfo {
</span><span class="cx">         StructureStubInfo(unsigned opcodeIndex)
</span><span class="cx">             : opcodeIndex(opcodeIndex)
</span><span class="cx">             , stubRoutine(0)
</span><span class="cx">             , callReturnLocation(0)
</span><span class="cx">             , hotPathBegin(0)
</span><ins>+            , hotPathOther(0)
+            , coldPathOther(0)
+            , linkInfoPtr(0)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx">     
</span><span class="lines">@@ -91,8 +96,23 @@
</span><span class="cx">         void* stubRoutine;
</span><span class="cx">         void* callReturnLocation;
</span><span class="cx">         void* hotPathBegin;
</span><ins>+        void* hotPathOther;
+        void* coldPathOther;
+        CallLinkInfo* linkInfoPtr;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    struct CallLinkInfo {
+        CodeBlock* callee;
+        StructureStubInfo* callerStructureStubInfo;
+        unsigned position;
+
+        CallLinkInfo(CodeBlock* c, StructureStubInfo* css)
+        {
+            callee = c;
+            callerStructureStubInfo = css;
+        }
+    };
+
</ins><span class="cx">     struct StringJumpTable {
</span><span class="cx">         typedef HashMap&lt;RefPtr&lt;UString::Rep&gt;, OffsetLocation&gt; StringOffsetTable;
</span><span class="cx">         StringOffsetTable offsetTable;
</span><span class="lines">@@ -203,6 +223,30 @@
</span><span class="cx"> 
</span><span class="cx">         ~CodeBlock();
</span><span class="cx"> 
</span><ins>+#if ENABLE(CTI) 
+        void unlinkCallers();
+#endif
+
+        void addCaller(StructureStubInfo* caller)
+        {
+            CallLinkInfo* callLinkInfo = new CallLinkInfo(this, caller);
+            caller-&gt;linkInfoPtr = callLinkInfo;
+            callLinkInfo-&gt;position = linkedCallerList.size();
+            linkedCallerList.append(callLinkInfo);
+        }
+
+        void removeCaller(CallLinkInfo* caller)
+        {
+            unsigned pos = caller-&gt;position;
+            unsigned lastPos = linkedCallerList.size() - 1;
+
+            if (pos != lastPos) {
+                linkedCallerList[pos] = linkedCallerList[lastPos];
+                linkedCallerList[pos]-&gt;position = pos;
+            }
+            linkedCallerList.shrink(lastPos);
+        }
+
</ins><span class="cx"> #if !defined(NDEBUG) || ENABLE_SAMPLING_TOOL
</span><span class="cx">         void dump(ExecState*) const;
</span><span class="cx">         void printStructureIDs(const Instruction*) const;
</span><span class="lines">@@ -221,6 +265,7 @@
</span><span class="cx">         {
</span><span class="cx">             // FIXME: would a binary chop be faster here?
</span><span class="cx">             for (unsigned i = 0; ; ++i) {
</span><ins>+                ASSERT(i &lt; structureIDInstructions.size());
</ins><span class="cx">                 if (structureIDInstructions[i].callReturnLocation == returnAddress)
</span><span class="cx">                     return structureIDInstructions[i];
</span><span class="cx">             }
</span><span class="lines">@@ -251,6 +296,7 @@
</span><span class="cx"> 
</span><span class="cx">         Vector&lt;Instruction&gt; instructions;
</span><span class="cx">         Vector&lt;StructureStubInfo&gt; structureIDInstructions;
</span><ins>+        Vector&lt;CallLinkInfo*&gt; linkedCallerList;
</ins><span class="cx"> 
</span><span class="cx">         // Constant pool
</span><span class="cx">         Vector&lt;Identifier&gt; identifiers;
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CodeGenerator.cpp (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CodeGenerator.cpp        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/VM/CodeGenerator.cpp        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -1153,6 +1153,7 @@
</span><span class="cx">         callFrame.append(newTemporary());
</span><span class="cx"> 
</span><span class="cx">     emitExpressionInfo(divot, startOffset, endOffset);
</span><ins>+    m_codeBlock-&gt;structureIDInstructions.append(instructions().size());
</ins><span class="cx">     emitOpcode(opcodeID);
</span><span class="cx">     instructions().append(dst-&gt;index());
</span><span class="cx">     instructions().append(func-&gt;index());
</span><span class="lines">@@ -1204,6 +1205,7 @@
</span><span class="cx">         callFrame.append(newTemporary());
</span><span class="cx"> 
</span><span class="cx">     emitExpressionInfo(divot, startOffset, endOffset);
</span><ins>+    m_codeBlock-&gt;structureIDInstructions.append(instructions().size());
</ins><span class="cx">     emitOpcode(op_construct);
</span><span class="cx">     instructions().append(dst-&gt;index());
</span><span class="cx">     instructions().append(func-&gt;index());
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMMachinecpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/Machine.cpp (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/Machine.cpp        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/VM/Machine.cpp        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -4544,6 +4544,12 @@
</span><span class="cx">     return ARG_func1-&gt;makeFunction(ARG_callFrame, ARG_callFrame-&gt;scopeChain());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Machine::cti_op_call_profiler(CTI_ARGS)
+{
+    ASSERT(*ARG_profilerReference);
+    (*ARG_profilerReference)-&gt;willExecute(ARG_callFrame, static_cast&lt;JSFunction*&gt;(ARG_src1));
+}
+
</ins><span class="cx"> VoidPtrPair Machine::cti_op_call_JSFunction(CTI_ARGS)
</span><span class="cx"> {
</span><span class="cx"> #ifndef NDEBUG
</span><span class="lines">@@ -4551,9 +4557,6 @@
</span><span class="cx">     ASSERT(ARG_src1-&gt;getCallData(callData) == CallTypeJS);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(*ARG_profilerReference != 0))
-        (*ARG_profilerReference)-&gt;willExecute(ARG_callFrame, static_cast&lt;JSFunction*&gt;(ARG_src1));
-
</del><span class="cx">     ScopeChainNode* callDataScopeChain = static_cast&lt;JSFunction*&gt;(ARG_src1)-&gt;m_scopeChain.node();
</span><span class="cx">     CodeBlock* newCodeBlock = &amp;static_cast&lt;JSFunction*&gt;(ARG_src1)-&gt;m_body-&gt;byteCode(callDataScopeChain);
</span><span class="cx">     CallFrame* callFrame = ARG_callFrame;
</span><span class="lines">@@ -4593,6 +4596,24 @@
</span><span class="cx">     return pair;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void* Machine::cti_vm_lazyLinkCall(CTI_ARGS)
+{
+    Machine* machine = ARG_globalData-&gt;machine;
+    CallFrame* callFrame = CallFrame::create(ARG_callFrame);
+    CallFrame* callerCallFrame = callFrame-&gt;callerFrame();
+    CodeBlock* callerCodeBlock = callerCallFrame-&gt;codeBlock();
+
+    JSFunction* callee = static_cast&lt;JSFunction*&gt;(ARG_src1);
+    CodeBlock* codeBlock = &amp;callee-&gt;m_body-&gt;byteCode(callee-&gt;m_scopeChain.node());
+    if (!codeBlock-&gt;ctiCode)
+        CTI::compile(machine, callFrame, codeBlock);
+
+    int argCount = ARG_int3;
+    CTI::linkCall(callerCodeBlock, callee, codeBlock, codeBlock-&gt;ctiCode, CTI_RETURN_ADDRESS, argCount);
+
+    return codeBlock-&gt;ctiCode;
+}
+
</ins><span class="cx"> void* Machine::cti_vm_compile(CTI_ARGS)
</span><span class="cx"> {
</span><span class="cx">     CodeBlock* codeBlock = ARG_callFrame-&gt;codeBlock();
</span><span class="lines">@@ -4715,24 +4736,36 @@
</span><span class="cx">     VM_THROW_EXCEPTION();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSValue* Machine::cti_op_construct_JSConstructFast(CTI_ARGS)
+{
+#ifndef NDEBUG
+    ConstructData constructData;
+    ASSERT(static_cast&lt;JSFunction*&gt;(ARG_src1)-&gt;getConstructData(constructData) == ConstructTypeJS);
+#endif
+
+    StructureID* structure;
+    if (ARG_src2-&gt;isObject())
+        structure = static_cast&lt;JSObject*&gt;(ARG_src2)-&gt;inheritorID();
+    else
+        structure = static_cast&lt;JSFunction*&gt;(ARG_src1)-&gt;m_scopeChain.node()-&gt;globalObject()-&gt;emptyObjectStructure();
+    return new (ARG_globalData) JSObject(structure);
+}
+
</ins><span class="cx"> VoidPtrPair Machine::cti_op_construct_JSConstruct(CTI_ARGS)
</span><span class="cx"> {
</span><span class="cx">     CallFrame* callFrame = ARG_callFrame;
</span><span class="cx"> 
</span><span class="cx">     JSFunction* constructor = static_cast&lt;JSFunction*&gt;(ARG_src1);
</span><del>-    JSValue* constrProtoVal = ARG_src2;
-    int firstArg = ARG_int3;
-    int registerOffset = ARG_int4;
-    int argCount = ARG_int5;
</del><ins>+    int registerOffset = ARG_int2;
+    int argCount = ARG_int3;
+    JSValue* constrProtoVal = ARG_src5;
+    int firstArg = ARG_int6;
</ins><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     ConstructData constructData;
</span><del>-    ASSERT(ARG_src1-&gt;getConstructData(constructData) == ConstructTypeJS);
</del><ins>+    ASSERT(constructor-&gt;getConstructData(constructData) == ConstructTypeJS);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (*ARG_profilerReference)
-        (*ARG_profilerReference)-&gt;willExecute(callFrame, constructor);
-
</del><span class="cx">     ScopeChainNode* callDataScopeChain = constructor-&gt;m_scopeChain.node();
</span><span class="cx">     FunctionBodyNode* functionBodyNode = constructor-&gt;m_body.get();
</span><span class="cx">     CodeBlock* newCodeBlock = &amp;functionBodyNode-&gt;byteCode(callDataScopeChain);
</span><span class="lines">@@ -4783,8 +4816,8 @@
</span><span class="cx">     CallFrame* callFrame = ARG_callFrame;
</span><span class="cx"> 
</span><span class="cx">     JSValue* constrVal = ARG_src1;
</span><del>-    int firstArg = ARG_int3;
-    int argCount = ARG_int5;
</del><ins>+    int argCount = ARG_int3;
+    int firstArg = ARG_int6;
</ins><span class="cx"> 
</span><span class="cx">     ConstructData constructData;
</span><span class="cx">     ConstructType constructType = constrVal-&gt;getConstructData(constructData);
</span><span class="lines">@@ -4810,7 +4843,7 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(constructType == ConstructTypeNone);
</span><span class="cx"> 
</span><del>-    ARG_globalData-&gt;exception = createNotAConstructorError(callFrame, constrVal, ARG_instr6, callFrame-&gt;codeBlock());
</del><ins>+    ARG_globalData-&gt;exception = createNotAConstructorError(callFrame, constrVal, ARG_instr4, callFrame-&gt;codeBlock());
</ins><span class="cx">     VM_THROW_EXCEPTION();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMMachineh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/Machine.h (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/Machine.h        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/VM/Machine.h        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -188,11 +188,11 @@
</span><span class="cx">         static void SFX_CALL cti_op_create_arguments(CTI_ARGS);
</span><span class="cx">         static void SFX_CALL cti_op_tear_off_activation(CTI_ARGS);
</span><span class="cx">         static void SFX_CALL cti_op_tear_off_arguments(CTI_ARGS);
</span><del>-        static void SFX_CALL cti_op_ret_profiler(CTI_ARGS);
</del><span class="cx">         static void SFX_CALL cti_op_ret_scopeChain(CTI_ARGS);
</span><span class="cx">         static JSValue* SFX_CALL cti_op_new_array(CTI_ARGS);
</span><span class="cx">         static JSValue* SFX_CALL cti_op_resolve(CTI_ARGS);
</span><span class="cx">         static JSValue* SFX_CALL cti_op_resolve_global(CTI_ARGS);
</span><ins>+        static JSValue* SFX_CALL cti_op_construct_JSConstructFast(CTI_ARGS);
</ins><span class="cx">         static VoidPtrPair SFX_CALL cti_op_construct_JSConstruct(CTI_ARGS);
</span><span class="cx">         static JSValue* SFX_CALL cti_op_construct_NotJSConstruct(CTI_ARGS);
</span><span class="cx">         static JSValue* SFX_CALL cti_op_get_by_val(CTI_ARGS);
</span><span class="lines">@@ -255,8 +255,12 @@
</span><span class="cx">         static JSValue* SFX_CALL cti_op_new_error(CTI_ARGS);
</span><span class="cx">         static void SFX_CALL cti_op_debug(CTI_ARGS);
</span><span class="cx"> 
</span><ins>+        static void SFX_CALL cti_op_call_profiler(CTI_ARGS);
+        static void SFX_CALL cti_op_ret_profiler(CTI_ARGS);
+
</ins><span class="cx">         static void* SFX_CALL cti_vm_throw(CTI_ARGS);
</span><span class="cx">         static void* SFX_CALL cti_vm_compile(CTI_ARGS);
</span><ins>+        static void* SFX_CALL cti_vm_lazyLinkCall(CTI_ARGS);
</ins><span class="cx">         static JSValue* SFX_CALL cti_op_push_activation(CTI_ARGS);
</span><span class="cx">         
</span><span class="cx"> #endif // ENABLE(CTI)
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSFunction.cpp (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSFunction.cpp        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/kjs/JSFunction.cpp        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CodeBlock.h&quot;
</ins><span class="cx"> #include &quot;CommonIdentifiers.h&quot;
</span><span class="cx"> #include &quot;ExecState.h&quot;
</span><span class="cx"> #include &quot;FunctionPrototype.h&quot;
</span><span class="lines">@@ -51,6 +52,17 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSFunction::~JSFunction()
+{
+#if ENABLE(CTI) 
+    // JIT code for other functions may have had calls linked directly to the code for this function; these links
+    // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
+    // this memory is freed and may be reused (potentially for another, different JSFunction).
+    if (m_body.get() &amp;&amp; m_body-&gt;isGenerated())
+        m_body-&gt;generatedByteCode().unlinkCallers();
+#endif
+}
+
</ins><span class="cx"> void JSFunction::mark()
</span><span class="cx"> {
</span><span class="cx">     Base::mark();
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSFunctionh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSFunction.h (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSFunction.h        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/kjs/JSFunction.h        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx">         JSFunction(PassRefPtr&lt;JSC::StructureID&gt; st) : InternalFunction(st), m_scopeChain(NoScopeChain()) {}
</span><span class="cx">     public:
</span><span class="cx">         JSFunction(ExecState*, const Identifier&amp;, FunctionBodyNode*, ScopeChainNode*);
</span><ins>+        ~JSFunction();
</ins><span class="cx"> 
</span><span class="cx">         virtual bool getOwnPropertySlot(ExecState*, const Identifier&amp;, PropertySlot&amp;);
</span><span class="cx">         virtual void put(ExecState*, const Identifier&amp; propertyName, JSValue*, PutPropertySlot&amp;);
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsnodesh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/nodes.h (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/nodes.h        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/kjs/nodes.h        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -2278,6 +2278,11 @@
</span><span class="cx">             return *m_code;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        bool isGenerated() JSC_FAST_CALL
+        {
+            return m_code;
+        }
+
</ins><span class="cx">         void mark();
</span><span class="cx"> 
</span><span class="cx">         void finishParsing(const SourceCode&amp;, ParameterNode*);
</span></span></pre></div>
<a id="trunkJavaScriptCoremasmX86Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/masm/X86Assembler.h (37669 => 37670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/masm/X86Assembler.h        2008-10-18 01:04:12 UTC (rev 37669)
+++ trunk/JavaScriptCore/masm/X86Assembler.h        2008-10-18 02:51:52 UTC (rev 37670)
</span><span class="lines">@@ -1057,6 +1057,11 @@
</span><span class="cx">         return dst.m_offset - src.m_offset;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
+    {
+        return dst.m_offset - src.m_offset;
+    }
+    
</ins><span class="cx">     static void repatchImmediate(intptr_t where, int32_t value)
</span><span class="cx">     {
</span><span class="cx">         reinterpret_cast&lt;int32_t*&gt;(where)[-1] = value;
</span></span></pre>
</div>
</div>

</body>
</html>