<!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>[36821] 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/36821">36821</a></dd>
<dt>Author</dt> <dd>ggaren@apple.com</dd>
<dt>Date</dt> <dd>2008-09-23 17:27:18 -0700 (Tue, 23 Sep 2008)</dd>
</dl>
<h3>Log Message</h3>
<pre>2008-09-23 Geoffrey Garen <ggaren@apple.com>
Reviewed by Darin Adler.
Changed the layout of the call frame from
{ header, parameters, locals | constants, temporaries }
to
{ parameters, header | locals, constants, temporaries }
This simplifies function entry+exit, and enables a number of future
optimizations.
13.5% speedup on empty call benchmark for bytecode; 23.6% speedup on
empty call benchmark for CTI.
SunSpider says no change. SunSpider --v8 says 1% faster.
* VM/CTI.cpp:
Added a bit of abstraction for calculating whether a register is a
constant, since this patch changes that calculation:
(JSC::CTI::isConstant):
(JSC::CTI::getConstant):
(JSC::CTI::emitGetArg):
(JSC::CTI::emitGetPutArg):
(JSC::CTI::getConstantImmediateNumericArg):
Updated for changes to callframe header location:
(JSC::CTI::emitPutToCallFrameHeader):
(JSC::CTI::emitGetFromCallFrameHeader):
(JSC::CTI::printOpcodeOperandTypes):
Renamed to spite Oliver:
(JSC::CTI::emitInitRegister):
Added an abstraction for emitting a call through a register, so that
calls through registers generate exception info, too:
(JSC::CTI::emitCall):
Updated to match the new callframe header layout, and to support calls
through registers, which have no destination address:
(JSC::CTI::compileOpCall):
(JSC::CTI::privateCompileMainPass):
(JSC::CTI::privateCompileSlowCases):
(JSC::CTI::privateCompile):
* VM/CTI.h:
More of the above:
(JSC::CallRecord::CallRecord):
* VM/CodeBlock.cpp:
Updated for new register layout:
(JSC::registerName):
(JSC::CodeBlock::dump):
* VM/CodeBlock.h:
Updated CodeBlock to track slightly different information about the
register frame, and tweaked the style of an ASSERT_NOT_REACHED.
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::getStubInfo):
* VM/CodeGenerator.cpp:
Added some abstraction around constant register allocation, since this
patch changes it, changed codegen to account for the new callframe
layout, and added abstraction around register fetching code
that used to assume that all local registers lived at negative indices,
since vars now live at positive indices:
(JSC::CodeGenerator::generate):
(JSC::CodeGenerator::addVar):
(JSC::CodeGenerator::addGlobalVar):
(JSC::CodeGenerator::allocateConstants):
(JSC::CodeGenerator::CodeGenerator):
(JSC::CodeGenerator::addParameter):
(JSC::CodeGenerator::registerFor):
(JSC::CodeGenerator::constRegisterFor):
(JSC::CodeGenerator::newRegister):
(JSC::CodeGenerator::newTemporary):
(JSC::CodeGenerator::highestUsedRegister):
(JSC::CodeGenerator::addConstant):
ASSERT that our caller referenced the registers it passed to us.
Otherwise, we might overwrite them with parameters:
(JSC::CodeGenerator::emitCall):
(JSC::CodeGenerator::emitConstruct):
* VM/CodeGenerator.h:
Added some abstraction for getting a RegisterID for a given index,
since the rules are a little weird:
(JSC::CodeGenerator::registerFor):
* VM/Machine.cpp:
Utility function to transform a machine return PC to a virtual machine
return VPC, for the sake of stack unwinding, since both PCs are stored
in the same location now:
(JSC::vPCForPC):
Tweaked to account for new call frame:
(JSC::Machine::initializeCallFrame):
Tweaked to account for registerOffset supplied by caller:
(JSC::slideRegisterWindowForCall):
Tweaked to account for new register layout:
(JSC::scopeChainForCall):
(JSC::Machine::callEval):
(JSC::Machine::dumpRegisters):
(JSC::Machine::unwindCallFrame):
(JSC::Machine::execute):
Changed op_call and op_construct to implement the new calling convention:
(JSC::Machine::privateExecute):
Tweaked to account for the new register layout:
(JSC::Machine::retrieveArguments):
(JSC::Machine::retrieveCaller):
(JSC::Machine::retrieveLastCaller):
(JSC::Machine::callFrame):
(JSC::Machine::getArgumentsData):
Changed CTI call helpers to implement the new calling convention:
(JSC::Machine::cti_op_call_JSFunction):
(JSC::Machine::cti_op_call_NotJSFunction):
(JSC::Machine::cti_op_ret_activation):
(JSC::Machine::cti_op_ret_profiler):
(JSC::Machine::cti_op_construct_JSConstruct):
(JSC::Machine::cti_op_construct_NotJSConstruct):
(JSC::Machine::cti_op_call_eval):
* VM/Machine.h:
* VM/Opcode.h:
Renamed op_initialise_locals to op_init, because this opcode
doesn't initialize all locals, and it doesn't initialize only locals.
Also, to spite Oliver.
* VM/RegisterFile.h:
New call frame enumeration values:
(JSC::RegisterFile::):
Simplified the calculation of whether a RegisterID is a temporary,
since we can no longer assume that all positive non-constant registers
are temporaries:
* VM/RegisterID.h:
(JSC::RegisterID::RegisterID):
(JSC::RegisterID::setTemporary):
(JSC::RegisterID::isTemporary):
Renamed firstArgumentIndex to firstParameterIndex because the assumption
that this variable pertained to the actual arguments supplied by the
caller caused me to write some buggy code:
* kjs/Arguments.cpp:
(JSC::ArgumentsData::ArgumentsData):
(JSC::Arguments::Arguments):
(JSC::Arguments::fillArgList):
(JSC::Arguments::getOwnPropertySlot):
(JSC::Arguments::put):
Updated for new call frame layout:
* kjs/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::functionName):
(JSC::DebuggerCallFrame::type):
* kjs/DebuggerCallFrame.h:
Changed the activation object to account for the fact that a call frame
header now sits between parameters and local variables. This change
requires all variable objects to do their own marking, since they
now use their register storage differently:
* kjs/JSActivation.cpp:
(JSC::JSActivation::mark):
(JSC::JSActivation::copyRegisters):
(JSC::JSActivation::createArgumentsObject):
* kjs/JSActivation.h:
Updated global object to use the new interfaces required by the change
to JSActivation above:
* kjs/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
(JSC::JSGlobalObject::mark):
(JSC::JSGlobalObject::copyGlobalsFrom):
(JSC::JSGlobalObject::copyGlobalsTo):
* kjs/JSGlobalObject.h:
(JSC::JSGlobalObject::addStaticGlobals):
Updated static scope object to use the new interfaces required by the
change to JSActivation above:
* kjs/JSStaticScopeObject.cpp:
(JSC::JSStaticScopeObject::mark):
(JSC::JSStaticScopeObject::~JSStaticScopeObject):
* kjs/JSStaticScopeObject.h:
(JSC::JSStaticScopeObject::JSStaticScopeObject):
(JSC::JSStaticScopeObject::d):
Updated variable object to use the new interfaces required by the
change to JSActivation above:
* kjs/JSVariableObject.cpp:
(JSC::JSVariableObject::copyRegisterArray):
(JSC::JSVariableObject::setRegisters):
* kjs/JSVariableObject.h:
Changed the bit twiddling in symbol table not to assume that all indices
are negative, since they can be positive now:
* kjs/SymbolTable.h:
(JSC::SymbolTableEntry::SymbolTableEntry):
(JSC::SymbolTableEntry::isNull):
(JSC::SymbolTableEntry::getIndex):
(JSC::SymbolTableEntry::getAttributes):
(JSC::SymbolTableEntry::setAttributes):
(JSC::SymbolTableEntry::isReadOnly):
(JSC::SymbolTableEntry::pack):
(JSC::SymbolTableEntry::isValidIndex):
Changed call and construct nodes to ref their functions and/or bases,
so that emitCall/emitConstruct doesn't overwrite them with parameters.
Also, updated for rename to registerFor:
* kjs/nodes.cpp:
(JSC::ResolveNode::emitCode):
(JSC::NewExprNode::emitCode):
(JSC::EvalFunctionCallNode::emitCode):
(JSC::FunctionCallValueNode::emitCode):
(JSC::FunctionCallResolveNode::emitCode):
(JSC::FunctionCallBracketNode::emitCode):
(JSC::FunctionCallDotNode::emitCode):
(JSC::PostfixResolveNode::emitCode):
(JSC::DeleteResolveNode::emitCode):
(JSC::TypeOfResolveNode::emitCode):
(JSC::PrefixResolveNode::emitCode):
(JSC::ReadModifyResolveNode::emitCode):
(JSC::AssignResolveNode::emitCode):
(JSC::ConstDeclNode::emitCodeSingle):
(JSC::ForInNode::emitCode):
Added abstraction for getting exception info out of a call through a
register:
* masm/X86Assembler.h:
(JSC::X86Assembler::emitCall):
Removed duplicate #if:
* wtf/Platform.h:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreChangeLog">trunk/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCoreexp">trunk/JavaScriptCore/JavaScriptCore.exp</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="#trunkJavaScriptCoreVMCodeGeneratorh">trunk/JavaScriptCore/VM/CodeGenerator.h</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="#trunkJavaScriptCoreVMOpcodeh">trunk/JavaScriptCore/VM/Opcode.h</a></li>
<li><a href="#trunkJavaScriptCoreVMRegisterFileh">trunk/JavaScriptCore/VM/RegisterFile.h</a></li>
<li><a href="#trunkJavaScriptCoreVMRegisterIDh">trunk/JavaScriptCore/VM/RegisterID.h</a></li>
<li><a href="#trunkJavaScriptCorekjsArgumentscpp">trunk/JavaScriptCore/kjs/Arguments.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsDebuggerCallFramecpp">trunk/JavaScriptCore/kjs/DebuggerCallFrame.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsDebuggerCallFrameh">trunk/JavaScriptCore/kjs/DebuggerCallFrame.h</a></li>
<li><a href="#trunkJavaScriptCorekjsJSActivationcpp">trunk/JavaScriptCore/kjs/JSActivation.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsJSActivationh">trunk/JavaScriptCore/kjs/JSActivation.h</a></li>
<li><a href="#trunkJavaScriptCorekjsJSGlobalObjectcpp">trunk/JavaScriptCore/kjs/JSGlobalObject.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsJSGlobalObjecth">trunk/JavaScriptCore/kjs/JSGlobalObject.h</a></li>
<li><a href="#trunkJavaScriptCorekjsJSStaticScopeObjectcpp">trunk/JavaScriptCore/kjs/JSStaticScopeObject.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsJSStaticScopeObjecth">trunk/JavaScriptCore/kjs/JSStaticScopeObject.h</a></li>
<li><a href="#trunkJavaScriptCorekjsJSVariableObjectcpp">trunk/JavaScriptCore/kjs/JSVariableObject.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsJSVariableObjecth">trunk/JavaScriptCore/kjs/JSVariableObject.h</a></li>
<li><a href="#trunkJavaScriptCorekjsSymbolTableh">trunk/JavaScriptCore/kjs/SymbolTable.h</a></li>
<li><a href="#trunkJavaScriptCorekjsnodescpp">trunk/JavaScriptCore/kjs/nodes.cpp</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 (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/ChangeLog 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/ChangeLog 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -1,3 +1,253 @@
</span><ins>+2008-09-23 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Changed the layout of the call frame from
+
+ { header, parameters, locals | constants, temporaries }
+
+ to
+
+ { parameters, header | locals, constants, temporaries }
+
+ This simplifies function entry+exit, and enables a number of future
+ optimizations.
+
+ 13.5% speedup on empty call benchmark for bytecode; 23.6% speedup on
+ empty call benchmark for CTI.
+
+ SunSpider says no change. SunSpider --v8 says 1% faster.
+
+ * VM/CTI.cpp:
+
+ Added a bit of abstraction for calculating whether a register is a
+ constant, since this patch changes that calculation:
+ (JSC::CTI::isConstant):
+ (JSC::CTI::getConstant):
+ (JSC::CTI::emitGetArg):
+ (JSC::CTI::emitGetPutArg):
+ (JSC::CTI::getConstantImmediateNumericArg):
+
+ Updated for changes to callframe header location:
+ (JSC::CTI::emitPutToCallFrameHeader):
+ (JSC::CTI::emitGetFromCallFrameHeader):
+ (JSC::CTI::printOpcodeOperandTypes):
+
+ Renamed to spite Oliver:
+ (JSC::CTI::emitInitRegister):
+
+ Added an abstraction for emitting a call through a register, so that
+ calls through registers generate exception info, too:
+ (JSC::CTI::emitCall):
+
+ Updated to match the new callframe header layout, and to support calls
+ through registers, which have no destination address:
+ (JSC::CTI::compileOpCall):
+ (JSC::CTI::privateCompileMainPass):
+ (JSC::CTI::privateCompileSlowCases):
+ (JSC::CTI::privateCompile):
+
+ * VM/CTI.h:
+
+ More of the above:
+ (JSC::CallRecord::CallRecord):
+
+ * VM/CodeBlock.cpp:
+
+ Updated for new register layout:
+ (JSC::registerName):
+ (JSC::CodeBlock::dump):
+
+ * VM/CodeBlock.h:
+
+ Updated CodeBlock to track slightly different information about the
+ register frame, and tweaked the style of an ASSERT_NOT_REACHED.
+ (JSC::CodeBlock::CodeBlock):
+ (JSC::CodeBlock::getStubInfo):
+
+ * VM/CodeGenerator.cpp:
+
+ Added some abstraction around constant register allocation, since this
+ patch changes it, changed codegen to account for the new callframe
+ layout, and added abstraction around register fetching code
+ that used to assume that all local registers lived at negative indices,
+ since vars now live at positive indices:
+ (JSC::CodeGenerator::generate):
+ (JSC::CodeGenerator::addVar):
+ (JSC::CodeGenerator::addGlobalVar):
+ (JSC::CodeGenerator::allocateConstants):
+ (JSC::CodeGenerator::CodeGenerator):
+ (JSC::CodeGenerator::addParameter):
+ (JSC::CodeGenerator::registerFor):
+ (JSC::CodeGenerator::constRegisterFor):
+ (JSC::CodeGenerator::newRegister):
+ (JSC::CodeGenerator::newTemporary):
+ (JSC::CodeGenerator::highestUsedRegister):
+ (JSC::CodeGenerator::addConstant):
+
+ ASSERT that our caller referenced the registers it passed to us.
+ Otherwise, we might overwrite them with parameters:
+ (JSC::CodeGenerator::emitCall):
+ (JSC::CodeGenerator::emitConstruct):
+
+ * VM/CodeGenerator.h:
+
+ Added some abstraction for getting a RegisterID for a given index,
+ since the rules are a little weird:
+ (JSC::CodeGenerator::registerFor):
+
+ * VM/Machine.cpp:
+
+ Utility function to transform a machine return PC to a virtual machine
+ return VPC, for the sake of stack unwinding, since both PCs are stored
+ in the same location now:
+ (JSC::vPCForPC):
+
+ Tweaked to account for new call frame:
+ (JSC::Machine::initializeCallFrame):
+
+ Tweaked to account for registerOffset supplied by caller:
+ (JSC::slideRegisterWindowForCall):
+
+ Tweaked to account for new register layout:
+ (JSC::scopeChainForCall):
+ (JSC::Machine::callEval):
+ (JSC::Machine::dumpRegisters):
+ (JSC::Machine::unwindCallFrame):
+ (JSC::Machine::execute):
+
+ Changed op_call and op_construct to implement the new calling convention:
+ (JSC::Machine::privateExecute):
+
+ Tweaked to account for the new register layout:
+ (JSC::Machine::retrieveArguments):
+ (JSC::Machine::retrieveCaller):
+ (JSC::Machine::retrieveLastCaller):
+ (JSC::Machine::callFrame):
+ (JSC::Machine::getArgumentsData):
+
+ Changed CTI call helpers to implement the new calling convention:
+ (JSC::Machine::cti_op_call_JSFunction):
+ (JSC::Machine::cti_op_call_NotJSFunction):
+ (JSC::Machine::cti_op_ret_activation):
+ (JSC::Machine::cti_op_ret_profiler):
+ (JSC::Machine::cti_op_construct_JSConstruct):
+ (JSC::Machine::cti_op_construct_NotJSConstruct):
+ (JSC::Machine::cti_op_call_eval):
+
+ * VM/Machine.h:
+
+ * VM/Opcode.h:
+
+ Renamed op_initialise_locals to op_init, because this opcode
+ doesn't initialize all locals, and it doesn't initialize only locals.
+ Also, to spite Oliver.
+
+ * VM/RegisterFile.h:
+
+ New call frame enumeration values:
+ (JSC::RegisterFile::):
+
+ Simplified the calculation of whether a RegisterID is a temporary,
+ since we can no longer assume that all positive non-constant registers
+ are temporaries:
+ * VM/RegisterID.h:
+ (JSC::RegisterID::RegisterID):
+ (JSC::RegisterID::setTemporary):
+ (JSC::RegisterID::isTemporary):
+
+ Renamed firstArgumentIndex to firstParameterIndex because the assumption
+ that this variable pertained to the actual arguments supplied by the
+ caller caused me to write some buggy code:
+ * kjs/Arguments.cpp:
+ (JSC::ArgumentsData::ArgumentsData):
+ (JSC::Arguments::Arguments):
+ (JSC::Arguments::fillArgList):
+ (JSC::Arguments::getOwnPropertySlot):
+ (JSC::Arguments::put):
+
+ Updated for new call frame layout:
+ * kjs/DebuggerCallFrame.cpp:
+ (JSC::DebuggerCallFrame::functionName):
+ (JSC::DebuggerCallFrame::type):
+ * kjs/DebuggerCallFrame.h:
+
+ Changed the activation object to account for the fact that a call frame
+ header now sits between parameters and local variables. This change
+ requires all variable objects to do their own marking, since they
+ now use their register storage differently:
+ * kjs/JSActivation.cpp:
+ (JSC::JSActivation::mark):
+ (JSC::JSActivation::copyRegisters):
+ (JSC::JSActivation::createArgumentsObject):
+ * kjs/JSActivation.h:
+
+ Updated global object to use the new interfaces required by the change
+ to JSActivation above:
+ * kjs/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::reset):
+ (JSC::JSGlobalObject::mark):
+ (JSC::JSGlobalObject::copyGlobalsFrom):
+ (JSC::JSGlobalObject::copyGlobalsTo):
+ * kjs/JSGlobalObject.h:
+ (JSC::JSGlobalObject::addStaticGlobals):
+
+ Updated static scope object to use the new interfaces required by the
+ change to JSActivation above:
+ * kjs/JSStaticScopeObject.cpp:
+ (JSC::JSStaticScopeObject::mark):
+ (JSC::JSStaticScopeObject::~JSStaticScopeObject):
+ * kjs/JSStaticScopeObject.h:
+ (JSC::JSStaticScopeObject::JSStaticScopeObject):
+ (JSC::JSStaticScopeObject::d):
+
+ Updated variable object to use the new interfaces required by the
+ change to JSActivation above:
+ * kjs/JSVariableObject.cpp:
+ (JSC::JSVariableObject::copyRegisterArray):
+ (JSC::JSVariableObject::setRegisters):
+ * kjs/JSVariableObject.h:
+
+ Changed the bit twiddling in symbol table not to assume that all indices
+ are negative, since they can be positive now:
+ * kjs/SymbolTable.h:
+ (JSC::SymbolTableEntry::SymbolTableEntry):
+ (JSC::SymbolTableEntry::isNull):
+ (JSC::SymbolTableEntry::getIndex):
+ (JSC::SymbolTableEntry::getAttributes):
+ (JSC::SymbolTableEntry::setAttributes):
+ (JSC::SymbolTableEntry::isReadOnly):
+ (JSC::SymbolTableEntry::pack):
+ (JSC::SymbolTableEntry::isValidIndex):
+
+ Changed call and construct nodes to ref their functions and/or bases,
+ so that emitCall/emitConstruct doesn't overwrite them with parameters.
+ Also, updated for rename to registerFor:
+ * kjs/nodes.cpp:
+ (JSC::ResolveNode::emitCode):
+ (JSC::NewExprNode::emitCode):
+ (JSC::EvalFunctionCallNode::emitCode):
+ (JSC::FunctionCallValueNode::emitCode):
+ (JSC::FunctionCallResolveNode::emitCode):
+ (JSC::FunctionCallBracketNode::emitCode):
+ (JSC::FunctionCallDotNode::emitCode):
+ (JSC::PostfixResolveNode::emitCode):
+ (JSC::DeleteResolveNode::emitCode):
+ (JSC::TypeOfResolveNode::emitCode):
+ (JSC::PrefixResolveNode::emitCode):
+ (JSC::ReadModifyResolveNode::emitCode):
+ (JSC::AssignResolveNode::emitCode):
+ (JSC::ConstDeclNode::emitCodeSingle):
+ (JSC::ForInNode::emitCode):
+
+ Added abstraction for getting exception info out of a call through a
+ register:
+ * masm/X86Assembler.h:
+ (JSC::X86Assembler::emitCall):
+
+ Removed duplicate #if:
+ * wtf/Platform.h:
+
</ins><span class="cx"> 2008-09-23 Kevin McCullough <kmccullough@apple.com>
</span><span class="cx">
</span><span class="cx"> Reviewed by Darin.
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCoreexp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/JavaScriptCore.exp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/JavaScriptCore.exp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/JavaScriptCore.exp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -153,9 +153,9 @@
</span><span class="cx"> __ZN3JSC15JSWrapperObject4markEv
</span><span class="cx"> __ZN3JSC16InternalFunction4infoE
</span><span class="cx"> __ZN3JSC16InternalFunctionC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_11StructureIDEEERKNS_10IdentifierE
</span><ins>+__ZN3JSC16JSVariableObject12setRegistersEPNS_8RegisterES2_m
</ins><span class="cx"> __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
</span><span class="cx"> __ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
</span><del>-__ZN3JSC16JSVariableObject16setRegisterArrayEPNS_8RegisterEm
</del><span class="cx"> __ZN3JSC16ParserRefCounted3refEv
</span><span class="cx"> __ZN3JSC16ParserRefCounted5derefEv
</span><span class="cx"> __ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCTIcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CTI.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CTI.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/CTI.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -106,12 +106,22 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx">
</span><ins>+ALWAYS_INLINE bool CTI::isConstant(int src)
+{
+ return src >= m_codeBlock->numVars && src < m_codeBlock->numVars + m_codeBlock->numConstants;
+}
+
+ALWAYS_INLINE JSValue* CTI::getConstant(ExecState* exec, int src)
+{
+ return m_codeBlock->constantRegisters[src - m_codeBlock->numVars].jsValue(exec);
+}
+
</ins><span class="cx"> // get arg puts an arg from the SF register array into a h/w register
</span><span class="cx"> ALWAYS_INLINE void CTI::emitGetArg(unsigned src, X86Assembler::RegisterID dst)
</span><span class="cx"> {
</span><span class="cx"> // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
</span><del>- if (src < m_codeBlock->constantRegisters.size()) {
- JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
</del><ins>+ if (isConstant(src)) {
+ JSValue* js = getConstant(m_exec, src);
</ins><span class="cx"> m_jit.movl_i32r(reinterpret_cast<unsigned>(js), dst);
</span><span class="cx"> } else
</span><span class="cx"> m_jit.movl_mr(src * sizeof(Register), X86::edi, dst);
</span><span class="lines">@@ -120,8 +130,8 @@
</span><span class="cx"> // get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
</span><span class="cx"> ALWAYS_INLINE void CTI::emitGetPutArg(unsigned src, unsigned offset, X86Assembler::RegisterID scratch)
</span><span class="cx"> {
</span><del>- if (src < m_codeBlock->constantRegisters.size()) {
- JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
</del><ins>+ if (isConstant(src)) {
+ JSValue* js = getConstant(m_exec, src);
</ins><span class="cx"> m_jit.movl_i32m(reinterpret_cast<unsigned>(js), offset + sizeof(void*), X86::esp);
</span><span class="cx"> } else {
</span><span class="cx"> m_jit.movl_mr(src * sizeof(Register), X86::edi, scratch);
</span><span class="lines">@@ -142,8 +152,8 @@
</span><span class="cx">
</span><span class="cx"> ALWAYS_INLINE JSValue* CTI::getConstantImmediateNumericArg(unsigned src)
</span><span class="cx"> {
</span><del>- if (src < m_codeBlock->constantRegisters.size()) {
- JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
</del><ins>+ if (isConstant(src)) {
+ JSValue* js = getConstant(m_exec, src);
</ins><span class="cx"> return JSImmediate::isNumber(js) ? js : 0;
</span><span class="cx"> }
</span><span class="cx"> return 0;
</span><span class="lines">@@ -166,12 +176,12 @@
</span><span class="cx">
</span><span class="cx"> ALWAYS_INLINE void CTI::emitPutToCallFrameHeader(X86Assembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
</span><span class="cx"> {
</span><del>- m_jit.movl_rm(from, -((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), X86::edi);
</del><ins>+ m_jit.movl_rm(from, entry * sizeof(Register), X86::edi);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ALWAYS_INLINE void CTI::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, X86Assembler::RegisterID to)
</span><span class="cx"> {
</span><del>- m_jit.movl_mr(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), X86::edi, to);
</del><ins>+ m_jit.movl_mr(entry * sizeof(Register), X86::edi, to);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ALWAYS_INLINE void CTI::emitPutResult(unsigned dst, X86Assembler::RegisterID from)
</span><span class="lines">@@ -180,7 +190,7 @@
</span><span class="cx"> // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
</span><span class="cx"> }
</span><span class="cx">
</span><del>-ALWAYS_INLINE void CTI::emitInitialiseRegister(unsigned dst)
</del><ins>+ALWAYS_INLINE void CTI::emitInitRegister(unsigned dst)
</ins><span class="cx"> {
</span><span class="cx"> m_jit.movl_i32m(reinterpret_cast<unsigned>(jsUndefined()), dst * sizeof(Register), X86::edi);
</span><span class="cx"> // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
</span><span class="lines">@@ -220,8 +230,8 @@
</span><span class="cx"> void CTI::printOpcodeOperandTypes(unsigned src1, unsigned src2)
</span><span class="cx"> {
</span><span class="cx"> char which1 = '*';
</span><del>- if (src1 < m_codeBlock->constantRegisters.size()) {
- JSValue* js = m_codeBlock->constantRegisters[src1].jsValue(m_exec);
</del><ins>+ if (isConstant(src1)) {
+ JSValue* js = getConstant(m_exec, src1);
</ins><span class="cx"> which1 =
</span><span class="cx"> JSImmediate::isImmediate(js) ?
</span><span class="cx"> (JSImmediate::isNumber(js) ? 'i' :
</span><span class="lines">@@ -234,8 +244,8 @@
</span><span class="cx"> 'k');
</span><span class="cx"> }
</span><span class="cx"> char which2 = '*';
</span><del>- if (src2 < m_codeBlock->constantRegisters.size()) {
- JSValue* js = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
</del><ins>+ if (isConstant(src2)) {
+ JSValue* js = getConstant(m_exec, src2);
</ins><span class="cx"> which2 =
</span><span class="cx"> JSImmediate::isImmediate(js) ?
</span><span class="cx"> (JSImmediate::isNumber(js) ? 'i' :
</span><span class="lines">@@ -253,6 +263,15 @@
</span><span class="cx">
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, X86::RegisterID r)
+{
+ X86Assembler::JmpSrc call = m_jit.emitCall(r);
+ m_calls.append(CallRecord(call, opcodeIndex));
+ emitDebugExceptionCheck();
+
+ return call;
+}
+
</ins><span class="cx"> ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, CTIHelper_j helper)
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(SAMPLING_TOOL)
</span><span class="lines">@@ -431,22 +450,30 @@
</span><span class="cx"> int dst = instruction[i + 1].u.operand;
</span><span class="cx"> int firstArg = instruction[i + 4].u.operand;
</span><span class="cx"> int argCount = instruction[i + 5].u.operand;
</span><ins>+ int registerOffset = instruction[i + 6].u.operand;
</ins><span class="cx">
</span><ins>+ if (type == OpCallEval)
+ emitGetPutArg(instruction[i + 3].u.operand, 16, X86::ecx);
+
</ins><span class="cx"> if (type == OpConstruct) {
</span><del>- emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
- emitPutArgConstant(argCount, 12);
</del><ins>+ emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 20);
+ emitPutArgConstant(argCount, 16);
+ emitPutArgConstant(registerOffset, 12);
</ins><span class="cx"> emitPutArgConstant(firstArg, 8);
</span><span class="cx"> emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
</span><span class="cx"> } else {
</span><del>- emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
- emitPutArgConstant(argCount, 12);
- emitPutArgConstant(firstArg, 8);
- // FIXME: should this be loaded dynamically off m_exec?
</del><ins>+ emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 12);
+ emitPutArgConstant(argCount, 8);
+ emitPutArgConstant(registerOffset, 4);
+
</ins><span class="cx"> int thisVal = instruction[i + 3].u.operand;
</span><span class="cx"> if (thisVal == missingThisObjectMarker()) {
</span><del>- emitPutArgConstant(reinterpret_cast<unsigned>(m_exec->globalThisValue()), 4);
- } else
- emitGetPutArg(thisVal, 4, X86::ecx);
</del><ins>+ // FIXME: should this be loaded dynamically off m_exec?
+ m_jit.movl_i32m(reinterpret_cast<unsigned>(m_exec->globalThisValue()), firstArg * sizeof(Register), X86::edi);
+ } else {
+ emitGetArg(thisVal, X86::ecx);
+ emitPutResult(firstArg, X86::ecx);
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> X86Assembler::JmpSrc wasEval;
</span><span class="lines">@@ -459,28 +486,14 @@
</span><span class="cx">
</span><span class="cx"> m_jit.cmpl_i32r(reinterpret_cast<unsigned>(JSImmediate::impossibleValue()), X86::eax);
</span><span class="cx"> wasEval = m_jit.emitUnlinkedJne();
</span><del>-
- // this reloads the first arg into ecx (checked just below).
</del><ins>+
+ // this sets up the first arg to op_cti_call (func), and explicitly leaves the value in ecx (checked just below).
</ins><span class="cx"> emitGetArg(instruction[i + 2].u.operand, X86::ecx);
</span><span class="cx"> } else {
</span><del>- // this sets up the first arg, and explicitly leaves the value in ecx (checked just below).
- emitGetArg(instruction[i + 2].u.operand, X86::ecx);
- emitPutArg(X86::ecx, 0);
</del><ins>+ // this sets up the first arg to op_cti_call (func), and explicitly leaves the value in ecx (checked just below).
+ emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- // initializeCallFrame!
- m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::CallerCodeBlock) * sizeof(Register), X86::edi);
- m_jit.movl_i32m(reinterpret_cast<unsigned>(instruction + i), (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ReturnVPC) * sizeof(Register), X86::edi);
- emitGetCTIParam(CTI_ARGS_scopeChain, X86::edx);
- m_jit.movl_rm(X86::edx, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::CallerScopeChain) * sizeof(Register), X86::edi);
- m_jit.movl_rm(X86::edi, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::CallerRegisters) * sizeof(Register), X86::edi);
- m_jit.movl_i32m(dst, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ReturnValueRegister) * sizeof(Register), X86::edi);
- m_jit.movl_i32m(firstArg, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ArgumentStartRegister) * sizeof(Register), X86::edi);
- m_jit.movl_i32m(argCount, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ArgumentCount) * sizeof(Register), X86::edi);
- m_jit.movl_rm(X86::ecx, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::Callee) * sizeof(Register), X86::edi);
- m_jit.movl_i32m(0, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::OptionalCalleeActivation) * sizeof(Register), X86::edi);
- // CTIReturnEIP (set in callee)
-
</del><span class="cx"> // Fast check for JS function.
</span><span class="cx"> m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx);
</span><span class="cx"> X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne();
</span><span class="lines">@@ -490,27 +503,32 @@
</span><span class="cx">
</span><span class="cx"> // This handles host functions
</span><span class="cx"> emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction));
</span><del>- emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
-
</del><ins>+
</ins><span class="cx"> X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp();
</span><span class="cx"> m_jit.link(isJSFunction, m_jit.label());
</span><span class="cx">
</span><span class="cx"> // This handles JSFunctions
</span><span class="cx"> emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction));
</span><ins>+
+ // Initialize the parts of the call frame that have not already been initialized.
+ emitGetCTIParam(CTI_ARGS_r, X86::edi);
+ m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), RegisterFile::CallerCodeBlock * sizeof(Register), X86::edi);
+ m_jit.movl_i32m(dst, RegisterFile::ReturnValueRegister * sizeof(Register), X86::edi);
+
</ins><span class="cx"> // Check the ctiCode has been generated - if not, this is handled in a slow case.
</span><span class="cx"> m_jit.testl_rr(X86::eax, X86::eax);
</span><span class="cx"> m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i));
</span><del>- m_jit.call_r(X86::eax);
</del><ins>+ emitCall(i, X86::eax);
</ins><span class="cx">
</span><span class="cx"> // In the interpreter the following actions are performed by op_ret:
</span><del>-
- // Store the scope chain - returned by op_ret in %edx (see below) - to ExecState::m_scopeChain and CTI_ARGS_scopeChain on the stack.
</del><ins>+
+ // Restore ExecState::m_scopeChain and CTI_ARGS_scopeChain. NOTE: After
+ // op_ret, %edx holds the caller's scope chain.
</ins><span class="cx"> emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
</span><span class="cx"> emitPutCTIParam(X86::edx, CTI_ARGS_scopeChain);
</span><span class="cx"> m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_scopeChain), X86::ecx);
</span><span class="cx"> // Restore ExecState::m_callFrame.
</span><del>- m_jit.leal_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) * sizeof(Register), X86::edi, X86::edx);
- m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_callFrame), X86::ecx);
</del><ins>+ m_jit.movl_rm(X86::edi, OBJECT_OFFSET(ExecState, m_callFrame), X86::ecx);
</ins><span class="cx"> // Restore CTI_ARGS_codeBlock.
</span><span class="cx"> emitPutCTIParam(m_codeBlock, CTI_ARGS_codeBlock);
</span><span class="cx">
</span><span class="lines">@@ -593,13 +611,6 @@
</span><span class="cx">
</span><span class="cx"> void CTI::privateCompileMainPass()
</span><span class="cx"> {
</span><del>- if (m_codeBlock->codeType == FunctionCode) {
- for (int i = -m_codeBlock->numVars; i < 0; i++)
- emitInitialiseRegister(i);
- }
- for (size_t i = 0; i < m_codeBlock->constantRegisters.size(); ++i)
- emitInitialiseRegister(i);
-
</del><span class="cx"> Instruction* instruction = m_codeBlock->instructions.begin();
</span><span class="cx"> unsigned instructionCount = m_codeBlock->instructions.size();
</span><span class="cx">
</span><span class="lines">@@ -617,8 +628,8 @@
</span><span class="cx"> switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
</span><span class="cx"> case op_mov: {
</span><span class="cx"> unsigned src = instruction[i + 2].u.operand;
</span><del>- if (src < m_codeBlock->constantRegisters.size())
- m_jit.movl_i32r(reinterpret_cast<unsigned>(m_codeBlock->constantRegisters[src].jsValue(m_exec)), X86::edx);
</del><ins>+ if (isConstant(src))
+ m_jit.movl_i32r(reinterpret_cast<unsigned>(getConstant(m_exec, src)), X86::edx);
</ins><span class="cx"> else
</span><span class="cx"> emitGetArg(src, X86::edx);
</span><span class="cx"> emitPutResult(instruction[i + 1].u.operand, X86::edx);
</span><span class="lines">@@ -629,8 +640,8 @@
</span><span class="cx"> unsigned dst = instruction[i + 1].u.operand;
</span><span class="cx"> unsigned src1 = instruction[i + 2].u.operand;
</span><span class="cx"> unsigned src2 = instruction[i + 3].u.operand;
</span><del>- if (src2 < m_codeBlock->constantRegisters.size()) {
- JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
</del><ins>+ if (isConstant(src2)) {
+ JSValue* value = getConstant(m_exec, src2);
</ins><span class="cx"> if (JSImmediate::isNumber(value)) {
</span><span class="cx"> emitGetArg(src1, X86::eax);
</span><span class="cx"> emitJumpSlowCaseIfNotImmNum(X86::eax, i);
</span><span class="lines">@@ -640,7 +651,7 @@
</span><span class="cx"> i += 4;
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- } else if (!(src1 < m_codeBlock->constantRegisters.size())) {
</del><ins>+ } else if (!isConstant(src1)) {
</ins><span class="cx"> emitGetArg(src1, X86::eax);
</span><span class="cx"> emitGetArg(src2, X86::edx);
</span><span class="cx"> emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
</span><span class="lines">@@ -665,7 +676,7 @@
</span><span class="cx"> #if ENABLE(SAMPLING_TOOL)
</span><span class="cx"> m_jit.movl_i32m(-1, &currentOpcodeID);
</span><span class="cx"> #endif
</span><del>- m_jit.pushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi);
</del><ins>+ m_jit.pushl_m(RegisterFile::ReturnPC * sizeof(Register), X86::edi);
</ins><span class="cx"> m_jit.ret();
</span><span class="cx"> i += 2;
</span><span class="cx"> break;
</span><span class="lines">@@ -872,14 +883,14 @@
</span><span class="cx"> unsigned dst = instruction[i + 1].u.operand;
</span><span class="cx"> unsigned src1 = instruction[i + 2].u.operand;
</span><span class="cx"> unsigned src2 = instruction[i + 3].u.operand;
</span><del>- if (src1 < m_codeBlock->constantRegisters.size() || src2 < m_codeBlock->constantRegisters.size()) {
</del><ins>+ if (isConstant(src1) || isConstant(src2)) {
</ins><span class="cx"> unsigned constant = src1;
</span><span class="cx"> unsigned nonconstant = src2;
</span><del>- if (!(src1 < m_codeBlock->constantRegisters.size())) {
</del><ins>+ if (!isConstant(src1)) {
</ins><span class="cx"> constant = src2;
</span><span class="cx"> nonconstant = src1;
</span><span class="cx"> }
</span><del>- JSValue* value = m_codeBlock->constantRegisters[constant].jsValue(m_exec);
</del><ins>+ JSValue* value = getConstant(m_exec, constant);
</ins><span class="cx"> if (JSImmediate::isNumber(value)) {
</span><span class="cx"> emitGetArg(nonconstant, X86::eax);
</span><span class="cx"> emitJumpSlowCaseIfNotImmNum(X86::eax, i);
</span><span class="lines">@@ -915,7 +926,7 @@
</span><span class="cx"> }
</span><span class="cx"> case op_call: {
</span><span class="cx"> compileOpCall(instruction, i);
</span><del>- i += 6;
</del><ins>+ i += 7;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_get_global_var: {
</span><span class="lines">@@ -962,7 +973,7 @@
</span><span class="cx"> }
</span><span class="cx"> case op_ret: {
</span><span class="cx"> // Check for an activation - if there is one, jump to the hook below.
</span><del>- m_jit.cmpl_i32m(0, -(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::OptionalCalleeActivation) * sizeof(Register), X86::edi);
</del><ins>+ m_jit.cmpl_i32m(0, RegisterFile::OptionalCalleeActivation * sizeof(Register), X86::edi);
</ins><span class="cx"> X86Assembler::JmpSrc activation = m_jit.emitUnlinkedJne();
</span><span class="cx"> X86Assembler::JmpDst activated = m_jit.label();
</span><span class="cx">
</span><span class="lines">@@ -979,11 +990,11 @@
</span><span class="cx"> // Return the result in %eax, and the caller scope chain in %edx (this is read from the callee call frame,
</span><span class="cx"> // but is only assigned to ExecState::m_scopeChain if returning to a JSFunction).
</span><span class="cx"> emitGetArg(instruction[i + 1].u.operand, X86::eax);
</span><del>- m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CallerScopeChain) * sizeof(Register), X86::edi, X86::edx);
</del><ins>+ m_jit.movl_mr(RegisterFile::CallerScopeChain * sizeof(Register), X86::edi, X86::edx);
</ins><span class="cx"> // Restore the machine return addess from the callframe, roll the callframe back to the caller callframe,
</span><span class="cx"> // and preserve a copy of r on the stack at CTI_ARGS_r.
</span><del>- m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi, X86::ecx);
- m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CallerRegisters) * sizeof(Register), X86::edi, X86::edi);
</del><ins>+ m_jit.movl_mr(RegisterFile::ReturnPC * sizeof(Register), X86::edi, X86::ecx);
+ m_jit.movl_mr(RegisterFile::CallerRegisters * sizeof(Register), X86::edi, X86::edi);
</ins><span class="cx"> emitPutCTIParam(X86::edi, CTI_ARGS_r);
</span><span class="cx">
</span><span class="cx"> m_jit.pushl_r(X86::ecx);
</span><span class="lines">@@ -1021,7 +1032,7 @@
</span><span class="cx"> }
</span><span class="cx"> case op_construct: {
</span><span class="cx"> compileOpCall(instruction, i, OpConstruct);
</span><del>- i += 6;
</del><ins>+ i += 7;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_construct_verify: {
</span><span class="lines">@@ -1449,7 +1460,7 @@
</span><span class="cx"> }
</span><span class="cx"> case op_call_eval: {
</span><span class="cx"> compileOpCall(instruction, i, OpCallEval);
</span><del>- i += 6;
</del><ins>+ i += 7;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_throw: {
</span><span class="lines">@@ -1713,8 +1724,15 @@
</span><span class="cx"> i += 3;
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case op_initialise_locals: {
- i++;
</del><ins>+ case op_init: {
+ // Even though CTI doesn't use them, we initialize our constant
+ // registers to zap stale pointers, to avoid unnecessarily prolonging
+ // object lifetime and increasing GC pressure.
+ size_t count = m_codeBlock->numVars + m_codeBlock->constantRegisters.size();
+ for (size_t j = 0; j < count; ++j)
+ emitInitRegister(j);
+
+ i+= 1;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_get_array_length:
</span><span class="lines">@@ -1765,8 +1783,8 @@
</span><span class="cx"> case op_add: {
</span><span class="cx"> unsigned dst = instruction[i + 1].u.operand;
</span><span class="cx"> unsigned src2 = instruction[i + 3].u.operand;
</span><del>- if (src2 < m_codeBlock->constantRegisters.size()) {
- JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
</del><ins>+ if (isConstant(src2)) {
+ JSValue* value = getConstant(m_exec, src2);
</ins><span class="cx"> if (JSImmediate::isNumber(value)) {
</span><span class="cx"> X86Assembler::JmpSrc notImm = iter->from;
</span><span class="cx"> m_jit.link((++iter)->from, m_jit.label());
</span><span class="lines">@@ -1781,7 +1799,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- ASSERT(!(static_cast<unsigned>(instruction[i + 2].u.operand) < m_codeBlock->constantRegisters.size()));
</del><ins>+ ASSERT(!isConstant(instruction[i + 2].u.operand));
</ins><span class="cx">
</span><span class="cx"> X86Assembler::JmpSrc notImm = iter->from;
</span><span class="cx"> m_jit.link((++iter)->from, m_jit.label());
</span><span class="lines">@@ -2196,24 +2214,24 @@
</span><span class="cx">
</span><span class="cx"> // We jump to this slow case if the ctiCode for the codeBlock has not yet been generated; compile it now.
</span><span class="cx"> emitCall(i, Machine::cti_vm_compile);
</span><del>- m_jit.call_r(X86::eax);
-
</del><ins>+ emitCall(i, X86::eax);
+
</ins><span class="cx"> // Instead of checking for 0 we could initialize the CodeBlock::ctiCode to point to a trampoline that would trigger the translation.
</span><span class="cx">
</span><span class="cx"> // In the interpreter the following actions are performed by op_ret:
</span><del>-
- // Store the scope chain - returned by op_ret in %edx (see below) - to ExecState::m_scopeChain and CTI_ARGS_scopeChain on the stack.
</del><ins>+
+ // Restore ExecState::m_scopeChain and CTI_ARGS_scopeChain. NOTE: After
+ // op_ret, %edx holds the caller's scope chain.
</ins><span class="cx"> emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
</span><span class="cx"> emitPutCTIParam(X86::edx, CTI_ARGS_scopeChain);
</span><span class="cx"> m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_scopeChain), X86::ecx);
</span><span class="cx"> // Restore ExecState::m_callFrame.
</span><del>- m_jit.leal_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) * sizeof(Register), X86::edi, X86::edx);
- m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_callFrame), X86::ecx);
</del><ins>+ m_jit.movl_rm(X86::edi, OBJECT_OFFSET(ExecState, m_callFrame), X86::ecx);
</ins><span class="cx"> // Restore CTI_ARGS_codeBlock.
</span><span class="cx"> emitPutCTIParam(m_codeBlock, CTI_ARGS_codeBlock);
</span><span class="cx">
</span><span class="cx"> emitPutResult(instruction[i + 1].u.operand);
</span><del>- i += 6;
</del><ins>+ i += 7;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2233,7 +2251,7 @@
</span><span class="cx"> // Could use a popl_m, but would need to offset the following instruction if so.
</span><span class="cx"> m_jit.popl_r(X86::ecx);
</span><span class="cx"> emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
</span><del>- emitPutToCallFrameHeader(X86::ecx, RegisterFile::CTIReturnEIP);
</del><ins>+ emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
</ins><span class="cx">
</span><span class="cx"> // Lazy copy of the scopeChain
</span><span class="cx"> X86Assembler::JmpSrc callToUpdateScopeChain;
</span><span class="lines">@@ -2282,11 +2300,9 @@
</span><span class="cx"> for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter)
</span><span class="cx"> iter->nativeCode = m_jit.getRelocatedAddress(code, m_labels[iter->target]);
</span><span class="cx">
</span><del>- // FIXME: There doesn't seem to be a way to hint to a hashmap that it should make a certain capacity available;
- // could be faster if we could do something like this:
- // m_codeBlock->ctiReturnAddressVPCMap.grow(m_calls.size());
</del><span class="cx"> for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
</span><del>- X86Assembler::link(code, iter->from, iter->to);
</del><ins>+ if (iter->to)
+ X86Assembler::link(code, iter->from, iter->to);
</ins><span class="cx"> m_codeBlock->ctiReturnAddressVPCMap.add(m_jit.getRelocatedAddress(code, iter->from), iter->opcodeIndex);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCTIh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CTI.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CTI.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/CTI.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -76,6 +76,7 @@
</span><span class="cx"> #define ARG_src2 ((JSValue*)((ARGS)[2]))
</span><span class="cx"> #define ARG_src3 ((JSValue*)((ARGS)[3]))
</span><span class="cx"> #define ARG_src4 ((JSValue*)((ARGS)[4]))
</span><ins>+#define ARG_src5 ((JSValue*)((ARGS)[5]))
</ins><span class="cx"> #define ARG_id1 ((Identifier*)((ARGS)[1]))
</span><span class="cx"> #define ARG_id2 ((Identifier*)((ARGS)[2]))
</span><span class="cx"> #define ARG_id3 ((Identifier*)((ARGS)[3]))
</span><span class="lines">@@ -84,6 +85,7 @@
</span><span class="cx"> #define ARG_int2 ((int)((ARGS)[2]))
</span><span class="cx"> #define ARG_int3 ((int)((ARGS)[3]))
</span><span class="cx"> #define ARG_int4 ((int)((ARGS)[4]))
</span><ins>+#define ARG_int5 ((int)((ARGS)[5]))
</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 +96,7 @@
</span><span class="cx"> #define ARG_instr3 ((Instruction*)((ARGS)[3]))
</span><span class="cx"> #define ARG_instr4 ((Instruction*)((ARGS)[4]))
</span><span class="cx"> #define ARG_instr5 ((Instruction*)((ARGS)[5]))
</span><ins>+#define ARG_instr6 ((Instruction*)((ARGS)[6]))
</ins><span class="cx">
</span><span class="cx"> #define CTI_RETURN_ADDRESS ((ARGS)[-1])
</span><span class="cx">
</span><span class="lines">@@ -161,6 +164,13 @@
</span><span class="cx"> , opcodeIndex(i)
</span><span class="cx"> {
</span><span class="cx"> }
</span><ins>+
+ CallRecord(X86Assembler::JmpSrc f, unsigned i)
+ : from(f)
+ , to(0)
+ , opcodeIndex(i)
+ {
+ }
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> struct JmpTable {
</span><span class="lines">@@ -322,6 +332,10 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> CTI(Machine*, ExecState*, CodeBlock*);
</span><ins>+
+ bool isConstant(int src);
+ JSValue* CTI::getConstant(ExecState*, int src);
+
</ins><span class="cx"> void privateCompileMainPass();
</span><span class="cx"> void privateCompileLinkPass();
</span><span class="cx"> void privateCompileSlowCases();
</span><span class="lines">@@ -347,7 +361,7 @@
</span><span class="cx"> void emitPutArgConstant(unsigned value, unsigned offset);
</span><span class="cx"> void emitPutResult(unsigned dst, X86Assembler::RegisterID from = X86::eax);
</span><span class="cx">
</span><del>- void emitInitialiseRegister(unsigned dst);
</del><ins>+ void emitInitRegister(unsigned dst);
</ins><span class="cx">
</span><span class="cx"> void emitPutCTIParam(void* value, unsigned name);
</span><span class="cx"> void emitPutCTIParam(X86Assembler::RegisterID from, unsigned name);
</span><span class="lines">@@ -376,6 +390,7 @@
</span><span class="cx">
</span><span class="cx"> void emitDebugExceptionCheck();
</span><span class="cx">
</span><ins>+ X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, X86::RegisterID);
</ins><span class="cx"> X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_j);
</span><span class="cx"> X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_p);
</span><span class="cx"> X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_b);
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CodeBlock.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CodeBlock.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/CodeBlock.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -64,13 +64,10 @@
</span><span class="cx">
</span><span class="cx"> static CString registerName(int r)
</span><span class="cx"> {
</span><del>- if (r < 0)
- return (UString("lr") + UString::from(-r)).UTF8String();
-
</del><span class="cx"> if (r == missingThisObjectMarker())
</span><span class="cx"> return "<null>";
</span><span class="cx">
</span><del>- return (UString("tr") + UString::from(r)).UTF8String();
</del><ins>+ return (UString("r") + UString::from(r)).UTF8String();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static CString constantName(ExecState* exec, int k, JSValue* value)
</span><span class="lines">@@ -233,10 +230,10 @@
</span><span class="cx"> if (exec->machine()->isOpcode(it->u.opcode))
</span><span class="cx"> ++instructionCount;
</span><span class="cx">
</span><del>- printf("%lu instructions; %lu bytes at %p; %d locals (%d parameters); %d temporaries\n\n",
</del><ins>+ printf("%lu instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
</ins><span class="cx"> static_cast<unsigned long>(instructionCount),
</span><span class="cx"> static_cast<unsigned long>(instructions.size() * sizeof(Instruction)),
</span><del>- this, numLocals, numParameters, numTemporaries);
</del><ins>+ this, numParameters, numCalleeRegisters);
</ins><span class="cx">
</span><span class="cx"> for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
</span><span class="cx"> dump(exec, begin, it);
</span><span class="lines">@@ -254,7 +251,7 @@
</span><span class="cx"> printf("\nConstants:\n");
</span><span class="cx"> size_t i = 0;
</span><span class="cx"> do {
</span><del>- printf(" tr%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, constantRegisters[i].jsValue(exec)).ascii());
</del><ins>+ printf(" r%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, constantRegisters[i].jsValue(exec)).ascii());
</ins><span class="cx"> ++i;
</span><span class="cx"> } while (i < constantRegisters.size());
</span><span class="cx"> }
</span><span class="lines">@@ -351,8 +348,8 @@
</span><span class="cx"> {
</span><span class="cx"> int location = it - begin;
</span><span class="cx"> switch (exec->machine()->getOpcodeID(it->u.opcode)) {
</span><del>- case op_initialise_locals: {
- printf("[%4d] initialise_locals\n", location);
</del><ins>+ case op_init: {
+ printf("[%4d] init\n", location);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_unexpected_load: {
</span><span class="lines">@@ -779,7 +776,8 @@
</span><span class="cx"> int r2 = (++it)->u.operand;
</span><span class="cx"> int tempCount = (++it)->u.operand;
</span><span class="cx"> int argCount = (++it)->u.operand;
</span><del>- printf("[%4d] call\t\t %s, %s, %s, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount);
</del><ins>+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] call\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_call_eval: {
</span><span class="lines">@@ -788,7 +786,8 @@
</span><span class="cx"> int r2 = (++it)->u.operand;
</span><span class="cx"> int tempCount = (++it)->u.operand;
</span><span class="cx"> int argCount = (++it)->u.operand;
</span><del>- printf("[%4d] call_eval\t\t %s, %s, %s, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount);
</del><ins>+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] call_eval\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_ret: {
</span><span class="lines">@@ -802,7 +801,8 @@
</span><span class="cx"> int r2 = (++it)->u.operand;
</span><span class="cx"> int tempCount = (++it)->u.operand;
</span><span class="cx"> int argCount = (++it)->u.operand;
</span><del>- printf("[%4d] construct\t %s, %s, %s, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount);
</del><ins>+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] construct\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_construct_verify: {
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CodeBlock.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CodeBlock.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/CodeBlock.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -186,10 +186,10 @@
</span><span class="cx"> #if ENABLE(CTI)
</span><span class="cx"> , ctiCode(0)
</span><span class="cx"> #endif
</span><del>- , numTemporaries(0)
</del><ins>+ , numCalleeRegisters(0)
+ , numConstants(0)
</ins><span class="cx"> , numVars(0)
</span><span class="cx"> , numParameters(0)
</span><del>- , numLocals(0)
</del><span class="cx"> , needsFullScopeChain(ownerNode_->usesEval() || ownerNode_->needsClosure())
</span><span class="cx"> , usesEval(ownerNode_->usesEval())
</span><span class="cx"> , codeType(codeType_)
</span><span class="lines">@@ -217,15 +217,10 @@
</span><span class="cx"> StructureStubInfo& getStubInfo(void* returnAddress)
</span><span class="cx"> {
</span><span class="cx"> // FIXME: would a binary chop be faster here?
</span><del>- for (unsigned i = 0; i < structureIDInstructions.size(); ++i) {
</del><ins>+ for (unsigned i = 0; ; ++i) {
</ins><span class="cx"> if (structureIDInstructions[i].callReturnLocation == returnAddress)
</span><span class="cx"> return structureIDInstructions[i];
</span><span class="cx"> }
</span><del>-
- ASSERT_NOT_REACHED();
- // keep the compiler happy.
- static StructureStubInfo duff(0);
- return duff;
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ScopeNode* ownerNode;
</span><span class="lines">@@ -234,11 +229,15 @@
</span><span class="cx"> void* ctiCode;
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ int numCalleeRegisters;
+
+ // NOTE: numConstants holds the number of constant registers allocated
+ // by the code generator, not the number of constant registers used.
+ // (Duplicate constants are uniqued during code generation, and spare
+ // constant registers may be allocated.)
</ins><span class="cx"> int numConstants;
</span><del>- int numTemporaries;
</del><span class="cx"> int numVars;
</span><span class="cx"> int numParameters;
</span><del>- int numLocals;
</del><span class="cx"> int thisRegister;
</span><span class="cx"> bool needsFullScopeChain;
</span><span class="cx"> bool usesEval;
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CodeGenerator.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CodeGenerator.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/CodeGenerator.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -129,8 +129,8 @@
</span><span class="cx">
</span><span class="cx"> void CodeGenerator::generate()
</span><span class="cx"> {
</span><del>- m_codeBlock->numLocals = m_codeBlock->numVars + m_codeBlock->numParameters;
</del><span class="cx"> m_codeBlock->thisRegister = m_thisRegister.index();
</span><ins>+
</ins><span class="cx"> if (m_shouldEmitDebugHooks)
</span><span class="cx"> m_codeBlock->needsFullScopeChain = true;
</span><span class="cx">
</span><span class="lines">@@ -152,40 +152,50 @@
</span><span class="cx">
</span><span class="cx"> bool CodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
</span><span class="cx"> {
</span><del>- int index = m_nextVar;
</del><ins>+ int index = m_calleeRegisters.size();
</ins><span class="cx"> SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
</span><span class="cx"> pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
</span><span class="cx">
</span><del>- if (!result.second)
- index = result.first->second.getIndex();
- else {
- --m_nextVar;
- ++m_codeBlock->numVars;
-
- m_locals.append(index);
</del><ins>+ if (!result.second) {
+ r0 = &registerFor(result.first->second.getIndex());
+ return false;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- r0 = &m_locals[localsIndex(index)];
- return result.second;
</del><ins>+ ++m_codeBlock->numVars;
+ r0 = newRegister();
+ return true;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool CodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
</span><span class="cx"> {
</span><del>- int index = m_nextVar;
</del><ins>+ int index = m_nextGlobal;
</ins><span class="cx"> SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
</span><span class="cx"> pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
</span><span class="cx">
</span><span class="cx"> if (!result.second)
</span><span class="cx"> index = result.first->second.getIndex();
</span><span class="cx"> else {
</span><del>- --m_nextVar;
- m_locals.append(index + m_globalVarStorageOffset);
</del><ins>+ --m_nextGlobal;
+ m_globals.append(index + m_globalVarStorageOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- r0 = &m_locals[localsIndex(index)];
</del><ins>+ r0 = &registerFor(index);
</ins><span class="cx"> return result.second;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CodeGenerator::allocateConstants(size_t count)
+{
+ m_codeBlock->numConstants = count;
+ if (!count)
+ return;
+
+ m_nextConstant = m_calleeRegisters.size();
+
+ for (size_t i = 0; i < count; ++i)
+ newRegister();
+ m_lastConstant = &m_calleeRegisters.last();
+}
+
</ins><span class="cx"> CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock, VarStack& varStack, FunctionStack& functionStack)
</span><span class="cx"> : m_shouldEmitDebugHooks(!!debugger)
</span><span class="cx"> , m_scopeChain(&scopeChain)
</span><span class="lines">@@ -197,36 +207,36 @@
</span><span class="cx"> , m_dynamicScopeDepth(0)
</span><span class="cx"> , m_codeType(GlobalCode)
</span><span class="cx"> , m_continueDepth(0)
</span><del>- , m_nextVar(-1)
</del><ins>+ , m_nextGlobal(-1)
</ins><span class="cx"> , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
</span><span class="cx"> , m_lastOpcodeID(op_end)
</span><span class="cx"> {
</span><ins>+ emitOpcode(op_init);
</ins><span class="cx"> codeBlock->globalData = m_globalData;
</span><span class="cx">
</span><span class="cx"> // FIXME: Move code that modifies the global object to Machine::execute.
</span><span class="cx">
</span><del>- m_codeBlock->numConstants = programNode->neededConstants();
- m_codeBlock->numVars = 1; // Allocate space for "this"
</del><ins>+ m_codeBlock->numParameters = 1; // Allocate space for "this"
</ins><span class="cx">
</span><span class="cx"> JSGlobalObject* globalObject = scopeChain.globalObject();
</span><span class="cx"> ExecState* exec = globalObject->globalExec();
</span><span class="cx"> RegisterFile* registerFile = &exec->globalData().machine->registerFile();
</span><span class="cx">
</span><span class="cx"> // Shift register indexes in generated code to elide registers allocated by intermediate stack frames.
</span><del>- m_globalVarStorageOffset = -1 - RegisterFile::CallFrameHeaderSize - registerFile->size();
</del><ins>+ m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->numParameters - registerFile->size();
</ins><span class="cx">
</span><span class="cx"> // Add previously defined symbols to bookkeeping.
</span><del>- m_locals.resize(symbolTable->size());
</del><ins>+ m_globals.resize(symbolTable->size());
</ins><span class="cx"> SymbolTable::iterator end = symbolTable->end();
</span><span class="cx"> for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
</span><del>- m_locals[localsIndex(it->second.getIndex())].setIndex(it->second.getIndex() + m_globalVarStorageOffset);
</del><ins>+ registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset);
</ins><span class="cx">
</span><span class="cx"> BatchedTransitionOptimizer optimizer(globalObject);
</span><span class="cx">
</span><span class="cx"> bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals();
</span><span class="cx"> if (canOptimizeNewGlobals) {
</span><span class="cx"> // Shift new symbols so they get stored prior to existing symbols.
</span><del>- m_nextVar -= symbolTable->size();
</del><ins>+ m_nextGlobal -= symbolTable->size();
</ins><span class="cx">
</span><span class="cx"> for (size_t i = 0; i < functionStack.size(); ++i) {
</span><span class="cx"> FuncDeclNode* funcDecl = functionStack[i].get();
</span><span class="lines">@@ -234,10 +244,15 @@
</span><span class="cx"> emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- for (size_t i = 0; i < varStack.size(); ++i) {
</del><ins>+ Vector<RegisterID*, 32> newVars;
+ for (size_t i = 0; i < varStack.size(); ++i)
</ins><span class="cx"> if (!globalObject->hasProperty(exec, varStack[i].first))
</span><del>- emitLoad(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant), jsUndefined());
- }
</del><ins>+ newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
+
+ allocateConstants(programNode->neededConstants());
+
+ for (size_t i = 0; i < newVars.size(); ++i)
+ emitLoad(newVars[i], jsUndefined());
</ins><span class="cx"> } else {
</span><span class="cx"> for (size_t i = 0; i < functionStack.size(); ++i) {
</span><span class="cx"> FuncDeclNode* funcDecl = functionStack[i].get();
</span><span class="lines">@@ -251,6 +266,8 @@
</span><span class="cx"> attributes |= ReadOnly;
</span><span class="cx"> globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
</span><span class="cx"> }
</span><ins>+
+ allocateConstants(programNode->neededConstants());
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -264,15 +281,12 @@
</span><span class="cx"> , m_dynamicScopeDepth(0)
</span><span class="cx"> , m_codeType(FunctionCode)
</span><span class="cx"> , m_continueDepth(0)
</span><del>- , m_nextVar(-1)
</del><span class="cx"> , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
</span><span class="cx"> , m_lastOpcodeID(op_end)
</span><span class="cx"> {
</span><del>- emitOpcode(op_initialise_locals);
</del><ins>+ emitOpcode(op_init);
</ins><span class="cx"> codeBlock->globalData = m_globalData;
</span><span class="cx">
</span><del>- m_codeBlock->numConstants = functionBody->neededConstants();
-
</del><span class="cx"> const Node::FunctionStack& functionStack = functionBody->functionStack();
</span><span class="cx"> for (size_t i = 0; i < functionStack.size(); ++i) {
</span><span class="cx"> FuncDeclNode* funcDecl = functionStack[i].get();
</span><span class="lines">@@ -291,8 +305,8 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Vector<Identifier>& parameters = functionBody->parameters();
</span><del>- m_nextParameter = m_nextVar - parameters.size(); // parameters are allocated prior to vars
- m_locals.resize(localsIndex(m_nextParameter) + 1); // localsIndex of 0 => m_locals size of 1
</del><ins>+ m_nextParameter = -RegisterFile::CallFrameHeaderSize - parameters.size() - 1;
+ m_parameters.resize(1 + parameters.size()); // reserve space for "this"
</ins><span class="cx">
</span><span class="cx"> // Add "this" as a parameter
</span><span class="cx"> m_thisRegister.setIndex(m_nextParameter);
</span><span class="lines">@@ -301,6 +315,8 @@
</span><span class="cx">
</span><span class="cx"> for (size_t i = 0; i < parameters.size(); ++i)
</span><span class="cx"> addParameter(parameters[i]);
</span><ins>+
+ allocateConstants(functionBody->neededConstants());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> CodeGenerator::CodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
</span><span class="lines">@@ -317,27 +333,23 @@
</span><span class="cx"> , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
</span><span class="cx"> , m_lastOpcodeID(op_end)
</span><span class="cx"> {
</span><del>- emitOpcode(op_initialise_locals);
</del><ins>+ emitOpcode(op_init);
</ins><span class="cx"> codeBlock->globalData = m_globalData;
</span><ins>+ m_codeBlock->numParameters = 1; // Allocate space for "this"
</ins><span class="cx">
</span><del>- m_codeBlock->numConstants = evalNode->neededConstants();
- m_codeBlock->numVars = 1; // Allocate space for "this"
</del><ins>+ allocateConstants(evalNode->neededConstants());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-CodeGenerator::~CodeGenerator()
-{
-}
-
</del><span class="cx"> RegisterID* CodeGenerator::addParameter(const Identifier& ident)
</span><span class="cx"> {
</span><del>- // Parameters overwrite var declarations, but not function declarations,
- // in the symbol table.
</del><ins>+ // Parameters overwrite var declarations, but not function declarations.
</ins><span class="cx"> RegisterID* result = 0;
</span><span class="cx"> UString::Rep* rep = ident.ustring().rep();
</span><span class="cx"> if (!m_functions.contains(rep)) {
</span><span class="cx"> symbolTable().set(rep, m_nextParameter);
</span><del>- m_locals[localsIndex(m_nextParameter)].setIndex(m_nextParameter);
- result = &(m_locals[localsIndex(m_nextParameter)]);
</del><ins>+ RegisterID& parameter = registerFor(m_nextParameter);
+ parameter.setIndex(m_nextParameter);
+ result = &parameter;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // To maintain the calling convention, we have to allocate unique space for
</span><span class="lines">@@ -347,7 +359,7 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* CodeGenerator::registerForLocal(const Identifier& ident)
</del><ins>+RegisterID* CodeGenerator::registerFor(const Identifier& ident)
</ins><span class="cx"> {
</span><span class="cx"> if (m_codeType == FunctionCode && ident == propertyNames().arguments)
</span><span class="cx"> m_codeBlock->needsFullScopeChain = true;
</span><span class="lines">@@ -362,10 +374,10 @@
</span><span class="cx"> if (entry.isNull())
</span><span class="cx"> return 0;
</span><span class="cx">
</span><del>- return &m_locals[localsIndex(entry.getIndex())];
</del><ins>+ return &registerFor(entry.getIndex());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* CodeGenerator::registerForLocalConstInit(const Identifier& ident)
</del><ins>+RegisterID* CodeGenerator::constRegisterFor(const Identifier& ident)
</ins><span class="cx"> {
</span><span class="cx"> if (m_codeType == EvalCode)
</span><span class="cx"> return 0;
</span><span class="lines">@@ -373,7 +385,7 @@
</span><span class="cx"> SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
</span><span class="cx"> ASSERT(!entry.isNull());
</span><span class="cx">
</span><del>- return &m_locals[localsIndex(entry.getIndex())];
</del><ins>+ return &registerFor(entry.getIndex());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool CodeGenerator::isLocal(const Identifier& ident)
</span><span class="lines">@@ -389,23 +401,30 @@
</span><span class="cx"> return symbolTable().get(ident.ustring().rep()).isReadOnly();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+RegisterID* CodeGenerator::newRegister()
+{
+ m_calleeRegisters.append(m_calleeRegisters.size());
+ m_codeBlock->numCalleeRegisters = max<int>(m_codeBlock->numCalleeRegisters, m_calleeRegisters.size());
+ return &m_calleeRegisters.last();
+}
+
</ins><span class="cx"> RegisterID* CodeGenerator::newTemporary()
</span><span class="cx"> {
</span><span class="cx"> // Reclaim free register IDs.
</span><del>- while (m_temporaries.size() && !m_temporaries.last().refCount())
- m_temporaries.removeLast();
-
- // Allocate new register ID.
- m_temporaries.append(m_temporaries.size() + m_codeBlock->numConstants);
- m_codeBlock->numTemporaries = max<int>(m_codeBlock->numTemporaries, m_temporaries.size());
- return &m_temporaries.last();
</del><ins>+ while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
+ m_calleeRegisters.removeLast();
+
+ RegisterID* result = newRegister();
+ result->setTemporary();
+ return result;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* CodeGenerator::highestUsedRegister()
</span><span class="cx"> {
</span><del>- while (m_temporaries.size() < static_cast<unsigned>(m_codeBlock->numTemporaries))
- m_temporaries.append(m_temporaries.size());
- return &m_temporaries.last();
</del><ins>+ size_t count = m_codeBlock->numCalleeRegisters;
+ while (m_calleeRegisters.size() < count)
+ newRegister();
+ return &m_calleeRegisters.last();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> PassRefPtr<LabelID> CodeGenerator::newLabel()
</span><span class="lines">@@ -579,16 +598,17 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* CodeGenerator::addConstant(JSValue* v)
</span><span class="cx"> {
</span><del>- pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_codeBlock->constantRegisters.size());
</del><ins>+ pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_nextConstant);
</ins><span class="cx"> if (result.second) {
</span><del>- m_constants.append(m_codeBlock->constantRegisters.size());
- m_constants.last().makeConstant();
</del><ins>+ RegisterID& constant = m_calleeRegisters[m_nextConstant];
+
+ ++m_nextConstant;
+
</ins><span class="cx"> m_codeBlock->constantRegisters.append(v);
</span><del>- ASSERT(m_codeBlock->constantRegisters.size() <= (unsigned) m_codeBlock->numConstants);
- return &m_constants.last();
</del><ins>+ return &constant;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- return &m_constants[result.first->second];
</del><ins>+ return &registerFor(result.first->second);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> unsigned CodeGenerator::addUnexpectedConstant(JSValue* v)
</span><span class="lines">@@ -1089,18 +1109,9 @@
</span><span class="cx"> RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
</span><ins>+ ASSERT(func->refCount());
+ ASSERT(!base || base->refCount());
</ins><span class="cx">
</span><del>- // Ordinarily, we might ref "func" and "base", to avoid allocating new
- // temporaries in the same registers. In this case, though, we actually
- // want the call frame we allocate to overlap "func" and "base", if they're
- // not otherwise referenced. op_call will read "func" and "base" before
- // writing out the call frame, so this is safe.
-
- // Reserve space for call frame.
- Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
- for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
- callFrame.append(newTemporary());
-
</del><span class="cx"> // Generate code for arguments.
</span><span class="cx"> Vector<RefPtr<RegisterID>, 16> argv;
</span><span class="cx"> argv.append(newTemporary()); // reserve space for "this"
</span><span class="lines">@@ -1109,6 +1120,11 @@
</span><span class="cx"> emitNode(argv.last().get(), n);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ // Reserve space for call frame.
+ Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
+ for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
+ callFrame.append(newTemporary());
+
</ins><span class="cx"> emitExpressionInfo(divot, startOffset, endOffset);
</span><span class="cx"> emitOpcode(opcodeID);
</span><span class="cx"> instructions().append(dst->index());
</span><span class="lines">@@ -1116,6 +1132,7 @@
</span><span class="cx"> instructions().append(base ? base->index() : missingThisObjectMarker()); // We encode the "this" value in the instruction stream, to avoid an explicit instruction for copying or loading it.
</span><span class="cx"> instructions().append(argv[0]->index()); // argv
</span><span class="cx"> instructions().append(argv.size()); // argc
</span><ins>+ instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
</ins><span class="cx"> return dst;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1130,14 +1147,11 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(func->refCount());
</span><span class="cx">
</span><del>- // Reserve space for prototype
</del><ins>+ // Load prototype.
+ emitExpressionInfo(divot, startOffset, endOffset);
</ins><span class="cx"> RefPtr<RegisterID> funcProto = newTemporary();
</span><ins>+ emitGetById(funcProto.get(), func, globalExec()->propertyNames().prototype);
</ins><span class="cx">
</span><del>- // Reserve space for call frame.
- Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
- for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
- callFrame.append(newTemporary());
-
</del><span class="cx"> // Generate code for arguments.
</span><span class="cx"> Vector<RefPtr<RegisterID>, 16> argv;
</span><span class="cx"> argv.append(newTemporary()); // reserve space for "this"
</span><span class="lines">@@ -1146,8 +1160,10 @@
</span><span class="cx"> emitNode(argv.last().get(), n);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- emitExpressionInfo(divot, startOffset, endOffset);
- emitGetById(funcProto.get(), func, globalExec()->propertyNames().prototype);
</del><ins>+ // Reserve space for call frame.
+ Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
+ for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
+ callFrame.append(newTemporary());
</ins><span class="cx">
</span><span class="cx"> emitExpressionInfo(divot, startOffset, endOffset);
</span><span class="cx"> emitOpcode(op_construct);
</span><span class="lines">@@ -1156,7 +1172,8 @@
</span><span class="cx"> instructions().append(funcProto->index());
</span><span class="cx"> instructions().append(argv[0]->index()); // argv
</span><span class="cx"> instructions().append(argv.size()); // argc
</span><del>-
</del><ins>+ instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
+
</ins><span class="cx"> emitOpcode(op_construct_verify);
</span><span class="cx"> instructions().append(dst->index());
</span><span class="cx"> instructions().append(argv[0]->index());
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMCodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/CodeGenerator.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/CodeGenerator.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/CodeGenerator.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -79,20 +79,19 @@
</span><span class="cx"> CodeGenerator(FunctionBodyNode*, const Debugger*, const ScopeChain&, SymbolTable*, CodeBlock*);
</span><span class="cx"> CodeGenerator(EvalNode*, const Debugger*, const ScopeChain&, SymbolTable*, EvalCodeBlock*);
</span><span class="cx">
</span><del>- ~CodeGenerator();
-
</del><span class="cx"> JSGlobalData* globalData() const { return m_globalData; }
</span><span class="cx"> const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }
</span><span class="cx">
</span><span class="cx"> void generate();
</span><span class="cx">
</span><span class="cx"> // Returns the register corresponding to a local variable, or 0 if no
</span><del>- // such register exists. Registers returned by registerForLocal do not
</del><ins>+ // such register exists. Registers returned by registerFor do not
</ins><span class="cx"> // require explicit reference counting.
</span><del>- RegisterID* registerForLocal(const Identifier&);
- // Behaves as registerForLocal does, but ignores dynamic scope as
</del><ins>+ RegisterID* registerFor(const Identifier&);
+
+ // Behaves as registerFor does, but ignores dynamic scope as
</ins><span class="cx"> // dynamic scope should not interfere with const initialisation
</span><del>- RegisterID* registerForLocalConstInit(const Identifier&);
</del><ins>+ RegisterID* constRegisterFor(const Identifier&);
</ins><span class="cx">
</span><span class="cx"> // Searches the scope chain in an attempt to statically locate the requested
</span><span class="cx"> // property. Returns false if for any reason the property cannot be safely
</span><span class="lines">@@ -352,10 +351,9 @@
</span><span class="cx"> typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap;
</span><span class="cx">
</span><span class="cx"> RegisterID* emitCall(OpcodeID, RegisterID*, RegisterID*, RegisterID*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
</span><ins>+
+ RegisterID* newRegister();
</ins><span class="cx">
</span><del>- // Maps a register index in the symbol table to a RegisterID index in m_locals.
- int localsIndex(int registerIndex) { return -registerIndex - 1; }
-
</del><span class="cx"> // Returns the RegisterID corresponding to ident.
</span><span class="cx"> RegisterID* addVar(const Identifier& ident, bool isConstant)
</span><span class="cx"> {
</span><span class="lines">@@ -377,7 +375,22 @@
</span><span class="cx"> bool addGlobalVar(const Identifier&, bool isConstant, RegisterID*&);
</span><span class="cx">
</span><span class="cx"> RegisterID* addParameter(const Identifier&);
</span><ins>+
+ void allocateConstants(size_t);
</ins><span class="cx">
</span><ins>+ RegisterID& registerFor(int index)
+ {
+ if (index >= 0)
+ return m_calleeRegisters[index];
+
+ if (m_parameters.size()) {
+ ASSERT(!m_globals.size());
+ return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
+ }
+
+ return m_globals[-index - 1];
+ }
+
</ins><span class="cx"> unsigned addConstant(FuncDeclNode*);
</span><span class="cx"> unsigned addConstant(FuncExprNode*);
</span><span class="cx"> unsigned addConstant(const Identifier&);
</span><span class="lines">@@ -403,9 +416,10 @@
</span><span class="cx">
</span><span class="cx"> HashSet<RefPtr<UString::Rep>, IdentifierRepHash> m_functions;
</span><span class="cx"> RegisterID m_thisRegister;
</span><del>- SegmentedVector<RegisterID, 512> m_locals;
- SegmentedVector<RegisterID, 512> m_constants;
- SegmentedVector<RegisterID, 512> m_temporaries;
</del><ins>+ RefPtr<RegisterID> m_lastConstant;
+ SegmentedVector<RegisterID, 512> m_calleeRegisters;
+ SegmentedVector<RegisterID, 512> m_parameters;
+ SegmentedVector<RegisterID, 512> m_globals;
</ins><span class="cx"> SegmentedVector<LabelID, 512> m_labels;
</span><span class="cx"> int m_finallyDepth;
</span><span class="cx"> int m_dynamicScopeDepth;
</span><span class="lines">@@ -416,8 +430,9 @@
</span><span class="cx"> Vector<ControlFlowContext> m_scopeContextStack;
</span><span class="cx"> Vector<SwitchInfo> m_switchContextStack;
</span><span class="cx">
</span><del>- int m_nextVar;
</del><ins>+ int m_nextGlobal;
</ins><span class="cx"> int m_nextParameter;
</span><ins>+ int m_nextConstant;
</ins><span class="cx">
</span><span class="cx"> int m_globalVarStorageOffset;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMMachinecpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/Machine.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/Machine.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/Machine.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -83,6 +83,27 @@
</span><span class="cx"> static void* op_call_indirect;
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+#if ENABLE(CTI)
+
+ALWAYS_INLINE static Instruction* vPCForPC(CodeBlock* codeBlock, void* pc)
+{
+ if (pc >= codeBlock->instructions.begin() && pc < codeBlock->instructions.end())
+ return static_cast<Instruction*>(pc);
+
+ ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(pc));
+ unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(pc);
+ return codeBlock->instructions.begin() + vPCIndex;
+}
+
+#else // #ENABLE(CTI)
+
+ALWAYS_INLINE static Instruction* vPCForPC(CodeBlock*, void* pc)
+{
+ return static_cast<Instruction*>(pc);
+}
+
+#endif // #ENABLE(CTI)
+
</ins><span class="cx"> // Returns the depth of the scope chain within a given call frame.
</span><span class="cx"> static int depth(CodeBlock* codeBlock, ScopeChain& sc)
</span><span class="cx"> {
</span><span class="lines">@@ -498,23 +519,21 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx">
</span><del>-ALWAYS_INLINE void Machine::initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argv, int argc, JSValue* function)
</del><ins>+ALWAYS_INLINE void Machine::initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argc, JSValue* function)
</ins><span class="cx"> {
</span><span class="cx"> callFrame[RegisterFile::CallerCodeBlock] = codeBlock;
</span><del>- callFrame[RegisterFile::ReturnVPC] = vPC + 1;
</del><span class="cx"> callFrame[RegisterFile::CallerScopeChain] = scopeChain;
</span><span class="cx"> callFrame[RegisterFile::CallerRegisters] = r;
</span><ins>+ callFrame[RegisterFile::ReturnPC] = vPC + 1;
</ins><span class="cx"> callFrame[RegisterFile::ReturnValueRegister] = returnValueRegister;
</span><del>- callFrame[RegisterFile::ArgumentStartRegister] = argv; // original argument vector (for the sake of the "arguments" object)
</del><span class="cx"> callFrame[RegisterFile::ArgumentCount] = argc; // original argument count (for the sake of the "arguments" object)
</span><span class="cx"> callFrame[RegisterFile::Callee] = function;
</span><span class="cx"> callFrame[RegisterFile::OptionalCalleeActivation] = nullJSValue;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, int argv, int argc, JSValue*& exceptionValue)
</del><ins>+ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, size_t registerOffset, int argc, JSValue*& exceptionValue)
</ins><span class="cx"> {
</span><del>- size_t registerOffset = argv + newCodeBlock->numLocals;
- size_t size = r - registerBase + registerOffset + newCodeBlock->numConstants + newCodeBlock->numTemporaries;
</del><ins>+ size_t size = r - registerBase + registerOffset + newCodeBlock->numCalleeRegisters;
</ins><span class="cx">
</span><span class="cx"> if (argc == newCodeBlock->numParameters) { // correct number of arguments
</span><span class="cx"> if (!registerFile->grow(size)) {
</span><span class="lines">@@ -523,20 +542,22 @@
</span><span class="cx"> }
</span><span class="cx"> r += registerOffset;
</span><span class="cx"> } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
</span><ins>+ size_t omittedArgCount = newCodeBlock->numParameters - argc;
+ registerOffset += omittedArgCount;
+ size += omittedArgCount;
</ins><span class="cx"> if (!registerFile->grow(size)) {
</span><span class="cx"> exceptionValue = createStackOverflowError(exec);
</span><span class="cx"> return r;
</span><span class="cx"> }
</span><span class="cx"> r += registerOffset;
</span><span class="cx">
</span><del>- int omittedArgCount = newCodeBlock->numParameters - argc;
- Register* endOfParams = r - newCodeBlock->numVars;
- for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
- (*it) = jsUndefined();
- } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
- int shift = argc + RegisterFile::CallFrameHeaderSize;
- registerOffset += shift;
- size += shift;
</del><ins>+ Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
+ for (size_t i = 0; i < omittedArgCount; ++i)
+ argv[i] = jsUndefined();
+ } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
+ size_t numParameters = newCodeBlock->numParameters;
+ registerOffset += numParameters;
+ size += numParameters;
</ins><span class="cx">
</span><span class="cx"> if (!registerFile->grow(size)) {
</span><span class="cx"> exceptionValue = createStackOverflowError(exec);
</span><span class="lines">@@ -544,20 +565,11 @@
</span><span class="cx"> }
</span><span class="cx"> r += registerOffset;
</span><span class="cx">
</span><del>- Register* it = r - newCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize - shift;
- Register* end = it + RegisterFile::CallFrameHeaderSize + newCodeBlock->numParameters;
- for ( ; it != end; ++it)
- *(it + shift) = *it;
</del><ins>+ Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
+ for (size_t i = 0; i < numParameters; ++i)
+ argv[i + argc] = argv[i];
</ins><span class="cx"> }
</span><del>-
- // initialize local variable slots
-#if ENABLE(CTI)
- if (!newCodeBlock->ctiCode)
-#endif
- {
</del><span class="cx">
</span><del>- }
-
</del><span class="cx"> return r;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -565,7 +577,7 @@
</span><span class="cx"> {
</span><span class="cx"> if (newCodeBlock->needsFullScopeChain) {
</span><span class="cx"> JSActivation* activation = new (exec) JSActivation(exec, functionBodyNode, r);
</span><del>- r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation;
</del><ins>+ r[RegisterFile::OptionalCalleeActivation] = activation;
</ins><span class="cx">
</span><span class="cx"> return callDataScopeChain->copy()->push(activation);
</span><span class="cx"> }
</span><span class="lines">@@ -601,7 +613,7 @@
</span><span class="cx">
</span><span class="cx"> JSValue* result = 0;
</span><span class="cx"> if (evalNode)
</span><del>- result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
</del><ins>+ result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + 1 + RegisterFile::CallFrameHeaderSize, scopeChain, &exceptionValue);
</ins><span class="cx">
</span><span class="cx"> if (*profiler)
</span><span class="cx"> (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
</span><span class="lines">@@ -683,46 +695,58 @@
</span><span class="cx"> printf("----------------------------------------------------\n");
</span><span class="cx"> }
</span><span class="cx">
</span><del>- it = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><ins>+ it = r - RegisterFile::CallFrameHeaderSize - codeBlock->numParameters;
+ printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
+ end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
+ if (it != end) {
+ do {
+ printf("[param] | %10p | %10p \n", it, (*it).v());
+ ++it;
+ } while (it != end);
+ }
+ printf("----------------------------------------------------\n");
+
</ins><span class="cx"> printf("[CallerCodeBlock] | %10p | %10p \n", it, (*it).v()); ++it;
</span><del>- printf("[ReturnVPC] | %10p | %10p \n", it, (*it).v()); ++it;
</del><span class="cx"> printf("[CallerScopeChain] | %10p | %10p \n", it, (*it).v()); ++it;
</span><del>- printf("[CallerRegisterOffset] | %10p | %10p \n", it, (*it).v()); ++it;
</del><ins>+ printf("[CallerRegisters] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[ReturnPC] | %10p | %10p \n", it, (*it).v()); ++it;
</ins><span class="cx"> printf("[ReturnValueRegister] | %10p | %10p \n", it, (*it).v()); ++it;
</span><del>- printf("[ArgumentStartRegister] | %10p | %10p \n", it, (*it).v()); ++it;
</del><span class="cx"> printf("[ArgumentCount] | %10p | %10p \n", it, (*it).v()); ++it;
</span><span class="cx"> printf("[Callee] | %10p | %10p \n", it, (*it).v()); ++it;
</span><span class="cx"> printf("[OptionalCalleeActivation] | %10p | %10p \n", it, (*it).v()); ++it;
</span><span class="cx"> printf("----------------------------------------------------\n");
</span><span class="cx">
</span><del>- printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
- end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
</del><ins>+ int registerCount = 0;
+
+ end = it + codeBlock->numVars;
</ins><span class="cx"> if (it != end) {
</span><span class="cx"> do {
</span><del>- printf("[param] | %10p | %10p \n", it, (*it).v());
</del><ins>+ printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
</ins><span class="cx"> ++it;
</span><ins>+ ++registerCount;
</ins><span class="cx"> } while (it != end);
</span><span class="cx"> }
</span><span class="cx"> printf("----------------------------------------------------\n");
</span><span class="cx">
</span><del>- if (codeBlock->codeType != GlobalCode) {
- end = it + codeBlock->numVars;
- if (it != end) {
- do {
- printf("[var] | %10p | %10p \n", it, (*it).v());
- ++it;
- } while (it != end);
- printf("----------------------------------------------------\n");
- }
</del><ins>+ end = it + codeBlock->numConstants;
+ if (it != end) {
+ do {
+ printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
+ ++it;
+ ++registerCount;
+ } while (it != end);
</ins><span class="cx"> }
</span><ins>+ printf("----------------------------------------------------\n");
</ins><span class="cx">
</span><del>- end = it + codeBlock->numTemporaries;
</del><ins>+ end = it + codeBlock->numCalleeRegisters - codeBlock->numConstants - codeBlock->numVars;
</ins><span class="cx"> if (it != end) {
</span><span class="cx"> do {
</span><del>- printf("[temp] | %10p | %10p \n", it, (*it).v());
</del><ins>+ printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
</ins><span class="cx"> ++it;
</span><ins>+ ++registerCount;
</ins><span class="cx"> } while (it != end);
</span><span class="cx"> }
</span><ins>+ printf("----------------------------------------------------\n");
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #endif
</span><span class="lines">@@ -745,19 +769,18 @@
</span><span class="cx"> NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
</span><span class="cx"> {
</span><span class="cx"> CodeBlock* oldCodeBlock = codeBlock;
</span><del>- Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><span class="cx">
</span><span class="cx"> if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
</span><span class="cx"> DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
</span><del>- if (callFrame[RegisterFile::Callee].jsValue(exec))
</del><ins>+ if (r[RegisterFile::Callee].jsValue(exec))
</ins><span class="cx"> debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
</span><span class="cx"> else
</span><span class="cx"> debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
</span><del>- if (callFrame[RegisterFile::Callee].jsValue(exec))
- profiler->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
</del><ins>+ if (r[RegisterFile::Callee].jsValue(exec))
+ profiler->didExecute(exec, static_cast<JSObject*>(r[RegisterFile::Callee].jsValue(exec)));
</ins><span class="cx"> else
</span><span class="cx"> profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
</span><span class="cx"> }
</span><span class="lines">@@ -766,19 +789,19 @@
</span><span class="cx"> scopeChain->deref();
</span><span class="cx">
</span><span class="cx"> // If this call frame created an activation, tear it off.
</span><del>- if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
</del><ins>+ if (JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
</ins><span class="cx"> ASSERT(activation->isActivationObject());
</span><span class="cx"> activation->copyRegisters();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
</del><ins>+ codeBlock = r[RegisterFile::CallerCodeBlock].codeBlock();
</ins><span class="cx"> if (!codeBlock)
</span><span class="cx"> return false;
</span><span class="cx">
</span><del>- scopeChain = callFrame[RegisterFile::CallerScopeChain].scopeChain();
- r = callFrame[RegisterFile::CallerRegisters].r();
- exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
- vPC = callFrame[RegisterFile::ReturnVPC].vPC();
</del><ins>+ scopeChain = r[RegisterFile::CallerScopeChain].scopeChain();
+ vPC = vPCForPC(codeBlock, r[RegisterFile::ReturnPC].v());
+ r = r[RegisterFile::CallerRegisters].r();
+ exec->m_callFrame = r;
</ins><span class="cx">
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="lines">@@ -862,7 +885,7 @@
</span><span class="cx"> CodeBlock* codeBlock = &programNode->byteCode(scopeChain);
</span><span class="cx">
</span><span class="cx"> size_t oldSize = m_registerFile.size();
</span><del>- size_t newSize = oldSize + RegisterFile::CallFrameHeaderSize + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries;
</del><ins>+ size_t newSize = oldSize + codeBlock->numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->numCalleeRegisters;
</ins><span class="cx"> if (!m_registerFile.grow(newSize)) {
</span><span class="cx"> *exception = createStackOverflowError(exec);
</span><span class="cx"> return 0;
</span><span class="lines">@@ -872,17 +895,10 @@
</span><span class="cx"> JSGlobalObject* globalObject = exec->dynamicGlobalObject();
</span><span class="cx"> globalObject->copyGlobalsTo(m_registerFile);
</span><span class="cx">
</span><del>- Register* callFrame = m_registerFile.base() + oldSize;
-
- // a 0 codeBlock indicates a built-in caller
- initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0);
-
- Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
</del><ins>+ Register* r = m_registerFile.base() + oldSize + codeBlock->numParameters + RegisterFile::CallFrameHeaderSize;
</ins><span class="cx"> r[codeBlock->thisRegister] = thisObj;
</span><ins>+ initializeCallFrame(r, 0, 0, 0, 0, 0, 0, 0);
</ins><span class="cx">
</span><del>- for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
- r[i] = codeBlock->constantRegisters[i];
-
</del><span class="cx"> if (codeBlock->needsFullScopeChain)
</span><span class="cx"> scopeChain = scopeChain->copy();
</span><span class="cx">
</span><span class="lines">@@ -921,36 +937,32 @@
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- int argv = RegisterFile::CallFrameHeaderSize;
- int argc = args.size() + 1; // implicit "this" parameter
</del><ins>+ size_t oldSize = m_registerFile.size();
+ int argc = 1 + args.size(); // implicit "this" parameter
</ins><span class="cx">
</span><del>- size_t oldSize = m_registerFile.size();
- if (!m_registerFile.grow(oldSize + RegisterFile::CallFrameHeaderSize + argc)) {
</del><ins>+ if (!m_registerFile.grow(oldSize + argc)) {
</ins><span class="cx"> *exception = createStackOverflowError(exec);
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- Register* callFrame = m_registerFile.base() + oldSize;
</del><ins>+ Register* argv = m_registerFile.base() + oldSize;
+ size_t dst = 0;
+ argv[dst] = thisObj;
</ins><span class="cx">
</span><del>- // put args in place, including "this"
- Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
- (*dst) = thisObj;
-
</del><span class="cx"> ArgList::const_iterator end = args.end();
</span><span class="cx"> for (ArgList::const_iterator it = args.begin(); it != end; ++it)
</span><del>- (*++dst) = *it;
</del><ins>+ argv[++dst] = *it;
</ins><span class="cx">
</span><del>- // a 0 codeBlock indicates a built-in caller
- initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, function);
-
</del><span class="cx"> CodeBlock* newCodeBlock = &functionBodyNode->byteCode(scopeChain);
</span><del>- Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
- if (*exception) {
</del><ins>+ Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), argv, argc + RegisterFile::CallFrameHeaderSize, argc, *exception);
+ if (UNLIKELY(*exception != 0)) {
</ins><span class="cx"> m_registerFile.shrink(oldSize);
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><ins>+ // a 0 codeBlock indicates a built-in caller
+ initializeCallFrame(r, 0, 0, 0, argv, 0, argc, function);
</ins><span class="cx">
</span><del>- ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
</del><ins>+ ExecState newExec(exec, &m_registerFile, scopeChain, r);
</ins><span class="cx">
</span><span class="cx"> Profiler** profiler = Profiler::enabledProfilerReference();
</span><span class="cx"> if (*profiler)
</span><span class="lines">@@ -973,6 +985,11 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception)
+{
+ return execute(evalNode, exec, thisObj, m_registerFile.size() + evalNode->byteCode(scopeChain).numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
+}
+
</ins><span class="cx"> JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
</span><span class="cx"> {
</span><span class="cx"> if (m_reentryDepth >= MaxReentryDepth) {
</span><span class="lines">@@ -1015,23 +1032,18 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> size_t oldSize = m_registerFile.size();
</span><del>- size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries + RegisterFile::CallFrameHeaderSize;
</del><ins>+ size_t newSize = registerOffset + codeBlock->numCalleeRegisters;
</ins><span class="cx"> if (!m_registerFile.grow(newSize)) {
</span><span class="cx"> *exception = createStackOverflowError(exec);
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- Register* callFrame = m_registerFile.base() + registerOffset;
</del><ins>+ Register* r = m_registerFile.base() + registerOffset;
</ins><span class="cx">
</span><span class="cx"> // a 0 codeBlock indicates a built-in caller
</span><del>- initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0);
-
- Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
</del><span class="cx"> r[codeBlock->thisRegister] = thisObj;
</span><ins>+ initializeCallFrame(r, 0, 0, 0, 0, 0, 0, 0);
</ins><span class="cx">
</span><del>- for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
- r[i] = codeBlock->constantRegisters[i];
-
</del><span class="cx"> if (codeBlock->needsFullScopeChain)
</span><span class="cx"> scopeChain = scopeChain->copy();
</span><span class="cx">
</span><span class="lines">@@ -3179,6 +3191,7 @@
</span><span class="cx"> int thisVal = (++vPC)->u.operand;
</span><span class="cx"> int firstArg = (++vPC)->u.operand;
</span><span class="cx"> int argCount = (++vPC)->u.operand;
</span><ins>+ ++vPC; // registerOffset
</ins><span class="cx">
</span><span class="cx"> JSValue* funcVal = r[func].jsValue(exec);
</span><span class="cx"> JSValue* baseVal = r[thisVal].jsValue(exec);
</span><span class="lines">@@ -3198,7 +3211,7 @@
</span><span class="cx"> // We didn't find the blessed version of eval, so reset vPC and process
</span><span class="cx"> // this instruction as a normal function call, supplying the proper 'this'
</span><span class="cx"> // value.
</span><del>- vPC -= 5;
</del><ins>+ vPC -= 6;
</ins><span class="cx"> r[thisVal] = baseVal->toThisObject(exec);
</span><span class="cx">
</span><span class="cx"> #if HAVE(COMPUTED_GOTO)
</span><span class="lines">@@ -3210,7 +3223,7 @@
</span><span class="cx"> // fall through to op_call
</span><span class="cx"> }
</span><span class="cx"> BEGIN_OPCODE(op_call) {
</span><del>- /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
</del><ins>+ /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n) registerOffset(n)
</ins><span class="cx">
</span><span class="cx"> Perform a function call. Specifically, call register func
</span><span class="cx"> with a "this" value of register thisVal, and put the result
</span><span class="lines">@@ -3251,31 +3264,32 @@
</span><span class="cx"> int thisVal = (++vPC)->u.operand;
</span><span class="cx"> int firstArg = (++vPC)->u.operand;
</span><span class="cx"> int argCount = (++vPC)->u.operand;
</span><ins>+ int registerOffset = (++vPC)->u.operand;
</ins><span class="cx">
</span><span class="cx"> JSValue* v = r[func].jsValue(exec);
</span><span class="cx">
</span><span class="cx"> CallData callData;
</span><span class="cx"> CallType callType = v->getCallData(callData);
</span><span class="cx">
</span><del>- if (*enabledProfilerReference)
- (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
-
- Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
- initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, v);
- exec->m_callFrame = callFrame;
-
</del><span class="cx"> if (callType == CallTypeJS) {
</span><del>-
</del><span class="cx"> ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
</span><span class="cx"> FunctionBodyNode* functionBodyNode = callData.js.functionBody;
</span><span class="cx"> CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
</span><span class="cx">
</span><span class="cx"> r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
</span><ins>+
+ Register* savedR = r;
</ins><span class="cx">
</span><del>- r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
</del><ins>+ r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, registerOffset, argCount, exceptionValue);
</ins><span class="cx"> if (UNLIKELY(exceptionValue != 0))
</span><span class="cx"> goto vm_throw;
</span><span class="cx">
</span><ins>+ initializeCallFrame(r, codeBlock, vPC, scopeChain, savedR, dst, argCount, v);
+ exec->m_callFrame = r;
+
+ if (*enabledProfilerReference)
+ (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
+
</ins><span class="cx"> codeBlock = newCodeBlock;
</span><span class="cx"> setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
</span><span class="cx"> vPC = codeBlock->instructions.begin();
</span><span class="lines">@@ -3283,7 +3297,7 @@
</span><span class="cx"> #if DUMP_OPCODE_STATS
</span><span class="cx"> OpcodeStats::resetLastInstruction();
</span><span class="cx"> #endif
</span><del>-
</del><ins>+
</ins><span class="cx"> NEXT_OPCODE;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -3291,10 +3305,16 @@
</span><span class="cx"> JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
</span><span class="cx"> ArgList args(r + firstArg + 1, argCount - 1);
</span><span class="cx">
</span><ins>+ initializeCallFrame(r + registerOffset, codeBlock, vPC, scopeChain, r, dst, argCount, v);
+ exec->m_callFrame = r + registerOffset;
+
+ if (*enabledProfilerReference)
+ (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
+
</ins><span class="cx"> MACHINE_SAMPLING_callingHostFunction();
</span><span class="cx">
</span><span class="cx"> JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
</span><del>- exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><ins>+ exec->m_callFrame = r;
</ins><span class="cx"> VM_CHECK_EXCEPTION();
</span><span class="cx">
</span><span class="cx"> r[dst] = returnValue;
</span><span class="lines">@@ -3309,7 +3329,6 @@
</span><span class="cx"> ASSERT(callType == CallTypeNone);
</span><span class="cx">
</span><span class="cx"> exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock);
</span><del>- exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><span class="cx"> goto vm_throw;
</span><span class="cx"> }
</span><span class="cx"> BEGIN_OPCODE(op_ret) {
</span><span class="lines">@@ -3324,44 +3343,47 @@
</span><span class="cx">
</span><span class="cx"> int result = (++vPC)->u.operand;
</span><span class="cx">
</span><del>- Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
- if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
</del><ins>+ if (JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
</ins><span class="cx"> ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
</span><span class="cx"> ASSERT(activation->isActivationObject());
</span><span class="cx"> activation->copyRegisters();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (*enabledProfilerReference)
</span><del>- (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
</del><ins>+ (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(r[RegisterFile::Callee].jsValue(exec)));
</ins><span class="cx">
</span><span class="cx"> if (codeBlock->needsFullScopeChain)
</span><span class="cx"> scopeChain->deref();
</span><span class="cx">
</span><span class="cx"> JSValue* returnValue = r[result].jsValue(exec);
</span><span class="cx">
</span><del>- codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
</del><ins>+ codeBlock = r[RegisterFile::CallerCodeBlock].codeBlock();
</ins><span class="cx"> if (!codeBlock)
</span><span class="cx"> return returnValue;
</span><span class="cx">
</span><del>- vPC = callFrame[RegisterFile::ReturnVPC].vPC();
- setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
- r = callFrame[RegisterFile::CallerRegisters].r();
- exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
- int dst = callFrame[RegisterFile::ReturnValueRegister].i();
</del><ins>+ vPC = r[RegisterFile::ReturnPC].vPC();
+ setScopeChain(exec, scopeChain, r[RegisterFile::CallerScopeChain].scopeChain());
+ int dst = r[RegisterFile::ReturnValueRegister].i();
+ r = r[RegisterFile::CallerRegisters].r();
+ exec->m_callFrame = r;
</ins><span class="cx"> r[dst] = returnValue;
</span><span class="cx">
</span><span class="cx"> NEXT_OPCODE;
</span><span class="cx"> }
</span><del>- BEGIN_OPCODE(op_initialise_locals) {
- for (Register* it = r - codeBlock->numVars + (codeBlock->codeType == EvalCode); it < r; ++it)
- (*it) = jsUndefined();
- for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
- r[i] = codeBlock->constantRegisters[i];
</del><ins>+ BEGIN_OPCODE(op_init) {
+ size_t i = 0;
+
+ for (size_t count = codeBlock->numVars; i < count; ++i)
+ r[i] = jsUndefined();
+
+ for (size_t count = codeBlock->constantRegisters.size(), j = 0; j < count; ++i, ++j)
+ r[i] = codeBlock->constantRegisters[j];
+
</ins><span class="cx"> ++vPC;
</span><span class="cx"> NEXT_OPCODE;
</span><span class="cx"> }
</span><span class="cx"> BEGIN_OPCODE(op_construct) {
</span><del>- /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n)
</del><ins>+ /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) registerOffset(n)
</ins><span class="cx">
</span><span class="cx"> Invoke register "constr" as a constructor. For JS
</span><span class="cx"> functions, the calling convention is exactly as for the
</span><span class="lines">@@ -3380,18 +3402,16 @@
</span><span class="cx"> int constrProto = (++vPC)->u.operand;
</span><span class="cx"> int firstArg = (++vPC)->u.operand;
</span><span class="cx"> int argCount = (++vPC)->u.operand;
</span><ins>+ int registerOffset = (++vPC)->u.operand;
</ins><span class="cx">
</span><del>- JSValue* constrVal = r[constr].jsValue(exec);
</del><ins>+ JSValue* v = r[constr].jsValue(exec);
</ins><span class="cx">
</span><span class="cx"> ConstructData constructData;
</span><del>- ConstructType constructType = constrVal->getConstructData(constructData);
</del><ins>+ ConstructType constructType = v->getConstructData(constructData);
</ins><span class="cx">
</span><del>- // Removing this line of code causes a measurable regression on squirrelfish.
- JSObject* constructor = static_cast<JSObject*>(constrVal);
-
</del><span class="cx"> if (constructType == ConstructTypeJS) {
</span><span class="cx"> if (*enabledProfilerReference)
</span><del>- (*enabledProfilerReference)->willExecute(exec, constructor);
</del><ins>+ (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
</ins><span class="cx">
</span><span class="cx"> StructureID* structure;
</span><span class="cx"> JSValue* prototype = r[constrProto].jsValue(exec);
</span><span class="lines">@@ -3407,36 +3427,48 @@
</span><span class="cx">
</span><span class="cx"> r[firstArg] = newObject; // "this" value
</span><span class="cx">
</span><del>- Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
- initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, constructor);
- exec->m_callFrame = callFrame;
</del><ins>+ Register* savedR = r;
</ins><span class="cx">
</span><del>- r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
- if (exceptionValue)
</del><ins>+ r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, registerOffset, argCount, exceptionValue);
+ if (UNLIKELY(exceptionValue != 0))
</ins><span class="cx"> goto vm_throw;
</span><span class="cx">
</span><ins>+ initializeCallFrame(r, codeBlock, vPC, scopeChain, savedR, dst, argCount, v);
+ exec->m_callFrame = r;
+
+ if (*enabledProfilerReference)
+ (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
+
</ins><span class="cx"> codeBlock = newCodeBlock;
</span><span class="cx"> setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
</span><span class="cx"> vPC = codeBlock->instructions.begin();
</span><span class="cx">
</span><ins>+#if DUMP_OPCODE_STATS
+ OpcodeStats::resetLastInstruction();
+#endif
+
</ins><span class="cx"> NEXT_OPCODE;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (constructType == ConstructTypeHost) {
</span><ins>+ ArgList args(r + firstArg + 1, argCount - 1);
+
+ initializeCallFrame(r + registerOffset, codeBlock, vPC, scopeChain, r, dst, argCount, v);
+ exec->m_callFrame = r + registerOffset;
+
</ins><span class="cx"> if (*enabledProfilerReference)
</span><del>- (*enabledProfilerReference)->willExecute(exec, constructor);
</del><ins>+ (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
</ins><span class="cx">
</span><del>- ArgList args(r + firstArg + 1, argCount - 1);
-
</del><span class="cx"> MACHINE_SAMPLING_callingHostFunction();
</span><span class="cx">
</span><del>- JSValue* returnValue = constructData.native.function(exec, constructor, args);
</del><ins>+ JSValue* returnValue = constructData.native.function(exec, static_cast<JSObject*>(v), args);
+ exec->m_callFrame = r;
</ins><span class="cx">
</span><span class="cx"> VM_CHECK_EXCEPTION();
</span><span class="cx"> r[dst] = returnValue;
</span><span class="cx">
</span><span class="cx"> if (*enabledProfilerReference)
</span><del>- (*enabledProfilerReference)->didExecute(exec, constructor);
</del><ins>+ (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
</ins><span class="cx">
</span><span class="cx"> ++vPC;
</span><span class="cx"> NEXT_OPCODE;
</span><span class="lines">@@ -3444,7 +3476,7 @@
</span><span class="cx">
</span><span class="cx"> ASSERT(constructType == ConstructTypeNone);
</span><span class="cx">
</span><del>- exceptionValue = createNotAConstructorError(exec, constrVal, vPC, codeBlock);
</del><ins>+ exceptionValue = createNotAConstructorError(exec, v, vPC, codeBlock);
</ins><span class="cx"> goto vm_throw;
</span><span class="cx"> }
</span><span class="cx"> BEGIN_OPCODE(op_construct_verify) {
</span><span class="lines">@@ -3776,8 +3808,7 @@
</span><span class="cx">
</span><span class="cx"> JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec));
</span><span class="cx"> if (!activation) {
</span><del>- CodeBlock* codeBlock = &function->m_body->generatedByteCode();
- activation = new (exec) JSActivation(exec, function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
</del><ins>+ activation = new (exec) JSActivation(exec, function->m_body, callFrame);
</ins><span class="cx"> callFrame[RegisterFile::OptionalCalleeActivation] = activation;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -3794,7 +3825,7 @@
</span><span class="cx"> if (!callerCodeBlock)
</span><span class="cx"> return jsNull();
</span><span class="cx">
</span><del>- Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><ins>+ Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].r();
</ins><span class="cx"> if (JSValue* caller = callerCallFrame[RegisterFile::Callee].jsValue(exec))
</span><span class="cx"> return caller;
</span><span class="cx">
</span><span class="lines">@@ -3815,7 +3846,7 @@
</span><span class="cx"> if (!callerCodeBlock)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- Instruction* vPC = callFrame[RegisterFile::ReturnVPC].vPC();
</del><ins>+ Instruction* vPC = vPCForPC(callerCodeBlock, callFrame[RegisterFile::ReturnPC].v());
</ins><span class="cx"> lineNumber = callerCodeBlock->lineNumberForVPC(vPC - 1);
</span><span class="cx"> sourceId = callerCodeBlock->ownerNode->sourceId();
</span><span class="cx"> sourceURL = callerCodeBlock->ownerNode->sourceURL();
</span><span class="lines">@@ -3846,17 +3877,26 @@
</span><span class="cx"> continue;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- callFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><ins>+ callFrame = callFrame[RegisterFile::CallerRegisters].r();
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
</del><ins>+void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, int& firstParameterIndex, Register*& argv, int& argc)
</ins><span class="cx"> {
</span><span class="cx"> function = static_cast<JSFunction*>(callFrame[RegisterFile::Callee].getJSValue());
</span><span class="cx"> ASSERT(function->inherits(&JSFunction::info));
</span><ins>+
+ CodeBlock* codeBlock = &function->m_body->generatedByteCode();
+ int numParameters = codeBlock->numParameters;
+ argc = callFrame[RegisterFile::ArgumentCount].i();
</ins><span class="cx">
</span><del>- argv = callFrame[RegisterFile::CallerRegisters].r() + callFrame[RegisterFile::ArgumentStartRegister].i() + 1; // + 1 to skip "this"
- argc = callFrame[RegisterFile::ArgumentCount].i() - 1; // - 1 to skip "this"
</del><ins>+ if (argc <= numParameters)
+ argv = callFrame - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ else
+ argv = callFrame - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this"
+
+ argc -= 1; // - 1 to skip "this"
+ firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #if ENABLE(CTI)
</span><span class="lines">@@ -4369,20 +4409,16 @@
</span><span class="cx"> RegisterFile* registerFile = ARG_registerFile;
</span><span class="cx"> Register* r = ARG_r;
</span><span class="cx">
</span><del>- JSValue* exceptionValue = 0;
</del><span class="cx"> Register* registerBase = registerFile->base();
</span><span class="cx">
</span><span class="cx"> JSValue* funcVal = ARG_src1;
</span><del>- JSValue* thisValue = ARG_src2;
- int firstArg = ARG_int3;
- int argCount = ARG_int4;
</del><ins>+ int registerOffset = ARG_int2;
+ int argCount = ARG_int3;
</ins><span class="cx">
</span><del>- // In the JIT code before entering this function we wil have checked the vptr,
- // and know this is an object of type JSFunction.
</del><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> CallData callData;
</span><ins>+ ASSERT(funcVal->getCallData(callData) == CallTypeJS);
</ins><span class="cx"> #endif
</span><del>- ASSERT(funcVal->getCallData(callData) == CallTypeJS);
</del><span class="cx">
</span><span class="cx"> if (*ARG_profilerReference)
</span><span class="cx"> (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
</span><span class="lines">@@ -4391,15 +4427,23 @@
</span><span class="cx"> FunctionBodyNode* functionBodyNode = static_cast<JSFunction*>(funcVal)->m_body.get();
</span><span class="cx">
</span><span class="cx"> CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
</span><ins>+
+ Register* savedR = r;
</ins><span class="cx">
</span><del>- r[firstArg] = thisValue;
</del><ins>+ JSValue* exceptionValue = 0;
+ r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, registerOffset, argCount, exceptionValue);
+ JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
</ins><span class="cx">
</span><del>- Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
- exec->m_callFrame = callFrame;
</del><ins>+ // RegisterFile::CallerCodeBlock is set by caller
+ r[RegisterFile::CallerScopeChain] = ARG_scopeChain;
+ r[RegisterFile::CallerRegisters] = savedR;
+ // RegisterFile::ReturnPC is set by callee
+ // RegisterFile::ReturnValueRegister is set by caller
+ r[RegisterFile::ArgumentCount] = argCount; // original argument count (for the sake of the "arguments" object)
+ r[RegisterFile::Callee] = funcVal;
+ r[RegisterFile::OptionalCalleeActivation] = nullJSValue;
</ins><span class="cx">
</span><del>- r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
- JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
-
</del><ins>+ exec->m_callFrame = r;
</ins><span class="cx"> exec->m_scopeChain = callDataScopeChain;
</span><span class="cx">
</span><span class="cx"> ARG_setScopeChain(callDataScopeChain);
</span><span class="lines">@@ -4433,12 +4477,8 @@
</span><span class="cx"> JSValue* Machine::cti_op_call_NotJSFunction(CTI_ARGS)
</span><span class="cx"> {
</span><span class="cx"> ExecState* exec = ARG_exec;
</span><del>- Register* r = ARG_r;
</del><span class="cx">
</span><span class="cx"> JSValue* funcVal = ARG_src1;
</span><del>- JSValue* thisValue = ARG_src2;
- int firstArg = ARG_int3;
- int argCount = ARG_int4;
</del><span class="cx">
</span><span class="cx"> CallData callData;
</span><span class="cx"> CallType callType = funcVal->getCallData(callData);
</span><span class="lines">@@ -4446,31 +4486,34 @@
</span><span class="cx"> ASSERT(callType != CallTypeJS);
</span><span class="cx">
</span><span class="cx"> if (callType == CallTypeHost) {
</span><del>- Register* oldCallFrame = exec->m_callFrame;
- Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
- exec->m_callFrame = callFrame;
</del><ins>+ int registerOffset = ARG_int2;
+ int argCount = ARG_int3;
+ Register* r = ARG_r + registerOffset;
+
+ initializeCallFrame(r, ARG_codeBlock, ARG_instr4, ARG_scopeChain, ARG_r, 0, argCount, funcVal);
+ exec->m_callFrame = r;
</ins><span class="cx">
</span><span class="cx"> if (*ARG_profilerReference)
</span><span class="cx"> (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
</span><span class="cx">
</span><del>- ArgList argList(r + firstArg + 1, argCount - 1);
</del><ins>+ Register* argv = r - RegisterFile::CallFrameHeaderSize - argCount;
+ ArgList argList(argv + 1, argCount - 1);
</ins><span class="cx">
</span><span class="cx"> CTI_MACHINE_SAMPLING_callingHostFunction();
</span><span class="cx">
</span><del>- JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(funcVal), thisValue, argList);
- exec->m_callFrame = oldCallFrame;
</del><ins>+ JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(funcVal), argv[0].jsValue(exec), argList);
</ins><span class="cx"> VM_CHECK_EXCEPTION(JSValue*);
</span><span class="cx">
</span><span class="cx"> if (*ARG_profilerReference)
</span><span class="cx"> (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(funcVal));
</span><span class="cx">
</span><ins>+ exec->m_callFrame = ARG_r;
</ins><span class="cx"> return returnValue;
</span><del>-
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ASSERT(callType == CallTypeNone);
</span><span class="cx">
</span><del>- exec->setException(createNotAFunctionError(exec, funcVal, ARG_instr5, ARG_codeBlock));
</del><ins>+ exec->setException(createNotAFunctionError(exec, funcVal, ARG_instr4, ARG_codeBlock));
</ins><span class="cx"> VM_CHECK_EXCEPTION_AT_END();
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="lines">@@ -4478,7 +4521,7 @@
</span><span class="cx"> void Machine::cti_op_ret_activation(CTI_ARGS)
</span><span class="cx"> {
</span><span class="cx"> ExecState* exec = ARG_exec;
</span><del>- Register* callFrame = ARG_r - ARG_codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><ins>+ Register* callFrame = ARG_r;
</ins><span class="cx">
</span><span class="cx"> JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec));
</span><span class="cx"> ASSERT(activation);
</span><span class="lines">@@ -4492,7 +4535,7 @@
</span><span class="cx"> {
</span><span class="cx"> ExecState* exec = ARG_exec;
</span><span class="cx">
</span><del>- Register* callFrame = ARG_r - ARG_codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
</del><ins>+ Register* callFrame = ARG_r;
</ins><span class="cx"> ASSERT(*ARG_profilerReference);
</span><span class="cx"> (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
</span><span class="cx"> }
</span><span class="lines">@@ -4543,27 +4586,22 @@
</span><span class="cx"> ExecState* exec = ARG_exec;
</span><span class="cx"> RegisterFile* registerFile = ARG_registerFile;
</span><span class="cx"> Register* r = ARG_r;
</span><del>- ScopeChainNode* scopeChain = ARG_scopeChain;
</del><span class="cx">
</span><del>- JSValue* exceptionValue = 0;
</del><span class="cx"> Register* registerBase = registerFile->base();
</span><span class="cx">
</span><span class="cx"> JSValue* constrVal = ARG_src1;
</span><span class="cx"> JSValue* constrProtoVal = ARG_src2;
</span><span class="cx"> int firstArg = ARG_int3;
</span><del>- int argCount = ARG_int4;
</del><ins>+ int registerOffset = ARG_int4;
+ int argCount = ARG_int5;
</ins><span class="cx">
</span><ins>+#ifndef NDEBUG
</ins><span class="cx"> ConstructData constructData;
</span><del>-#ifndef NDEBUG
- ConstructType constructType =
</del><ins>+ ASSERT(constrVal->getConstructData(constructData) == ConstructTypeJS);
</ins><span class="cx"> #endif
</span><del>- constrVal->getConstructData(constructData);
</del><span class="cx">
</span><del>- // Removing this line of code causes a measurable regression on sunspider.
- JSObject* constructor = static_cast<JSObject*>(constrVal);
</del><ins>+ JSFunction* constructor = static_cast<JSFunction*>(constrVal);
</ins><span class="cx">
</span><del>- ASSERT(constructType == ConstructTypeJS);
-
</del><span class="cx"> if (*ARG_profilerReference)
</span><span class="cx"> (*ARG_profilerReference)->willExecute(exec, constructor);
</span><span class="cx">
</span><span class="lines">@@ -4571,21 +4609,31 @@
</span><span class="cx"> if (constrProtoVal->isObject())
</span><span class="cx"> structure = static_cast<JSObject*>(constrProtoVal)->inheritorID();
</span><span class="cx"> else
</span><del>- structure = scopeChain->globalObject()->emptyObjectStructure();
</del><ins>+ structure = ARG_scopeChain->globalObject()->emptyObjectStructure();
</ins><span class="cx"> JSObject* newObject = new (exec) JSObject(structure);
</span><span class="cx">
</span><del>- ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
- FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
</del><ins>+ ScopeChainNode* callDataScopeChain = constructor->m_scopeChain.node();
+ FunctionBodyNode* functionBodyNode = constructor->m_body.get();
</ins><span class="cx"> CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
</span><span class="cx">
</span><span class="cx"> r[firstArg] = newObject; // "this" value
</span><span class="cx">
</span><del>- Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
- exec->m_callFrame = callFrame;
</del><ins>+ Register* savedR = r;
</ins><span class="cx">
</span><del>- r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
</del><ins>+ JSValue* exceptionValue = 0;
+ r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, registerOffset, argCount, exceptionValue);
</ins><span class="cx"> JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
</span><span class="cx">
</span><ins>+ // RegisterFile::CallerCodeBlock is set by caller
+ r[RegisterFile::CallerScopeChain] = ARG_scopeChain;
+ r[RegisterFile::CallerRegisters] = savedR;
+ // RegisterFile::ReturnPC is set by callee
+ // RegisterFile::ReturnValueRegister is set by caller
+ r[RegisterFile::ArgumentCount] = argCount; // original argument count (for the sake of the "arguments" object)
+ r[RegisterFile::Callee] = constructor;
+ r[RegisterFile::OptionalCalleeActivation] = nullJSValue;
+
+ exec->m_callFrame = r;
</ins><span class="cx"> exec->m_scopeChain = callDataScopeChain;
</span><span class="cx">
</span><span class="cx"> ARG_setScopeChain(callDataScopeChain);
</span><span class="lines">@@ -4601,21 +4649,14 @@
</span><span class="cx">
</span><span class="cx"> JSValue* constrVal = ARG_src1;
</span><span class="cx"> int firstArg = ARG_int3;
</span><del>- int argCount = ARG_int4;
</del><ins>+ int argCount = ARG_int5;
</ins><span class="cx">
</span><span class="cx"> ConstructData constructData;
</span><span class="cx"> ConstructType constructType = constrVal->getConstructData(constructData);
</span><span class="cx">
</span><del>- // Removing this line of code causes a measurable regression on squirrelfish.
</del><span class="cx"> JSObject* constructor = static_cast<JSObject*>(constrVal);
</span><span class="cx">
</span><del>- ASSERT(constructType != ConstructTypeJS);
-
</del><span class="cx"> if (constructType == ConstructTypeHost) {
</span><del>- Register* oldCallFrame = exec->m_callFrame;
- Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
- exec->m_callFrame = callFrame;
-
</del><span class="cx"> if (*ARG_profilerReference)
</span><span class="cx"> (*ARG_profilerReference)->willExecute(exec, constructor);
</span><span class="cx">
</span><span class="lines">@@ -4624,7 +4665,6 @@
</span><span class="cx"> CTI_MACHINE_SAMPLING_callingHostFunction();
</span><span class="cx">
</span><span class="cx"> JSValue* returnValue = constructData.native.function(exec, constructor, argList);
</span><del>- exec->m_callFrame = oldCallFrame;
</del><span class="cx"> VM_CHECK_EXCEPTION(JSValue*);
</span><span class="cx">
</span><span class="cx"> if (*ARG_profilerReference)
</span><span class="lines">@@ -4635,7 +4675,7 @@
</span><span class="cx">
</span><span class="cx"> ASSERT(constructType == ConstructTypeNone);
</span><span class="cx">
</span><del>- exec->setException(createNotAConstructorError(exec, constrVal, ARG_instr5, ARG_codeBlock));
</del><ins>+ exec->setException(createNotAConstructorError(exec, constrVal, ARG_instr6, ARG_codeBlock));
</ins><span class="cx"> VM_CHECK_EXCEPTION_AT_END();
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="lines">@@ -5193,16 +5233,16 @@
</span><span class="cx"> ScopeChainNode* scopeChain = ARG_scopeChain;
</span><span class="cx">
</span><span class="cx"> Machine* machine = exec->machine();
</span><del>- JSValue* exceptionValue = 0;
</del><span class="cx">
</span><span class="cx"> JSValue* funcVal = ARG_src1;
</span><del>- JSValue* baseVal = ARG_src2;
- int firstArg = ARG_int3;
- int argCount = ARG_int4;
</del><ins>+ int registerOffset = ARG_int2;
+ int argCount = ARG_int3;
+ JSValue* baseVal = ARG_src5;
</ins><span class="cx">
</span><span class="cx"> if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
</span><span class="cx"> JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
</span><del>- JSValue* result = machine->callEval(exec, codeBlock, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
</del><ins>+ JSValue* exceptionValue = 0;
+ JSValue* result = machine->callEval(exec, codeBlock, thisObject, scopeChain, registerFile, r, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argCount, exceptionValue);
</ins><span class="cx"> JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
</span><span class="cx"> return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMMachineh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/Machine.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/Machine.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/Machine.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -90,16 +90,13 @@
</span><span class="cx">
</span><span class="cx"> JSValue* execute(ProgramNode*, ExecState*, ScopeChainNode*, JSObject* thisObj, JSValue** exception);
</span><span class="cx"> JSValue* execute(FunctionBodyNode*, ExecState*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue** exception);
</span><del>- JSValue* execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception)
- {
- return execute(evalNode, exec, thisObj, m_registerFile.size(), scopeChain, exception);
- }
</del><ins>+ JSValue* execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception);
</ins><span class="cx">
</span><span class="cx"> JSValue* retrieveArguments(ExecState*, JSFunction*) const;
</span><span class="cx"> JSValue* retrieveCaller(ExecState*, InternalFunction*) const;
</span><span class="cx"> void retrieveLastCaller(ExecState* exec, int& lineNumber, int& sourceId, UString& sourceURL, JSValue*& function) const;
</span><span class="cx">
</span><del>- void getArgumentsData(Register* callFrame, JSFunction*&, Register*& argv, int& argc);
</del><ins>+ void getArgumentsData(Register* callFrame, JSFunction*&, int& firstParameterIndex, Register*& argv, int& argc);
</ins><span class="cx"> void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
</span><span class="cx">
</span><span class="cx"> void startTimeoutCheck()
</span><span class="lines">@@ -239,7 +236,7 @@
</span><span class="cx"> NEVER_INLINE JSValue* callEval(ExecState* exec, CodeBlock* callingCodeBlock, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile*, Register* r, int argv, int argc, JSValue*& exceptionValue);
</span><span class="cx"> JSValue* execute(EvalNode*, ExecState*, JSObject* thisObj, int registerOffset, ScopeChainNode*, JSValue** exception);
</span><span class="cx">
</span><del>- ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock*, Instruction*, ScopeChainNode*, Register* r, int returnValueRegister, int argv, int argc, JSValue* function);
</del><ins>+ ALWAYS_INLINE static void initializeCallFrame(Register* callFrame, CodeBlock*, Instruction*, ScopeChainNode*, Register* r, int returnValueRegister, int argc, JSValue* function);
</ins><span class="cx">
</span><span class="cx"> ALWAYS_INLINE void setScopeChain(ExecState* exec, ScopeChainNode*&, ScopeChainNode*);
</span><span class="cx"> NEVER_INLINE void debug(ExecState*, const CodeBlock*, ScopeChainNode*, Register*, DebugHookID, int firstLine, int lastLine);
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMOpcodeh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/Opcode.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/Opcode.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/Opcode.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx"> #define DUMP_OPCODE_STATS 0
</span><span class="cx">
</span><span class="cx"> #define FOR_EACH_OPCODE_ID(macro) \
</span><del>- macro(op_initialise_locals) \
</del><ins>+ macro(op_init) \
</ins><span class="cx"> macro(op_unexpected_load) \
</span><span class="cx"> macro(op_new_object) \
</span><span class="cx"> macro(op_new_array) \
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMRegisterFileh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/RegisterFile.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/RegisterFile.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/RegisterFile.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -90,20 +90,19 @@
</span><span class="cx"> class RegisterFile : Noncopyable {
</span><span class="cx"> public:
</span><span class="cx"> enum CallFrameHeaderEntry {
</span><del>- CallerCodeBlock = 0,
- ReturnVPC,
- CallerScopeChain,
- CallerRegisters,
- ReturnValueRegister,
- ArgumentStartRegister,
- ArgumentCount,
- Callee,
- OptionalCalleeActivation,
- CTIReturnEIP,
- CallFrameHeaderSize
</del><ins>+ CallFrameHeaderSize = 8,
+
+ CallerCodeBlock = -8,
+ CallerScopeChain = -7,
+ CallerRegisters = -6,
+ ReturnPC = -5,
+ ReturnValueRegister = -4,
+ ArgumentCount = -3,
+ Callee = -2,
+ OptionalCalleeActivation = -1,
</ins><span class="cx"> };
</span><span class="cx">
</span><del>- enum { ProgramCodeThisRegister = - 1 };
</del><ins>+ enum { ProgramCodeThisRegister = -CallFrameHeaderSize - 1 };
</ins><span class="cx">
</span><span class="cx"> enum { DefaultCapacity = 2 * 1024 * 1024 / sizeof(Register) };
</span><span class="cx"> enum { DefaultMaxGlobals = 8 * 1024 };
</span></span></pre></div>
<a id="trunkJavaScriptCoreVMRegisterIDh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/VM/RegisterID.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/VM/RegisterID.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/VM/RegisterID.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> public:
</span><span class="cx"> RegisterID()
</span><span class="cx"> : m_refCount(0)
</span><del>- , m_isConstant(false)
</del><ins>+ , m_isTemporary(false)
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> , m_didSetIndex(false)
</span><span class="cx"> #endif
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx"> explicit RegisterID(int index)
</span><span class="cx"> : m_refCount(0)
</span><span class="cx"> , m_index(index)
</span><del>- , m_isConstant(false)
</del><ins>+ , m_isTemporary(false)
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> , m_didSetIndex(true)
</span><span class="cx"> #endif
</span><span class="lines">@@ -65,9 +65,9 @@
</span><span class="cx"> m_index = index;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void makeConstant()
</del><ins>+ void setTemporary()
</ins><span class="cx"> {
</span><del>- m_isConstant = true;
</del><ins>+ m_isTemporary = true;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> int index() const
</span><span class="lines">@@ -78,7 +78,7 @@
</span><span class="cx">
</span><span class="cx"> bool isTemporary()
</span><span class="cx"> {
</span><del>- return m_index >= 0 && !m_isConstant;
</del><ins>+ return m_isTemporary;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void ref()
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx">
</span><span class="cx"> int m_refCount;
</span><span class="cx"> int m_index;
</span><del>- bool m_isConstant;
</del><ins>+ bool m_isTemporary;
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> bool m_didSetIndex;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/Arguments.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/Arguments.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/Arguments.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -38,10 +38,10 @@
</span><span class="cx"> const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
</span><span class="cx">
</span><span class="cx"> struct ArgumentsData : Noncopyable {
</span><del>- ArgumentsData(JSActivation* activation, unsigned numParameters, unsigned firstArgumentIndex, unsigned numArguments, JSFunction* callee)
</del><ins>+ ArgumentsData(JSActivation* activation, unsigned numParameters, int firstParameterIndex, unsigned numArguments, JSFunction* callee)
</ins><span class="cx"> : activation(activation)
</span><span class="cx"> , numParameters(numParameters)
</span><del>- , firstArgumentIndex(firstArgumentIndex)
</del><ins>+ , firstParameterIndex(firstParameterIndex)
</ins><span class="cx"> , numArguments(numArguments)
</span><span class="cx"> , extraArguments(0)
</span><span class="cx"> , callee(callee)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> JSActivation* activation;
</span><span class="cx">
</span><span class="cx"> unsigned numParameters;
</span><del>- unsigned firstArgumentIndex;
</del><ins>+ int firstParameterIndex;
</ins><span class="cx"> unsigned numArguments;
</span><span class="cx"> Register* extraArguments;
</span><span class="cx"> OwnArrayPtr<bool> deletedArguments;
</span><span class="lines">@@ -65,9 +65,9 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> // ECMA 10.1.8
</span><del>-Arguments::Arguments(ExecState* exec, JSFunction* function, JSActivation* activation, int firstArgumentIndex, Register* argv, int argc)
</del><ins>+Arguments::Arguments(ExecState* exec, JSFunction* function, JSActivation* activation, int firstParameterIndex, Register* argv, int argc)
</ins><span class="cx"> : JSObject(exec->lexicalGlobalObject()->argumentsStructure())
</span><del>- , d(new ArgumentsData(activation, function->numParameters(), firstArgumentIndex, argc, function))
</del><ins>+ , d(new ArgumentsData(activation, function->numParameters(), firstParameterIndex, argc, function))
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(activation);
</span><span class="cx">
</span><span class="lines">@@ -118,14 +118,14 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (d->numParameters == d->numArguments) {
</span><del>- args.initialize(&d->activation->registerAt(d->firstArgumentIndex), d->numArguments);
</del><ins>+ args.initialize(&d->activation->registerAt(d->firstParameterIndex), d->numArguments);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> unsigned parametersLength = min(d->numParameters, d->numArguments);
</span><span class="cx"> unsigned i = 0;
</span><span class="cx"> for (; i < parametersLength; ++i)
</span><del>- args.append(d->activation->uncheckedSymbolTableGetValue(d->firstArgumentIndex + i));
</del><ins>+ args.append(d->activation->uncheckedSymbolTableGetValue(d->firstParameterIndex + i));
</ins><span class="cx"> for (; i < d->numArguments; ++i)
</span><span class="cx"> args.append(d->extraArguments[i - d->numParameters].getJSValue());
</span><span class="cx"> return;
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx"> unsigned i = 0;
</span><span class="cx"> for (; i < parametersLength; ++i) {
</span><span class="cx"> if (!d->deletedArguments[i])
</span><del>- args.append(d->activation->uncheckedSymbolTableGetValue(d->firstArgumentIndex + i));
</del><ins>+ args.append(d->activation->uncheckedSymbolTableGetValue(d->firstParameterIndex + i));
</ins><span class="cx"> else
</span><span class="cx"> args.append(get(exec, i));
</span><span class="cx"> }
</span><span class="lines">@@ -151,7 +151,7 @@
</span><span class="cx"> {
</span><span class="cx"> if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
</span><span class="cx"> if (i < d->numParameters)
</span><del>- d->activation->uncheckedSymbolTableGet(d->firstArgumentIndex + i, slot);
</del><ins>+ d->activation->uncheckedSymbolTableGet(d->firstParameterIndex + i, slot);
</ins><span class="cx"> else
</span><span class="cx"> slot.setValue(d->extraArguments[i - d->numParameters].getJSValue());
</span><span class="cx"> return true;
</span><span class="lines">@@ -166,7 +166,7 @@
</span><span class="cx"> unsigned i = propertyName.toArrayIndex(&isArrayIndex);
</span><span class="cx"> if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
</span><span class="cx"> if (i < d->numParameters)
</span><del>- d->activation->uncheckedSymbolTableGet(d->firstArgumentIndex + i, slot);
</del><ins>+ d->activation->uncheckedSymbolTableGet(d->firstParameterIndex + i, slot);
</ins><span class="cx"> else
</span><span class="cx"> slot.setValue(d->extraArguments[i - d->numParameters].getJSValue());
</span><span class="cx"> return true;
</span><span class="lines">@@ -189,7 +189,7 @@
</span><span class="cx"> {
</span><span class="cx"> if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
</span><span class="cx"> if (i < d->numParameters)
</span><del>- d->activation->uncheckedSymbolTablePut(d->firstArgumentIndex + i, value);
</del><ins>+ d->activation->uncheckedSymbolTablePut(d->firstParameterIndex + i, value);
</ins><span class="cx"> else
</span><span class="cx"> d->extraArguments[i - d->numParameters] = value;
</span><span class="cx"> return;
</span><span class="lines">@@ -204,7 +204,7 @@
</span><span class="cx"> unsigned i = propertyName.toArrayIndex(&isArrayIndex);
</span><span class="cx"> if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
</span><span class="cx"> if (i < d->numParameters)
</span><del>- d->activation->uncheckedSymbolTablePut(d->firstArgumentIndex + i, value);
</del><ins>+ d->activation->uncheckedSymbolTablePut(d->firstParameterIndex + i, value);
</ins><span class="cx"> else
</span><span class="cx"> d->extraArguments[i - d->numParameters] = value;
</span><span class="cx"> return;
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsDebuggerCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/DebuggerCallFrame.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/DebuggerCallFrame.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/DebuggerCallFrame.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -36,17 +36,12 @@
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><del>-Register* DebuggerCallFrame::callFrame() const
-{
- return m_registers - m_codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
-}
-
</del><span class="cx"> const UString* DebuggerCallFrame::functionName() const
</span><span class="cx"> {
</span><span class="cx"> if (!m_codeBlock)
</span><span class="cx"> return 0;
</span><span class="cx">
</span><del>- JSFunction* function = static_cast<JSFunction*>(callFrame()[RegisterFile::Callee].getJSValue());
</del><ins>+ JSFunction* function = static_cast<JSFunction*>(m_registers[RegisterFile::Callee].getJSValue());
</ins><span class="cx"> if (!function)
</span><span class="cx"> return 0;
</span><span class="cx"> return &function->name(m_exec);
</span><span class="lines">@@ -54,7 +49,7 @@
</span><span class="cx">
</span><span class="cx"> DebuggerCallFrame::Type DebuggerCallFrame::type() const
</span><span class="cx"> {
</span><del>- if (callFrame()[RegisterFile::Callee].getJSValue())
</del><ins>+ if (m_registers[RegisterFile::Callee].getJSValue())
</ins><span class="cx"> return FunctionType;
</span><span class="cx">
</span><span class="cx"> return ProgramType;
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsDebuggerCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/DebuggerCallFrame.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/DebuggerCallFrame.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/DebuggerCallFrame.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -67,8 +67,6 @@
</span><span class="cx"> JSValue* exception() const { return m_exception; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- Register* callFrame() const;
-
</del><span class="cx"> ExecState* m_exec;
</span><span class="cx"> JSGlobalObject* m_dynamicGlobalObject;
</span><span class="cx"> const CodeBlock* m_codeBlock;
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSActivationcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSActivation.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSActivation.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSActivation.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -51,13 +51,57 @@
</span><span class="cx"> delete d();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void JSActivation::mark()
+{
+ Base::mark();
+
+ if (d()->argumentsObject)
+ d()->argumentsObject->mark();
+
+ Register* registerArray = d()->registerArray.get();
+ if (!registerArray)
+ return;
+
+ size_t numParametersMinusThis = d()->functionBody->generatedByteCode().numParameters - 1;
+
+ size_t i = 0;
+ size_t count = numParametersMinusThis;
+ for ( ; i < count; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+
+ size_t numVars = d()->functionBody->generatedByteCode().numVars;
+
+ // Skip the call frame, which sits between the parameters and vars.
+ i += RegisterFile::CallFrameHeaderSize;
+ count += RegisterFile::CallFrameHeaderSize + numVars;
+
+ for ( ; i < count; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+}
+
</ins><span class="cx"> void JSActivation::copyRegisters()
</span><span class="cx"> {
</span><del>- int numLocals = d()->functionBody->generatedByteCode().numLocals;
</del><ins>+ ASSERT(!d()->registerArray);
+ ASSERT(!d()->registerArraySize);
+
+ size_t numParametersMinusThis = d()->functionBody->generatedByteCode().numParameters - 1;
+ size_t numVars = d()->functionBody->generatedByteCode().numVars;
+ size_t numLocals = numVars + numParametersMinusThis;
+
</ins><span class="cx"> if (!numLocals)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- copyRegisterArray(d()->registers - numLocals, numLocals);
</del><ins>+ int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
+ size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
+
+ Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
+ setRegisters(registerArray + registerOffset, registerArray, registerArraySize);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
</span><span class="lines">@@ -126,14 +170,6 @@
</span><span class="cx"> return exec->globalThisValue();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JSActivation::mark()
-{
- Base::mark();
-
- if (d()->argumentsObject)
- d()->argumentsObject->mark();
-}
-
</del><span class="cx"> bool JSActivation::isActivationObject() const
</span><span class="cx"> {
</span><span class="cx"> return true;
</span><span class="lines">@@ -163,15 +199,13 @@
</span><span class="cx">
</span><span class="cx"> Arguments* JSActivation::createArgumentsObject(ExecState* exec)
</span><span class="cx"> {
</span><del>- Register* callFrame = d()->registers - d()->functionBody->generatedByteCode().numLocals - RegisterFile::CallFrameHeaderSize;
-
</del><span class="cx"> JSFunction* function;
</span><span class="cx"> Register* argv;
</span><span class="cx"> int argc;
</span><del>- exec->machine()->getArgumentsData(callFrame, function, argv, argc);
</del><ins>+ int firstParameterIndex;
+ exec->machine()->getArgumentsData(d()->registers, function, firstParameterIndex, argv, argc);
</ins><span class="cx">
</span><del>- int firstArgumentIndex = -d()->functionBody->generatedByteCode().numLocals + 1;
- return new (exec) Arguments(exec, function, this, firstArgumentIndex, argv, argc);
</del><ins>+ return new (exec) Arguments(exec, function, this, firstParameterIndex, argv, argc);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSActivationh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSActivation.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSActivation.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSActivation.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -44,6 +44,8 @@
</span><span class="cx"> JSActivation(ExecState* exec, PassRefPtr<FunctionBodyNode>, Register*);
</span><span class="cx"> virtual ~JSActivation();
</span><span class="cx">
</span><ins>+ virtual void mark();
+
</ins><span class="cx"> virtual bool isActivationObject() const;
</span><span class="cx"> virtual bool isDynamicScope() const;
</span><span class="cx">
</span><span class="lines">@@ -71,8 +73,6 @@
</span><span class="cx">
</span><span class="cx"> virtual JSObject* toThisObject(ExecState*) const;
</span><span class="cx">
</span><del>- virtual void mark();
-
</del><span class="cx"> void copyRegisters();
</span><span class="cx">
</span><span class="cx"> virtual const ClassInfo* classInfo() const { return &info; }
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSGlobalObject.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSGlobalObject.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSGlobalObject.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -202,7 +202,7 @@
</span><span class="cx">
</span><span class="cx"> ASSERT(!hasCustomProperties());
</span><span class="cx"> symbolTable().clear();
</span><del>- setRegisterArray(0, 0);
</del><ins>+ setRegisters(0, 0, 0);
</ins><span class="cx">
</span><span class="cx"> ExecState* exec = d()->globalExec.get();
</span><span class="cx">
</span><span class="lines">@@ -396,6 +396,17 @@
</span><span class="cx">
</span><span class="cx"> // No need to mark the other structures, because their prototypes are all
</span><span class="cx"> // guaranteed to be referenced elsewhere.
</span><ins>+
+ Register* registerArray = d()->registerArray.get();
+ if (!registerArray)
+ return;
+
+ size_t size = d()->registerArraySize;
+ for (size_t i = 0; i < size; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSGlobalObject* JSGlobalObject::toGlobalObject(ExecState*) const
</span><span class="lines">@@ -423,7 +434,9 @@
</span><span class="cx"> d()->registers = 0;
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>- copyRegisterArray(registerFile.lastGlobal(), numGlobals);
</del><ins>+
+ Register* registerArray = copyRegisterArray(registerFile.lastGlobal(), numGlobals);
+ setRegisters(registerArray + numGlobals, registerArray, numGlobals);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
</span><span class="lines">@@ -437,10 +450,8 @@
</span><span class="cx">
</span><span class="cx"> if (d()->registerArray) {
</span><span class="cx"> memcpy(registerFile.base() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(Register));
</span><del>- setRegisterArray(0, 0);
</del><ins>+ setRegisters(registerFile.base(), 0, 0);
</ins><span class="cx"> }
</span><del>-
- d()->registers = registerFile.base();
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSGlobalObject.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSGlobalObject.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSGlobalObject.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -156,6 +156,8 @@
</span><span class="cx"> public:
</span><span class="cx"> virtual ~JSGlobalObject();
</span><span class="cx">
</span><ins>+ virtual void mark();
+
</ins><span class="cx"> virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
</span><span class="cx"> virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
</span><span class="cx"> virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&);
</span><span class="lines">@@ -224,8 +226,6 @@
</span><span class="cx">
</span><span class="cx"> ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
</span><span class="cx">
</span><del>- virtual void mark();
-
</del><span class="cx"> virtual bool isGlobalObject() const { return true; }
</span><span class="cx"> virtual JSGlobalObject* toGlobalObject(ExecState*) const;
</span><span class="cx">
</span><span class="lines">@@ -274,13 +274,14 @@
</span><span class="cx">
</span><span class="cx"> inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
</span><span class="cx"> {
</span><del>- size_t registerArraySize = d()->registerArraySize;
- Register* registerArray = new Register[registerArraySize + count];
</del><ins>+ size_t oldSize = d()->registerArraySize;
+ size_t newSize = oldSize + count;
+ Register* registerArray = new Register[newSize];
</ins><span class="cx"> if (d()->registerArray)
</span><del>- memcpy(registerArray + count, d()->registerArray.get(), registerArraySize * sizeof(Register));
- setRegisterArray(registerArray, registerArraySize + count);
</del><ins>+ memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
+ setRegisters(registerArray + newSize, registerArray, newSize);
</ins><span class="cx">
</span><del>- for (int i = 0, index = -static_cast<int>(registerArraySize) - 1; i < count; ++i, --index) {
</del><ins>+ for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
</ins><span class="cx"> GlobalPropertyInfo& global = globals[i];
</span><span class="cx"> ASSERT(global.attributes & DontDelete);
</span><span class="cx"> SymbolTableEntry newEntry(index, global.attributes);
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSStaticScopeObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSStaticScopeObject.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSStaticScopeObject.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSStaticScopeObject.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -31,6 +31,14 @@
</span><span class="cx">
</span><span class="cx"> ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
</span><span class="cx">
</span><ins>+void JSStaticScopeObject::mark()
+{
+ JSVariableObject::mark();
+
+ if (!d()->registerStore.marked())
+ d()->registerStore.mark();
+}
+
</ins><span class="cx"> JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
</span><span class="cx"> {
</span><span class="cx"> return exec->globalThisValue();
</span><span class="lines">@@ -59,8 +67,8 @@
</span><span class="cx">
</span><span class="cx"> JSStaticScopeObject::~JSStaticScopeObject()
</span><span class="cx"> {
</span><del>- ASSERT(d);
- delete static_cast<JSStaticScopeObjectData*>(d);
</del><ins>+ ASSERT(d());
+ delete d();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSStaticScopeObjecth"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSStaticScopeObject.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSStaticScopeObject.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSStaticScopeObject.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -47,17 +47,20 @@
</span><span class="cx"> JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue* value, unsigned attributes)
</span><span class="cx"> : JSVariableObject(exec->globalData().nullProtoStructureID, new JSStaticScopeObjectData())
</span><span class="cx"> {
</span><del>- JSStaticScopeObjectData* data = static_cast<JSStaticScopeObjectData*>(d);
- data->registerStore = value;
</del><ins>+ d()->registerStore = value;
</ins><span class="cx"> symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes));
</span><span class="cx"> }
</span><span class="cx"> virtual ~JSStaticScopeObject();
</span><ins>+ virtual void mark();
</ins><span class="cx"> bool isDynamicScope() const;
</span><span class="cx"> virtual JSObject* toThisObject(ExecState*) const;
</span><span class="cx"> virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
</span><span class="cx"> virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
</span><span class="cx"> virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&);
</span><span class="cx"> void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes);
</span><ins>+
+ private:
+ JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSVariableObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSVariableObject.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSVariableObject.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSVariableObject.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -63,40 +63,25 @@
</span><span class="cx"> return JSObject::getPropertyAttributes(exec, propertyName, attributes);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JSVariableObject::mark()
-{
- JSObject::mark();
-
- if (!d->registerArray)
- return;
-
- Register* end = d->registerArray.get() + d->registerArraySize;
- for (Register* it = d->registerArray.get(); it != end; ++it)
- if (!(*it).marked())
- (*it).mark();
-}
-
</del><span class="cx"> bool JSVariableObject::isVariableObject() const
</span><span class="cx"> {
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JSVariableObject::copyRegisterArray(Register* src, size_t count)
</del><ins>+Register* JSVariableObject::copyRegisterArray(Register* src, size_t count)
</ins><span class="cx"> {
</span><del>- ASSERT(!d->registerArray);
-
</del><span class="cx"> Register* registerArray = new Register[count];
</span><span class="cx"> memcpy(registerArray, src, count * sizeof(Register));
</span><span class="cx">
</span><del>- setRegisterArray(registerArray, count);
</del><ins>+ return registerArray;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void JSVariableObject::setRegisterArray(Register* registerArray, size_t count)
</del><ins>+void JSVariableObject::setRegisters(Register* r, Register* registerArray, size_t count)
</ins><span class="cx"> {
</span><span class="cx"> if (registerArray != d->registerArray.get())
</span><span class="cx"> d->registerArray.set(registerArray);
</span><span class="cx"> d->registerArraySize = count;
</span><del>- d->registers = registerArray + count;
</del><ins>+ d->registers = r;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsJSVariableObjecth"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/JSVariableObject.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/JSVariableObject.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/JSVariableObject.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -48,7 +48,6 @@
</span><span class="cx">
</span><span class="cx"> virtual bool deleteProperty(ExecState*, const Identifier&);
</span><span class="cx"> virtual void getPropertyNames(ExecState*, PropertyNameArray&);
</span><del>- virtual void mark();
</del><span class="cx">
</span><span class="cx"> virtual bool isVariableObject() const;
</span><span class="cx"> virtual bool isDynamicScope() const = 0;
</span><span class="lines">@@ -71,7 +70,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
</span><del>- Register* registers; // Pointers to the register past the end of local storage. (Local storage indexes are negative.)
</del><ins>+ Register* registers; // "r" in the register file.
</ins><span class="cx"> OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
</span><span class="cx"> size_t registerArraySize;
</span><span class="cx">
</span><span class="lines">@@ -91,8 +90,8 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void copyRegisterArray(Register* src, size_t count);
- void setRegisterArray(Register* registerArray, size_t count);
</del><ins>+ Register* copyRegisterArray(Register* src, size_t count);
+ void setRegisters(Register* r, Register* registerArray, size_t count);
</ins><span class="cx">
</span><span class="cx"> bool symbolTableGet(const Identifier&, PropertySlot&);
</span><span class="cx"> bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsSymbolTableh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/SymbolTable.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/SymbolTable.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/SymbolTable.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -38,83 +38,84 @@
</span><span class="cx"> static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); }
</span><span class="cx">
</span><span class="cx"> // The bit twiddling in this class assumes that every register index is a
</span><del>- // reasonably small negative number, and therefore has its high two bits set.
</del><ins>+ // reasonably small positive or negative number, and therefore has its high
+ // four bits all set or all unset.
</ins><span class="cx">
</span><span class="cx"> struct SymbolTableEntry {
</span><span class="cx"> SymbolTableEntry()
</span><del>- : rawValue(0)
</del><ins>+ : m_bits(0)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> SymbolTableEntry(int index)
</span><span class="cx"> {
</span><del>- ASSERT(index & 0x80000000);
- ASSERT(index & 0x40000000);
</del><ins>+ ASSERT(isValidIndex(index));
+ pack(index, false, false);
+ }
</ins><span class="cx">
</span><del>- rawValue = index & ~0x80000000 & ~0x40000000;
- }
-
</del><span class="cx"> SymbolTableEntry(int index, unsigned attributes)
</span><span class="cx"> {
</span><del>- ASSERT(index & 0x80000000);
- ASSERT(index & 0x40000000);
-
- rawValue = index;
-
- if (!(attributes & ReadOnly))
- rawValue &= ~0x80000000;
-
- if (!(attributes & DontEnum))
- rawValue &= ~0x40000000;
</del><ins>+ ASSERT(isValidIndex(index));
+ pack(index, attributes & ReadOnly, attributes & DontEnum);
</ins><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> bool isNull() const
</span><span class="cx"> {
</span><del>- return !rawValue;
</del><ins>+ return !m_bits;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> int getIndex() const
</span><span class="cx"> {
</span><del>- ASSERT(!isNull());
- return rawValue | 0x80000000 | 0x40000000;
</del><ins>+ return m_bits >> FlagBits;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> unsigned getAttributes() const
</span><span class="cx"> {
</span><span class="cx"> unsigned attributes = 0;
</span><del>-
- if (rawValue & 0x80000000)
</del><ins>+ if (m_bits & ReadOnlyFlag)
</ins><span class="cx"> attributes |= ReadOnly;
</span><del>-
- if (rawValue & 0x40000000)
</del><ins>+ if (m_bits & DontEnumFlag)
</ins><span class="cx"> attributes |= DontEnum;
</span><del>-
</del><span class="cx"> return attributes;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void setAttributes(unsigned attributes)
</span><span class="cx"> {
</span><del>- rawValue = getIndex();
-
- if (!(attributes & ReadOnly))
- rawValue &= ~0x80000000;
-
- if (!(attributes & DontEnum))
- rawValue &= ~0x40000000;
</del><ins>+ pack(getIndex(), attributes & ReadOnly, attributes & DontEnum);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool isReadOnly() const
</span><span class="cx"> {
</span><del>- return rawValue & 0x80000000;
</del><ins>+ return m_bits & ReadOnlyFlag;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- int rawValue;
</del><ins>+ private:
+ static const unsigned ReadOnlyFlag = 0x1;
+ static const unsigned DontEnumFlag = 0x2;
+ static const unsigned NotNullFlag = 0x4;
+ static const unsigned FlagBits = 3;
+
+ void pack(int index, bool readOnly, bool dontEnum)
+ {
+ m_bits = (index << FlagBits) | NotNullFlag;
+ if (readOnly)
+ m_bits |= ReadOnlyFlag;
+ if (dontEnum)
+ m_bits |= DontEnumFlag;
+ }
+
+ bool isValidIndex(int index)
+ {
+ return ((index << FlagBits) >> FlagBits) == index;
+ }
+
+ int m_bits;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> struct SymbolTableIndexHashTraits {
</span><span class="cx"> typedef SymbolTableEntry TraitType;
</span><span class="cx"> static SymbolTableEntry emptyValue() { return SymbolTableEntry(); }
</span><del>- static const bool emptyValueIsZero = false;
</del><ins>+ static const bool emptyValueIsZero = true;
</ins><span class="cx"> static const bool needsDestruction = false;
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsnodescpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/nodes.cpp (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/nodes.cpp 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/kjs/nodes.cpp 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -286,7 +286,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocal(m_ident)) {
</del><ins>+ if (RegisterID* local = generator.registerFor(m_ident)) {
</ins><span class="cx"> if (dst == ignoredResult())
</span><span class="cx"> return 0;
</span><span class="cx"> return generator.moveToDestinationIfNeeded(dst, local);
</span><span class="lines">@@ -404,43 +404,43 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
- return generator.emitConstruct(generator.finalDestination(dst, r0.get()), r0.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
+ return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> base = generator.tempDestination(dst);
</span><del>- RegisterID* func = generator.newTemporary();
- generator.emitResolveWithBase(base.get(), func, generator.propertyNames().eval);
- return generator.emitCallEval(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ RefPtr<RegisterID> func = generator.newTemporary();
+ generator.emitResolveWithBase(base.get(), func.get(), generator.propertyNames().eval);
+ return generator.emitCallEval(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- RegisterID* func = generator.emitNode(m_expr.get());
- return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
+ return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocal(m_ident))
- return generator.emitCall(generator.finalDestination(dst), local, 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ if (RefPtr<RegisterID> local = generator.registerFor(m_ident))
+ return generator.emitCall(generator.finalDestination(dst), local.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx">
</span><span class="cx"> int index = 0;
</span><span class="cx"> size_t depth = 0;
</span><span class="cx"> JSValue* globalObject = 0;
</span><span class="cx"> if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
</span><del>- RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
- return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+ return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> base = generator.tempDestination(dst);
</span><del>- RegisterID* func = generator.newTemporary();
</del><ins>+ RefPtr<RegisterID> func = generator.newTemporary();
</ins><span class="cx"> int identifierStart = m_divot - m_startOffset;
</span><span class="cx"> generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
</span><del>- generator.emitResolveFunction(base.get(), func, m_ident);
- return generator.emitCall(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ generator.emitResolveFunction(base.get(), func.get(), m_ident);
+ return generator.emitCall(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="lines">@@ -448,16 +448,16 @@
</span><span class="cx"> RefPtr<RegisterID> base = generator.emitNode(m_base.get());
</span><span class="cx"> RegisterID* property = generator.emitNode(m_subscript.get());
</span><span class="cx"> generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
</span><del>- RegisterID* function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
- return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ RefPtr<RegisterID> function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
+ return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> base = generator.emitNode(m_base.get());
</span><span class="cx"> generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
</span><del>- RegisterID* function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
- return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</del><ins>+ RefPtr<RegisterID> function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
+ return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ PostfixResolveNode ----------------------------------
</span><span class="lines">@@ -474,7 +474,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocal(m_ident)) {
</del><ins>+ if (RegisterID* local = generator.registerFor(m_ident)) {
</ins><span class="cx"> if (generator.isLocalConstant(m_ident)) {
</span><span class="cx"> if (dst == ignoredResult())
</span><span class="cx"> return 0;
</span><span class="lines">@@ -574,7 +574,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (generator.registerForLocal(m_ident))
</del><ins>+ if (generator.registerFor(m_ident))
</ins><span class="cx"> return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
</span><span class="cx">
</span><span class="cx"> generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
</span><span class="lines">@@ -629,7 +629,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocal(m_ident)) {
</del><ins>+ if (RegisterID* local = generator.registerFor(m_ident)) {
</ins><span class="cx"> if (dst == ignoredResult())
</span><span class="cx"> return 0;
</span><span class="cx"> return generator.emitTypeOf(generator.finalDestination(dst), local);
</span><span class="lines">@@ -658,7 +658,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocal(m_ident)) {
</del><ins>+ if (RegisterID* local = generator.registerFor(m_ident)) {
</ins><span class="cx"> if (generator.isLocalConstant(m_ident)) {
</span><span class="cx"> if (dst == ignoredResult())
</span><span class="cx"> return 0;
</span><span class="lines">@@ -893,7 +893,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocal(m_ident)) {
</del><ins>+ if (RegisterID* local = generator.registerFor(m_ident)) {
</ins><span class="cx"> if (generator.isLocalConstant(m_ident)) {
</span><span class="cx"> RegisterID* src2 = generator.emitNode(m_right.get());
</span><span class="cx"> return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
</span><span class="lines">@@ -937,7 +937,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocal(m_ident)) {
</del><ins>+ if (RegisterID* local = generator.registerFor(m_ident)) {
</ins><span class="cx"> if (generator.isLocalConstant(m_ident))
</span><span class="cx"> return generator.emitNode(dst, m_right.get());
</span><span class="cx">
</span><span class="lines">@@ -1047,7 +1047,7 @@
</span><span class="cx">
</span><span class="cx"> RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
</span><span class="cx"> {
</span><del>- if (RegisterID* local = generator.registerForLocalConstInit(m_ident)) {
</del><ins>+ if (RegisterID* local = generator.constRegisterFor(m_ident)) {
</ins><span class="cx"> if (!m_init)
</span><span class="cx"> return local;
</span><span class="cx">
</span><span class="lines">@@ -1338,7 +1338,7 @@
</span><span class="cx"> RegisterID* propertyName;
</span><span class="cx"> if (m_lexpr->isResolveNode()) {
</span><span class="cx"> const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
</span><del>- propertyName = generator.registerForLocal(ident);
</del><ins>+ propertyName = generator.registerFor(ident);
</ins><span class="cx"> if (!propertyName) {
</span><span class="cx"> propertyName = generator.newTemporary();
</span><span class="cx"> RefPtr<RegisterID> protect = propertyName;
</span></span></pre></div>
<a id="trunkJavaScriptCoremasmX86Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/masm/X86Assembler.h (36820 => 36821)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/masm/X86Assembler.h 2008-09-24 00:23:28 UTC (rev 36820)
+++ trunk/JavaScriptCore/masm/X86Assembler.h 2008-09-24 00:27:18 UTC (rev 36821)
</span><span class="lines">@@ -678,12 +678,6 @@
</span><span class="cx"> emitModRm_opm(GROUP5_OP_JMPN, base, offset);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void call_r(RegisterID dst)
- {
- m_buffer->putByte(OP_GROUP5_Ev);
- emitModRm_opr(GROUP5_OP_CALLN, dst);
- }
-
</del><span class="cx"> // Opaque label types
</span><span class="cx">
</span><span class="cx"> class JmpSrc {
</span><span class="lines">@@ -728,6 +722,13 @@
</span><span class="cx"> return JmpSrc(m_buffer->getOffset());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ JmpSrc emitCall(RegisterID dst)
+ {
+ m_buffer->putByte(OP_GROUP5_Ev);
+ emitModRm_opr(GROUP5_OP_CALLN, dst);
+ return JmpSrc(m_buffer->getOffset());
+ }
+
</ins><span class="cx"> JmpDst label()
</span><span class="cx"> {
</span><span class="cx"> return JmpDst(m_buffer->getOffset());
</span></span></pre>
</div>
</div>
</body>
</html>