<!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>[38635] 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/38635">38635</a></dd>
<dt>Author</dt> <dd>weinig@apple.com</dd>
<dt>Date</dt> <dd>2008-11-20 15:23:59 -0800 (Thu, 20 Nov 2008)</dd>
</dl>

<h3>Log Message</h3>
<pre>2008-11-20  Sam Weinig  &lt;sam@webkit.org&gt;

        Reviewed by Darin Adler.

        Patch for https://bugs.webkit.org/show_bug.cgi?id=22385
        &lt;rdar://problem/6390179&gt;
        Lazily reparse FunctionBodyNodes on first execution.

        - Saves 57MB on Membuster head.

        * bytecompiler/BytecodeGenerator.cpp:
        (JSC::BytecodeGenerator::generate): Remove vector shrinking since this is now
        handled by destroying the ScopeNodeData after generation.

        * parser/Grammar.y: Add alternate NoNode version of the grammar
        that does not create nodes.  This is used to lazily create FunctionBodyNodes
        on first execution.

        * parser/Lexer.cpp:
        (JSC::Lexer::setCode): Fix bug where on reparse, the Lexer was confused about
        what position and length meant. Position is the current position in the original
        data buffer (important for getting correct line/column information) and length
        the end offset in the original buffer.
        * parser/Lexer.h:
        (JSC::Lexer::sourceCode): Positions are relative to the beginning of the buffer.

        * parser/Nodes.cpp:
        (JSC::ScopeNodeData::ScopeNodeData): Move initialization of ScopeNode data here.
        (JSC::ScopeNode::ScopeNode): Add constructor that only sets the JSGlobalData
        for FunctionBodyNode stubs.
        (JSC::ScopeNode::~ScopeNode): Release m_children now that we don't inherit from
        BlockNode.
        (JSC::ScopeNode::releaseNodes): Ditto.
        (JSC::EvalNode::generateBytecode): Only shrink m_children, as we need to keep around
        the rest of the data.
        (JSC::FunctionBodyNode::FunctionBodyNode): Add constructor that only sets the
        JSGlobalData. 
        (JSC::FunctionBodyNode::create): Ditto.
        (JSC::FunctionBodyNode::generateBytecode): If we don't have the data, do a reparse
        to construct it. Then after generation, destroy the data.
        (JSC::ProgramNode::generateBytecode): After generation, destroy the AST data.
        * parser/Nodes.h:
        (JSC::ExpressionNode::): Add isFuncExprNode for FunctionConstructor.
        (JSC::StatementNode::): Add isExprStatementNode for FunctionConstructor.
        (JSC::ExprStatementNode::): Ditto.
        (JSC::ExprStatementNode::expr): Add accessor for FunctionConstructor.
        (JSC::FuncExprNode::): Add isFuncExprNode for FunctionConstructor

        (JSC::ScopeNode::adoptData): Adopts a ScopeNodeData.
        (JSC::ScopeNode::data): Accessor for ScopeNodeData.
        (JSC::ScopeNode::destroyData): Deletes the ScopeNodeData.
        (JSC::ScopeNode::setFeatures): Added.
        (JSC::ScopeNode::varStack): Added assert.
        (JSC::ScopeNode::functionStack): Ditto.
        (JSC::ScopeNode::children): Ditto.
        (JSC::ScopeNode::neededConstants): Ditto.
        Factor m_varStack, m_functionStack, m_children and m_numConstants into ScopeNodeData.

        * parser/Parser.cpp:
        (JSC::Parser::reparse): Reparse the SourceCode in the FunctionBodyNode and set
        set up the ScopeNodeData for it. 
        * parser/Parser.h:

        * parser/SourceCode.h:
        (JSC::SourceCode::endOffset): Added for use in the lexer.

        * runtime/FunctionConstructor.cpp:
        (JSC::getFunctionBody): Assuming a ProgramNode with one FunctionExpression in it,
        get the FunctionBodyNode.  Any issues signifies a parse failure in constructFunction. 
        (JSC::constructFunction): Make parsing functions in the form new Function(&quot;&quot;), easier
        by concatenating the strings together (with some glue) and parsing the function expression
        as a ProgramNode from which we can receive the FunctionBodyNode. This has the added benefit
        of not having special parsing code for the arguments and lazily constructing the 
        FunctionBodyNode's AST on first execution.

        * runtime/Identifier.h:
        (JSC::operator!=): Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreChangeLog">trunk/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkJavaScriptCoreparserGrammary">trunk/JavaScriptCore/parser/Grammar.y</a></li>
<li><a href="#trunkJavaScriptCoreparserLexercpp">trunk/JavaScriptCore/parser/Lexer.cpp</a></li>
<li><a href="#trunkJavaScriptCoreparserLexerh">trunk/JavaScriptCore/parser/Lexer.h</a></li>
<li><a href="#trunkJavaScriptCoreparserNodescpp">trunk/JavaScriptCore/parser/Nodes.cpp</a></li>
<li><a href="#trunkJavaScriptCoreparserNodesh">trunk/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#trunkJavaScriptCoreparserParsercpp">trunk/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkJavaScriptCoreparserParserh">trunk/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkJavaScriptCoreparserSourceCodeh">trunk/JavaScriptCore/parser/SourceCode.h</a></li>
<li><a href="#trunkJavaScriptCoreruntimeFunctionConstructorcpp">trunk/JavaScriptCore/runtime/FunctionConstructor.cpp</a></li>
<li><a href="#trunkJavaScriptCoreruntimeIdentifierh">trunk/JavaScriptCore/runtime/Identifier.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/ChangeLog (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/ChangeLog        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/ChangeLog        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -1,5 +1,83 @@
</span><span class="cx"> 2008-11-20  Sam Weinig  &lt;sam@webkit.org&gt;
</span><span class="cx"> 
</span><ins>+        Reviewed by Darin Adler.
+
+        Patch for https://bugs.webkit.org/show_bug.cgi?id=22385
+        &lt;rdar://problem/6390179&gt;
+        Lazily reparse FunctionBodyNodes on first execution.
+
+        - Saves 57MB on Membuster head.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::generate): Remove vector shrinking since this is now
+        handled by destroying the ScopeNodeData after generation.
+
+        * parser/Grammar.y: Add alternate NoNode version of the grammar
+        that does not create nodes.  This is used to lazily create FunctionBodyNodes
+        on first execution.
+
+        * parser/Lexer.cpp:
+        (JSC::Lexer::setCode): Fix bug where on reparse, the Lexer was confused about
+        what position and length meant. Position is the current position in the original
+        data buffer (important for getting correct line/column information) and length
+        the end offset in the original buffer.
+        * parser/Lexer.h:
+        (JSC::Lexer::sourceCode): Positions are relative to the beginning of the buffer.
+
+        * parser/Nodes.cpp:
+        (JSC::ScopeNodeData::ScopeNodeData): Move initialization of ScopeNode data here.
+        (JSC::ScopeNode::ScopeNode): Add constructor that only sets the JSGlobalData
+        for FunctionBodyNode stubs.
+        (JSC::ScopeNode::~ScopeNode): Release m_children now that we don't inherit from
+        BlockNode.
+        (JSC::ScopeNode::releaseNodes): Ditto.
+        (JSC::EvalNode::generateBytecode): Only shrink m_children, as we need to keep around
+        the rest of the data.
+        (JSC::FunctionBodyNode::FunctionBodyNode): Add constructor that only sets the
+        JSGlobalData. 
+        (JSC::FunctionBodyNode::create): Ditto.
+        (JSC::FunctionBodyNode::generateBytecode): If we don't have the data, do a reparse
+        to construct it. Then after generation, destroy the data.
+        (JSC::ProgramNode::generateBytecode): After generation, destroy the AST data.
+        * parser/Nodes.h:
+        (JSC::ExpressionNode::): Add isFuncExprNode for FunctionConstructor.
+        (JSC::StatementNode::): Add isExprStatementNode for FunctionConstructor.
+        (JSC::ExprStatementNode::): Ditto.
+        (JSC::ExprStatementNode::expr): Add accessor for FunctionConstructor.
+        (JSC::FuncExprNode::): Add isFuncExprNode for FunctionConstructor
+
+        (JSC::ScopeNode::adoptData): Adopts a ScopeNodeData.
+        (JSC::ScopeNode::data): Accessor for ScopeNodeData.
+        (JSC::ScopeNode::destroyData): Deletes the ScopeNodeData.
+        (JSC::ScopeNode::setFeatures): Added.
+        (JSC::ScopeNode::varStack): Added assert.
+        (JSC::ScopeNode::functionStack): Ditto.
+        (JSC::ScopeNode::children): Ditto.
+        (JSC::ScopeNode::neededConstants): Ditto.
+        Factor m_varStack, m_functionStack, m_children and m_numConstants into ScopeNodeData.
+
+        * parser/Parser.cpp:
+        (JSC::Parser::reparse): Reparse the SourceCode in the FunctionBodyNode and set
+        set up the ScopeNodeData for it. 
+        * parser/Parser.h:
+
+        * parser/SourceCode.h:
+        (JSC::SourceCode::endOffset): Added for use in the lexer.
+
+        * runtime/FunctionConstructor.cpp:
+        (JSC::getFunctionBody): Assuming a ProgramNode with one FunctionExpression in it,
+        get the FunctionBodyNode.  Any issues signifies a parse failure in constructFunction. 
+        (JSC::constructFunction): Make parsing functions in the form new Function(&quot;&quot;), easier
+        by concatenating the strings together (with some glue) and parsing the function expression
+        as a ProgramNode from which we can receive the FunctionBodyNode. This has the added benefit
+        of not having special parsing code for the arguments and lazily constructing the 
+        FunctionBodyNode's AST on first execution.
+
+        * runtime/Identifier.h:
+        (JSC::operator!=): Added.
+
+2008-11-20  Sam Weinig  &lt;sam@webkit.org&gt;
+
</ins><span class="cx">         Reviewed by Geoffrey Garen.
</span><span class="cx"> 
</span><span class="cx">         Speedup the lexer to offset coming re-parsing patch.
</span></span></pre></div>
<a id="trunkJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -139,12 +139,6 @@
</span><span class="cx">         m_codeBlock-&gt;dump(globalObject-&gt;globalExec());
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><del>-
-    m_scopeNode-&gt;children().shrinkCapacity(0);
-    if (m_codeType != EvalCode) { // eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time.
-        m_scopeNode-&gt;varStack().shrinkCapacity(0);
-        m_scopeNode-&gt;functionStack().shrinkCapacity(0);
-    }
</del><span class="cx">     
</span><span class="cx">     m_codeBlock-&gt;instructions.shrinkToFit();
</span><span class="cx">     m_codeBlock-&gt;globalResolveInstructions.shrinkToFit();
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserGrammary"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/Grammar.y (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/Grammar.y        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/Grammar.y        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -283,6 +283,10 @@
</span><span class="cx"> %type &lt;propertyList&gt;    PropertyList
</span><span class="cx"> %%
</span><span class="cx"> 
</span><ins>+// FIXME: There are currently two versions of the grammar in this file, the normal one, and the NoNodes version used for
+// lazy recompilation of FunctionBodyNodes.  We should move to generating the two versions from a script to avoid bugs.
+// In the mean time, make sure to make any changes to the grammar in both versions.
+
</ins><span class="cx"> Literal:
</span><span class="cx">     NULLTOKEN                           { $$ = createNodeInfo&lt;ExpressionNode*&gt;(new NullNode(GLOBAL_DATA), 0, 1); }
</span><span class="cx">   | TRUETOKEN                           { $$ = createNodeInfo&lt;ExpressionNode*&gt;(new BooleanNode(GLOBAL_DATA, true), 0, 1); }
</span><span class="lines">@@ -1203,21 +1207,8 @@
</span><span class="cx"> ;
</span><span class="cx"> 
</span><span class="cx"> FunctionBody:
</span><del>-    /* not in spec */           { $$ = FunctionBodyNode::create(GLOBAL_DATA, 0, 0, 0, NoFeatures, 0); }
-  | SourceElements              { $$ = FunctionBodyNode::create(GLOBAL_DATA, $1.m_node, $1.m_varDeclarations ? &amp;$1.m_varDeclarations-&gt;data : 0, 
-                                                                $1.m_funcDeclarations ? &amp;$1.m_funcDeclarations-&gt;data : 0,
-                                                                $1.m_features, $1.m_numConstants);
-                                  // As in mergeDeclarationLists() we have to ref/deref to safely get rid of
-                                  // the declaration lists.
-                                  if ($1.m_varDeclarations) {
-                                      $1.m_varDeclarations-&gt;ref();
-                                      $1.m_varDeclarations-&gt;deref();
-                                  }
-                                  if ($1.m_funcDeclarations) {
-                                      $1.m_funcDeclarations-&gt;ref();
-                                      $1.m_funcDeclarations-&gt;deref();
-                                  }
-                                }
</del><ins>+    /* not in spec */                   { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
+  | SourceElements_NoNode               { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
</ins><span class="cx"> ;
</span><span class="cx"> 
</span><span class="cx"> Program:
</span><span class="lines">@@ -1247,6 +1238,598 @@
</span><span class="cx">   | Statement                           { $$ = $1; }
</span><span class="cx"> ;
</span><span class="cx">  
</span><ins>+// Start NoNodes
+
+Literal_NoNode:
+    NULLTOKEN
+  | TRUETOKEN
+  | FALSETOKEN
+  | NUMBER
+  | STRING
+  | '/' /* regexp */ { Lexer&amp; l = *LEXER; if (!l.scanRegExp()) YYABORT; }
+  | DIVEQUAL /* regexp with /= */ { Lexer&amp; l = *LEXER; if (!l.scanRegExp()) YYABORT; }
+;
+
+Property_NoNode:
+    IDENT ':' AssignmentExpr_NoNode
+  | STRING ':' AssignmentExpr_NoNode
+  | NUMBER ':' AssignmentExpr_NoNode
+  | IDENT IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != &quot;get&quot; &amp;&amp; *$1 != &quot;set&quot;) YYABORT; }
+  | IDENT IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != &quot;get&quot; &amp;&amp; *$1 != &quot;set&quot;) YYABORT; }
+;
+
+PropertyList_NoNode:
+    Property_NoNode
+  | PropertyList_NoNode ',' Property_NoNode
+;
+
+PrimaryExpr_NoNode:
+    PrimaryExprNoBrace_NoNode
+  | OPENBRACE CLOSEBRACE
+  | OPENBRACE PropertyList_NoNode CLOSEBRACE
+  /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
+  | OPENBRACE PropertyList_NoNode ',' CLOSEBRACE
+;
+
+PrimaryExprNoBrace_NoNode:
+    THISTOKEN
+  | Literal_NoNode
+  | ArrayLiteral_NoNode
+  | IDENT
+  | '(' Expr_NoNode ')'
+;
+
+ArrayLiteral_NoNode:
+    '[' ElisionOpt_NoNode ']'
+  | '[' ElementList_NoNode ']'
+  | '[' ElementList_NoNode ',' ElisionOpt_NoNode ']'
+;
+
+ElementList_NoNode:
+    ElisionOpt_NoNode AssignmentExpr_NoNode
+  | ElementList_NoNode ',' ElisionOpt_NoNode AssignmentExpr_NoNode
+;
+
+ElisionOpt_NoNode:
+    /* nothing */
+  | Elision_NoNode
+;
+
+Elision_NoNode:
+    ','
+  | Elision_NoNode ','
+;
+
+MemberExpr_NoNode:
+    PrimaryExpr_NoNode
+  | FunctionExpr_NoNode
+  | MemberExpr_NoNode '[' Expr_NoNode ']'
+  | MemberExpr_NoNode '.' IDENT
+  | NEW MemberExpr_NoNode Arguments_NoNode
+;
+
+MemberExprNoBF_NoNode:
+    PrimaryExprNoBrace_NoNode
+  | MemberExprNoBF_NoNode '[' Expr_NoNode ']'
+  | MemberExprNoBF_NoNode '.' IDENT
+  | NEW MemberExpr_NoNode Arguments_NoNode
+;
+
+NewExpr_NoNode:
+    MemberExpr_NoNode
+  | NEW NewExpr_NoNode
+;
+
+NewExprNoBF_NoNode:
+    MemberExprNoBF_NoNode
+  | NEW NewExpr_NoNode
+;
+
+CallExpr_NoNode:
+    MemberExpr_NoNode Arguments_NoNode
+  | CallExpr_NoNode Arguments_NoNode
+  | CallExpr_NoNode '[' Expr_NoNode ']'
+  | CallExpr_NoNode '.' IDENT
+;
+
+CallExprNoBF_NoNode:
+    MemberExprNoBF_NoNode Arguments_NoNode
+  | CallExprNoBF_NoNode Arguments_NoNode
+  | CallExprNoBF_NoNode '[' Expr_NoNode ']'
+  | CallExprNoBF_NoNode '.' IDENT
+;
+
+Arguments_NoNode:
+    '(' ')'
+  | '(' ArgumentList_NoNode ')'
+;
+
+ArgumentList_NoNode:
+    AssignmentExpr_NoNode
+  | ArgumentList_NoNode ',' AssignmentExpr_NoNode
+;
+
+LeftHandSideExpr_NoNode:
+    NewExpr_NoNode
+  | CallExpr_NoNode
+;
+
+LeftHandSideExprNoBF_NoNode:
+    NewExprNoBF_NoNode
+  | CallExprNoBF_NoNode
+;
+
+PostfixExpr_NoNode:
+    LeftHandSideExpr_NoNode
+  | LeftHandSideExpr_NoNode PLUSPLUS
+  | LeftHandSideExpr_NoNode MINUSMINUS
+;
+
+PostfixExprNoBF_NoNode:
+    LeftHandSideExprNoBF_NoNode
+  | LeftHandSideExprNoBF_NoNode PLUSPLUS
+  | LeftHandSideExprNoBF_NoNode MINUSMINUS
+;
+
+UnaryExprCommon_NoNode:
+    DELETETOKEN UnaryExpr_NoNode
+  | VOIDTOKEN UnaryExpr_NoNode
+  | TYPEOF UnaryExpr_NoNode
+  | PLUSPLUS UnaryExpr_NoNode
+  | AUTOPLUSPLUS UnaryExpr_NoNode
+  | MINUSMINUS UnaryExpr_NoNode
+  | AUTOMINUSMINUS UnaryExpr_NoNode
+  | '+' UnaryExpr_NoNode
+  | '-' UnaryExpr_NoNode
+  | '~' UnaryExpr_NoNode
+  | '!' UnaryExpr_NoNode
+
+UnaryExpr_NoNode:
+    PostfixExpr_NoNode
+  | UnaryExprCommon_NoNode
+;
+
+UnaryExprNoBF_NoNode:
+    PostfixExprNoBF_NoNode
+  | UnaryExprCommon_NoNode
+;
+
+MultiplicativeExpr_NoNode:
+    UnaryExpr_NoNode
+  | MultiplicativeExpr_NoNode '*' UnaryExpr_NoNode
+  | MultiplicativeExpr_NoNode '/' UnaryExpr_NoNode
+  | MultiplicativeExpr_NoNode '%' UnaryExpr_NoNode
+;
+
+MultiplicativeExprNoBF_NoNode:
+    UnaryExprNoBF_NoNode
+  | MultiplicativeExprNoBF_NoNode '*' UnaryExpr_NoNode
+  | MultiplicativeExprNoBF_NoNode '/' UnaryExpr_NoNode
+  | MultiplicativeExprNoBF_NoNode '%' UnaryExpr_NoNode
+;
+
+AdditiveExpr_NoNode:
+    MultiplicativeExpr_NoNode
+  | AdditiveExpr_NoNode '+' MultiplicativeExpr_NoNode
+  | AdditiveExpr_NoNode '-' MultiplicativeExpr_NoNode
+;
+
+AdditiveExprNoBF_NoNode:
+    MultiplicativeExprNoBF_NoNode
+  | AdditiveExprNoBF_NoNode '+' MultiplicativeExpr_NoNode
+  | AdditiveExprNoBF_NoNode '-' MultiplicativeExpr_NoNode
+;
+
+ShiftExpr_NoNode:
+    AdditiveExpr_NoNode
+  | ShiftExpr_NoNode LSHIFT AdditiveExpr_NoNode
+  | ShiftExpr_NoNode RSHIFT AdditiveExpr_NoNode
+  | ShiftExpr_NoNode URSHIFT AdditiveExpr_NoNode
+;
+
+ShiftExprNoBF_NoNode:
+    AdditiveExprNoBF_NoNode
+  | ShiftExprNoBF_NoNode LSHIFT AdditiveExpr_NoNode
+  | ShiftExprNoBF_NoNode RSHIFT AdditiveExpr_NoNode
+  | ShiftExprNoBF_NoNode URSHIFT AdditiveExpr_NoNode
+;
+
+RelationalExpr_NoNode:
+    ShiftExpr_NoNode
+  | RelationalExpr_NoNode '&lt;' ShiftExpr_NoNode
+  | RelationalExpr_NoNode '&gt;' ShiftExpr_NoNode
+  | RelationalExpr_NoNode LE ShiftExpr_NoNode
+  | RelationalExpr_NoNode GE ShiftExpr_NoNode
+  | RelationalExpr_NoNode INSTANCEOF ShiftExpr_NoNode
+  | RelationalExpr_NoNode INTOKEN ShiftExpr_NoNode
+;
+
+RelationalExprNoIn_NoNode:
+    ShiftExpr_NoNode
+  | RelationalExprNoIn_NoNode '&lt;' ShiftExpr_NoNode
+  | RelationalExprNoIn_NoNode '&gt;' ShiftExpr_NoNode
+  | RelationalExprNoIn_NoNode LE ShiftExpr_NoNode
+  | RelationalExprNoIn_NoNode GE ShiftExpr_NoNode
+  | RelationalExprNoIn_NoNode INSTANCEOF ShiftExpr_NoNode
+;
+
+RelationalExprNoBF_NoNode:
+    ShiftExprNoBF_NoNode
+  | RelationalExprNoBF_NoNode '&lt;' ShiftExpr_NoNode
+  | RelationalExprNoBF_NoNode '&gt;' ShiftExpr_NoNode
+  | RelationalExprNoBF_NoNode LE ShiftExpr_NoNode
+  | RelationalExprNoBF_NoNode GE ShiftExpr_NoNode
+  | RelationalExprNoBF_NoNode INSTANCEOF ShiftExpr_NoNode
+  | RelationalExprNoBF_NoNode INTOKEN ShiftExpr_NoNode
+;
+
+EqualityExpr_NoNode:
+    RelationalExpr_NoNode
+  | EqualityExpr_NoNode EQEQ RelationalExpr_NoNode
+  | EqualityExpr_NoNode NE RelationalExpr_NoNode
+  | EqualityExpr_NoNode STREQ RelationalExpr_NoNode
+  | EqualityExpr_NoNode STRNEQ RelationalExpr_NoNode
+;
+
+EqualityExprNoIn_NoNode:
+    RelationalExprNoIn_NoNode
+  | EqualityExprNoIn_NoNode EQEQ RelationalExprNoIn_NoNode
+  | EqualityExprNoIn_NoNode NE RelationalExprNoIn_NoNode
+  | EqualityExprNoIn_NoNode STREQ RelationalExprNoIn_NoNode
+  | EqualityExprNoIn_NoNode STRNEQ RelationalExprNoIn_NoNode
+;
+
+EqualityExprNoBF_NoNode:
+    RelationalExprNoBF_NoNode
+  | EqualityExprNoBF_NoNode EQEQ RelationalExpr_NoNode
+  | EqualityExprNoBF_NoNode NE RelationalExpr_NoNode
+  | EqualityExprNoBF_NoNode STREQ RelationalExpr_NoNode
+  | EqualityExprNoBF_NoNode STRNEQ RelationalExpr_NoNode
+;
+
+BitwiseANDExpr_NoNode:
+    EqualityExpr_NoNode
+  | BitwiseANDExpr_NoNode '&amp;' EqualityExpr_NoNode
+;
+
+BitwiseANDExprNoIn_NoNode:
+    EqualityExprNoIn_NoNode
+  | BitwiseANDExprNoIn_NoNode '&amp;' EqualityExprNoIn_NoNode
+;
+
+BitwiseANDExprNoBF_NoNode:
+    EqualityExprNoBF_NoNode
+  | BitwiseANDExprNoBF_NoNode '&amp;' EqualityExpr_NoNode
+;
+
+BitwiseXORExpr_NoNode:
+    BitwiseANDExpr_NoNode
+  | BitwiseXORExpr_NoNode '^' BitwiseANDExpr_NoNode
+;
+
+BitwiseXORExprNoIn_NoNode:
+    BitwiseANDExprNoIn_NoNode
+  | BitwiseXORExprNoIn_NoNode '^' BitwiseANDExprNoIn_NoNode
+;
+
+BitwiseXORExprNoBF_NoNode:
+    BitwiseANDExprNoBF_NoNode
+  | BitwiseXORExprNoBF_NoNode '^' BitwiseANDExpr_NoNode
+;
+
+BitwiseORExpr_NoNode:
+    BitwiseXORExpr_NoNode
+  | BitwiseORExpr_NoNode '|' BitwiseXORExpr_NoNode
+;
+
+BitwiseORExprNoIn_NoNode:
+    BitwiseXORExprNoIn_NoNode
+  | BitwiseORExprNoIn_NoNode '|' BitwiseXORExprNoIn_NoNode
+;
+
+BitwiseORExprNoBF_NoNode:
+    BitwiseXORExprNoBF_NoNode
+  | BitwiseORExprNoBF_NoNode '|' BitwiseXORExpr_NoNode
+;
+
+LogicalANDExpr_NoNode:
+    BitwiseORExpr_NoNode
+  | LogicalANDExpr_NoNode AND BitwiseORExpr_NoNode
+;
+
+LogicalANDExprNoIn_NoNode:
+    BitwiseORExprNoIn_NoNode
+  | LogicalANDExprNoIn_NoNode AND BitwiseORExprNoIn_NoNode
+;
+
+LogicalANDExprNoBF_NoNode:
+    BitwiseORExprNoBF_NoNode
+  | LogicalANDExprNoBF_NoNode AND BitwiseORExpr_NoNode
+;
+
+LogicalORExpr_NoNode:
+    LogicalANDExpr_NoNode
+  | LogicalORExpr_NoNode OR LogicalANDExpr_NoNode
+;
+
+LogicalORExprNoIn_NoNode:
+    LogicalANDExprNoIn_NoNode
+  | LogicalORExprNoIn_NoNode OR LogicalANDExprNoIn_NoNode
+;
+
+LogicalORExprNoBF_NoNode:
+    LogicalANDExprNoBF_NoNode
+  | LogicalORExprNoBF_NoNode OR LogicalANDExpr_NoNode
+;
+
+ConditionalExpr_NoNode:
+    LogicalORExpr_NoNode
+  | LogicalORExpr_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
+;
+
+ConditionalExprNoIn_NoNode:
+    LogicalORExprNoIn_NoNode
+  | LogicalORExprNoIn_NoNode '?' AssignmentExprNoIn_NoNode ':' AssignmentExprNoIn_NoNode
+;
+
+ConditionalExprNoBF_NoNode:
+    LogicalORExprNoBF_NoNode
+  | LogicalORExprNoBF_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
+;
+
+AssignmentExpr_NoNode:
+    ConditionalExpr_NoNode
+  | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
+;
+
+AssignmentExprNoIn_NoNode:
+    ConditionalExprNoIn_NoNode
+  | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExprNoIn_NoNode
+;
+
+AssignmentExprNoBF_NoNode:
+    ConditionalExprNoBF_NoNode
+  | LeftHandSideExprNoBF_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
+;
+
+AssignmentOperator_NoNode:
+    '='
+  | PLUSEQUAL
+  | MINUSEQUAL
+  | MULTEQUAL
+  | DIVEQUAL
+  | LSHIFTEQUAL
+  | RSHIFTEQUAL
+  | URSHIFTEQUAL
+  | ANDEQUAL
+  | XOREQUAL
+  | OREQUAL
+  | MODEQUAL
+;
+
+Expr_NoNode:
+    AssignmentExpr_NoNode
+  | Expr_NoNode ',' AssignmentExpr_NoNode
+;
+
+ExprNoIn_NoNode:
+    AssignmentExprNoIn_NoNode
+  | ExprNoIn_NoNode ',' AssignmentExprNoIn_NoNode
+;
+
+ExprNoBF_NoNode:
+    AssignmentExprNoBF_NoNode
+  | ExprNoBF_NoNode ',' AssignmentExpr_NoNode
+;
+
+Statement_NoNode:
+    Block_NoNode
+  | VariableStatement_NoNode
+  | ConstStatement_NoNode
+  | EmptyStatement_NoNode
+  | ExprStatement_NoNode
+  | IfStatement_NoNode
+  | IterationStatement_NoNode
+  | ContinueStatement_NoNode
+  | BreakStatement_NoNode
+  | ReturnStatement_NoNode
+  | WithStatement_NoNode
+  | SwitchStatement_NoNode
+  | LabelledStatement_NoNode
+  | ThrowStatement_NoNode
+  | TryStatement_NoNode
+  | DebuggerStatement_NoNode
+;
+
+Block_NoNode:
+    OPENBRACE CLOSEBRACE
+  | OPENBRACE SourceElements_NoNode CLOSEBRACE
+;
+
+VariableStatement_NoNode:
+    VAR VariableDeclarationList_NoNode ';'
+  | VAR VariableDeclarationList_NoNode error { AUTO_SEMICOLON; }
+;
+
+VariableDeclarationList_NoNode:
+    IDENT
+  | IDENT Initializer_NoNode
+  | VariableDeclarationList_NoNode ',' IDENT
+  | VariableDeclarationList_NoNode ',' IDENT Initializer_NoNode
+;
+
+VariableDeclarationListNoIn_NoNode:
+    IDENT
+  | IDENT InitializerNoIn_NoNode
+  | VariableDeclarationListNoIn_NoNode ',' IDENT
+  | VariableDeclarationListNoIn_NoNode ',' IDENT InitializerNoIn_NoNode
+;
+
+ConstStatement_NoNode:
+    CONSTTOKEN ConstDeclarationList_NoNode ';'
+  | CONSTTOKEN ConstDeclarationList_NoNode error { AUTO_SEMICOLON; }
+;
+
+ConstDeclarationList_NoNode:
+    ConstDeclaration_NoNode
+  | ConstDeclarationList_NoNode ',' ConstDeclaration_NoNode
+;
+
+ConstDeclaration_NoNode:
+    IDENT
+  | IDENT Initializer_NoNode
+;
+
+Initializer_NoNode:
+    '=' AssignmentExpr_NoNode
+;
+
+InitializerNoIn_NoNode:
+    '=' AssignmentExprNoIn_NoNode
+;
+
+EmptyStatement_NoNode:
+    ';'
+;
+
+ExprStatement_NoNode:
+    ExprNoBF_NoNode ';'
+  | ExprNoBF_NoNode error { AUTO_SEMICOLON; }
+;
+
+IfStatement_NoNode:
+    IF '(' Expr_NoNode ')' Statement_NoNode %prec IF_WITHOUT_ELSE
+  | IF '(' Expr_NoNode ')' Statement_NoNode ELSE Statement_NoNode
+;
+
+IterationStatement_NoNode:
+    DO Statement_NoNode WHILE '(' Expr_NoNode ')' ';'
+  | DO Statement_NoNode WHILE '(' Expr_NoNode ')' error // Always performs automatic semicolon insertion
+  | WHILE '(' Expr_NoNode ')' Statement_NoNode
+  | FOR '(' ExprNoInOpt_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
+  | FOR '(' VAR VariableDeclarationListNoIn_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
+  | FOR '(' LeftHandSideExpr_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
+  | FOR '(' VAR IDENT INTOKEN Expr_NoNode ')' Statement_NoNode
+  | FOR '(' VAR IDENT InitializerNoIn_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
+;
+
+ExprOpt_NoNode:
+    /* nothing */
+  | Expr_NoNode
+;
+
+ExprNoInOpt_NoNode:
+    /* nothing */
+  | ExprNoIn_NoNode
+;
+
+ContinueStatement_NoNode:
+    CONTINUE ';'
+  | CONTINUE error { AUTO_SEMICOLON; }
+  | CONTINUE IDENT ';'
+  | CONTINUE IDENT error { AUTO_SEMICOLON; }
+;
+
+BreakStatement_NoNode:
+    BREAK ';'
+  | BREAK error { AUTO_SEMICOLON; }
+  | BREAK IDENT ';'
+  | BREAK IDENT error { AUTO_SEMICOLON; }
+;
+
+ReturnStatement_NoNode:
+    RETURN ';'
+  | RETURN error { AUTO_SEMICOLON; }
+  | RETURN Expr_NoNode ';'
+  | RETURN Expr_NoNode error { AUTO_SEMICOLON; }
+;
+
+WithStatement_NoNode:
+    WITH '(' Expr_NoNode ')' Statement_NoNode
+;
+
+SwitchStatement_NoNode:
+    SWITCH '(' Expr_NoNode ')' CaseBlock_NoNode
+;
+
+CaseBlock_NoNode:
+    OPENBRACE CaseClausesOpt_NoNode CLOSEBRACE
+  | OPENBRACE CaseClausesOpt_NoNode DefaultClause_NoNode CaseClausesOpt_NoNode CLOSEBRACE
+;
+
+CaseClausesOpt_NoNode:
+    /* nothing */
+  | CaseClauses_NoNode
+;
+
+CaseClauses_NoNode:
+    CaseClause_NoNode
+  | CaseClauses_NoNode CaseClause_NoNode
+;
+
+CaseClause_NoNode:
+    CASE Expr_NoNode ':'
+  | CASE Expr_NoNode ':' SourceElements_NoNode
+;
+
+DefaultClause_NoNode:
+    DEFAULT ':'
+  | DEFAULT ':' SourceElements_NoNode
+;
+
+LabelledStatement_NoNode:
+    IDENT ':' Statement_NoNode;
+
+ThrowStatement_NoNode:
+    THROW Expr_NoNode ';'
+  | THROW Expr_NoNode error { AUTO_SEMICOLON; }
+;
+
+TryStatement_NoNode:
+    TRY Block_NoNode FINALLY Block_NoNode
+  | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode
+  | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode FINALLY Block_NoNode
+;
+
+DebuggerStatement_NoNode:
+    DEBUGGER ';'
+  | DEBUGGER error { AUTO_SEMICOLON; }
+;
+
+FunctionDeclaration_NoNode:
+    FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+  | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+;
+
+FunctionExpr_NoNode:
+    FUNCTION '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+  | FUNCTION '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+  | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+  | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+;
+
+FormalParameterList_NoNode:
+    IDENT
+  | FormalParameterList_NoNode ',' IDENT
+;
+
+FunctionBody_NoNode:
+    /* not in spec */
+  | SourceElements_NoNode
+;
+
+SourceElements_NoNode:
+    SourceElement_NoNode
+  | SourceElements_NoNode SourceElement_NoNode
+;
+
+SourceElement_NoNode:
+    FunctionDeclaration_NoNode
+  | Statement_NoNode
+;
+
+// End NoNodes
+
</ins><span class="cx"> %%
</span><span class="cx"> 
</span><span class="cx"> static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserLexercpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/Lexer.cpp (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/Lexer.cpp        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/Lexer.cpp        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -96,10 +96,10 @@
</span><span class="cx">     m_stackToken = -1;
</span><span class="cx">     m_lastToken = -1;
</span><span class="cx"> 
</span><del>-    m_position = 0;
</del><ins>+    m_position = source.startOffset();
</ins><span class="cx">     m_source = &amp;source;
</span><del>-    m_code = source.data();
-    m_length = source.length();
</del><ins>+    m_code = source.provider()-&gt;data();
+    m_length = source.endOffset();
</ins><span class="cx">     m_skipLF = false;
</span><span class="cx">     m_skipCR = false;
</span><span class="cx">     m_error = false;
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserLexerh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/Lexer.h (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/Lexer.h        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/Lexer.h        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx">         bool sawError() const { return m_error; }
</span><span class="cx"> 
</span><span class="cx">         void clear();
</span><del>-        SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source-&gt;provider(), m_source-&gt;startOffset() + openBrace + 1, m_source-&gt;startOffset() + closeBrace, firstLine); }
</del><ins>+        SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source-&gt;provider(), openBrace + 1, closeBrace, firstLine); }
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         friend class JSGlobalData;
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserNodescpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/Nodes.cpp (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/Nodes.cpp        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/Nodes.cpp        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -2377,23 +2377,55 @@
</span><span class="cx">     releaser.release(m_next);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// ------------------------------ ScopeNode -----------------------------
</del><ins>+// -----------------------------ScopeNodeData ---------------------------
</ins><span class="cx"> 
</span><del>-ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode&amp; source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
-    : BlockNode(globalData, children)
-    , m_source(source)
-    , m_features(features)
-    , m_numConstants(numConstants)
</del><ins>+ScopeNodeData::ScopeNodeData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants)
+    : m_numConstants(numConstants)
</ins><span class="cx"> {
</span><span class="cx">     if (varStack)
</span><span class="cx">         m_varStack = *varStack;
</span><span class="cx">     if (funcStack)
</span><span class="cx">         m_functionStack = *funcStack;
</span><ins>+    if (children)
+        children-&gt;releaseContentsIntoVector(m_children);
+}
+
+// ------------------------------ ScopeNode -----------------------------
+
+ScopeNode::ScopeNode(JSGlobalData* globalData)
+    : StatementNode(globalData)
+    , m_features(NoFeatures)
+{
</ins><span class="cx"> #if ENABLE(OPCODE_SAMPLING)
</span><span class="cx">     globalData-&gt;interpreter-&gt;sampler()-&gt;notifyOfScope(this);
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode&amp; source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
+    : StatementNode(globalData)
+    , m_data(new ScopeNodeData(children, varStack, funcStack, numConstants))
+    , m_features(features)
+    , m_source(source)
+{
+#if ENABLE(OPCODE_SAMPLING)
+    globalData-&gt;interpreter-&gt;sampler()-&gt;notifyOfScope(this);
+#endif
+}
+
+ScopeNode::~ScopeNode()
+{
+    NodeReleaser::releaseAllNodes(this);
+}
+
+void ScopeNode::releaseNodes(NodeReleaser&amp; releaser)
+{
+    if (!m_data)
+        return;
+    size_t size = m_data-&gt;m_children.size();
+    for (size_t i = 0; i &lt; size; ++i)
+        releaser.release(m_data-&gt;m_children[i]);
+}
+
</ins><span class="cx"> // ------------------------------ ProgramNode -----------------------------
</span><span class="cx"> 
</span><span class="cx"> ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode&amp; source, CodeFeatures features, int numConstants)
</span><span class="lines">@@ -2435,6 +2467,10 @@
</span><span class="cx"> 
</span><span class="cx">     BytecodeGenerator generator(this, globalObject-&gt;debugger(), scopeChain, &amp;m_code-&gt;symbolTable, m_code.get());
</span><span class="cx">     generator.generate();
</span><ins>+
+    // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
+    // so the entire ScopeNodeData cannot be destoyed.
+    children().clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode&amp; source, CodeFeatures features, int numConstants)
</span><span class="lines">@@ -2444,6 +2480,14 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ FunctionBodyNode -----------------------------
</span><span class="cx"> 
</span><ins>+FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
+    : ScopeNode(globalData)
+    , m_parameters(0)
+    , m_parameterCount(0)
+    , m_refCount(0)
+{
+}
+
</ins><span class="cx"> FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode&amp; sourceCode, CodeFeatures features, int numConstants)
</span><span class="cx">     : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
</span><span class="cx">     , m_parameters(0)
</span><span class="lines">@@ -2482,9 +2526,9 @@
</span><span class="cx">         m_code-&gt;mark();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
</del><ins>+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
</ins><span class="cx"> {
</span><del>-    return new FunctionBodyNode(globalData, children, varStack, funcStack, SourceCode(), features, numConstants);
</del><ins>+    return new FunctionBodyNode(globalData);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode&amp; sourceCode, CodeFeatures features, int numConstants)
</span><span class="lines">@@ -2494,6 +2538,12 @@
</span><span class="cx"> 
</span><span class="cx"> void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
</span><span class="cx"> {
</span><ins>+    // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
+    // calling Parser::parse&lt;FunctionBodyNode&gt;().   
+    if (!data())
+        scopeChainNode-&gt;globalData-&gt;parser-&gt;reparse(scopeChainNode-&gt;globalData, this);
+    ASSERT(data());
+
</ins><span class="cx">     ScopeChain scopeChain(scopeChainNode);
</span><span class="cx">     JSGlobalObject* globalObject = scopeChain.globalObject();
</span><span class="cx"> 
</span><span class="lines">@@ -2501,6 +2551,8 @@
</span><span class="cx"> 
</span><span class="cx">     BytecodeGenerator generator(this, globalObject-&gt;debugger(), scopeChain, &amp;m_code-&gt;symbolTable, m_code.get());
</span><span class="cx">     generator.generate();
</span><ins>+
+    destroyData();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID*)
</span><span class="lines">@@ -2537,6 +2589,8 @@
</span><span class="cx">     
</span><span class="cx">     BytecodeGenerator generator(this, globalObject-&gt;debugger(), scopeChain, &amp;globalObject-&gt;symbolTable(), m_code.get());
</span><span class="cx">     generator.generate();
</span><ins>+
+    destroyData();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> UString FunctionBodyNode::paramString() const
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/Nodes.h (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/Nodes.h        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/Nodes.h        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -170,6 +170,7 @@
</span><span class="cx">         virtual bool isResolveNode() const JSC_FAST_CALL { return false; }
</span><span class="cx">         virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; }
</span><span class="cx">         virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; }
</span><ins>+        virtual bool isFuncExprNode() const JSC_FAST_CALL { return false; } 
</ins><span class="cx"> 
</span><span class="cx">         virtual ExpressionNode* stripUnaryPlus() { return this; }
</span><span class="cx"> 
</span><span class="lines">@@ -191,6 +192,7 @@
</span><span class="cx"> 
</span><span class="cx">         virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; }
</span><span class="cx">         virtual bool isReturnNode() const JSC_FAST_CALL { return false; }
</span><ins>+        virtual bool isExprStatement() const JSC_FAST_CALL { return false; }
</ins><span class="cx"> 
</span><span class="cx">         virtual bool isBlock() const JSC_FAST_CALL { return false; }
</span><span class="cx">         virtual bool isLoop() const JSC_FAST_CALL { return false; }
</span><span class="lines">@@ -1742,8 +1744,12 @@
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        virtual bool isExprStatement() const JSC_FAST_CALL { return true; }
+
</ins><span class="cx">         virtual RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) JSC_FAST_CALL;
</span><span class="cx"> 
</span><ins>+        ExpressionNode* expr() const { return m_expr.get(); }
+
</ins><span class="cx">     private:
</span><span class="cx">         RefPtr&lt;ExpressionNode&gt; m_expr;
</span><span class="cx">     };
</span><span class="lines">@@ -2056,43 +2062,63 @@
</span><span class="cx">         RefPtr&lt;ParameterNode&gt; m_next;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    class ScopeNode : public BlockNode {
</del><ins>+    struct ScopeNodeData {
+        typedef DeclarationStacks::VarStack VarStack;
+        typedef DeclarationStacks::FunctionStack FunctionStack;
+
+        ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants);
+
+        VarStack m_varStack;
+        FunctionStack m_functionStack;
+        int m_numConstants;
+        StatementVector m_children;
+    };
+
+    class ScopeNode : public StatementNode {
</ins><span class="cx">     public:
</span><span class="cx">         typedef DeclarationStacks::VarStack VarStack;
</span><span class="cx">         typedef DeclarationStacks::FunctionStack FunctionStack;
</span><span class="cx"> 
</span><ins>+        ScopeNode(JSGlobalData*) JSC_FAST_CALL;
</ins><span class="cx">         ScopeNode(JSGlobalData*, const SourceCode&amp;, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
</span><ins>+        virtual ~ScopeNode();
+        virtual void releaseNodes(NodeReleaser&amp;);
</ins><span class="cx"> 
</span><ins>+        void adoptData(std::auto_ptr&lt;ScopeNodeData&gt; data) { m_data.adopt(data); }
+        ScopeNodeData* data() const { return m_data.get(); }
+        void destroyData() { m_data.clear(); }
+
</ins><span class="cx">         const SourceCode&amp; source() const { return m_source; }
</span><span class="cx">         const UString&amp; sourceURL() const JSC_FAST_CALL { return m_source.provider()-&gt;url(); }
</span><span class="cx">         intptr_t sourceID() const { return m_source.provider()-&gt;asID(); }
</span><span class="cx"> 
</span><ins>+        void setFeatures(CodeFeatures features) { m_features = features; }
</ins><span class="cx">         bool usesEval() const { return m_features &amp; EvalFeature; }
</span><span class="cx">         bool usesArguments() const { return m_features &amp; ArgumentsFeature; }
</span><span class="cx">         void setUsesArguments() { m_features |= ArgumentsFeature; }
</span><span class="cx">         bool usesThis() const { return m_features &amp; ThisFeature; }
</span><span class="cx">         bool needsActivation() const { return m_features &amp; (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
</span><span class="cx"> 
</span><del>-        VarStack&amp; varStack() { return m_varStack; }
-        FunctionStack&amp; functionStack() { return m_functionStack; }
</del><ins>+        VarStack&amp; varStack() { ASSERT(m_data); return m_data-&gt;m_varStack; }
+        FunctionStack&amp; functionStack() { ASSERT(m_data); return m_data-&gt;m_functionStack; }
</ins><span class="cx"> 
</span><ins>+        StatementVector&amp; children() { ASSERT(m_data); return m_data-&gt;m_children; }
+
</ins><span class="cx">         int neededConstants()
</span><span class="cx">         {
</span><ins>+            ASSERT(m_data);
</ins><span class="cx">             // We may need 2 more constants than the count given by the parser,
</span><span class="cx">             // because of the various uses of jsUndefined() and jsNull().
</span><del>-            return m_numConstants + 2;
</del><ins>+            return m_data-&gt;m_numConstants + 2;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">     protected:
</span><span class="cx">         void setSource(const SourceCode&amp; source) { m_source = source; }
</span><span class="cx"> 
</span><del>-        VarStack m_varStack;
-        FunctionStack m_functionStack;
-
</del><span class="cx">     private:
</span><ins>+        OwnPtr&lt;ScopeNodeData&gt; m_data;
+        CodeFeatures m_features;
</ins><span class="cx">         SourceCode m_source;
</span><del>-        CodeFeatures m_features;
-        int m_numConstants;
</del><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class ProgramNode : public ScopeNode {
</span><span class="lines">@@ -2141,9 +2167,9 @@
</span><span class="cx">     class FunctionBodyNode : public ScopeNode {
</span><span class="cx">         friend class JIT;
</span><span class="cx">     public:
</span><ins>+        static FunctionBodyNode* create(JSGlobalData*) JSC_FAST_CALL;
</ins><span class="cx">         static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&amp;, CodeFeatures, int numConstants) JSC_FAST_CALL;
</span><del>-        static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
-        ~FunctionBodyNode();
</del><ins>+        virtual ~FunctionBodyNode();
</ins><span class="cx"> 
</span><span class="cx">         const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; }
</span><span class="cx">         size_t parameterCount() const { return m_parameterCount; }
</span><span class="lines">@@ -2193,6 +2219,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">     private:
</span><ins>+        FunctionBodyNode(JSGlobalData*) JSC_FAST_CALL;
</ins><span class="cx">         FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&amp;, CodeFeatures, int numConstants) JSC_FAST_CALL;
</span><span class="cx"> 
</span><span class="cx">         void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
</span><span class="lines">@@ -2217,6 +2244,8 @@
</span><span class="cx">         virtual ~FuncExprNode();
</span><span class="cx">         virtual void releaseNodes(NodeReleaser&amp;);
</span><span class="cx"> 
</span><ins>+        virtual bool isFuncExprNode() const JSC_FAST_CALL { return true; } 
+
</ins><span class="cx">         virtual RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) JSC_FAST_CALL;
</span><span class="cx">         JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/Parser.cpp (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/Parser.cpp        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/Parser.cpp        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -63,6 +63,28 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Parser::reparse(JSGlobalData* globalData, FunctionBodyNode* functionBodyNode)
+{
+    ASSERT(!functionBodyNode-&gt;data());
+
+    m_source = &amp;functionBodyNode-&gt;source();
+    parse(globalData, 0, 0);
+    ASSERT(m_sourceElements);
+    functionBodyNode-&gt;adoptData(auto_ptr&lt;ScopeNodeData&gt;(new ScopeNodeData(m_sourceElements.get(),
+                                                                          m_varDeclarations ? &amp;m_varDeclarations-&gt;data : 0, 
+                                                                          m_funcDeclarations ? &amp;m_funcDeclarations-&gt;data : 0,
+                                                                          m_numConstants)));
+    bool usesArguments = functionBodyNode-&gt;usesArguments();
+    functionBodyNode-&gt;setFeatures(m_features);
+    if (usesArguments &amp;&amp; !functionBodyNode-&gt;usesArguments())
+        functionBodyNode-&gt;setUsesArguments();
+
+    m_source = 0;
+    m_sourceElements = 0;
+    m_varDeclarations = 0;
+    m_funcDeclarations = 0;
+}
+
</ins><span class="cx"> void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData&lt;DeclarationStacks::VarStack&gt;* varStack, 
</span><span class="cx">                               ParserRefCountedData&lt;DeclarationStacks::FunctionStack&gt;* funcStack, CodeFeatures features, int lastLine, int numConstants)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/Parser.h (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/Parser.h        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/Parser.h        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -51,6 +51,8 @@
</span><span class="cx">     public:
</span><span class="cx">         template &lt;class ParsedNode&gt; PassRefPtr&lt;ParsedNode&gt; parse(ExecState*, Debugger*, const SourceCode&amp;, int* errLine = 0, UString* errMsg = 0);
</span><span class="cx"> 
</span><ins>+        void reparse(JSGlobalData*, FunctionBodyNode*);
+
</ins><span class="cx">         void didFinishParsing(SourceElements*, ParserRefCountedData&lt;DeclarationStacks::VarStack&gt;*, 
</span><span class="cx">                               ParserRefCountedData&lt;DeclarationStacks::FunctionStack&gt;*, CodeFeatures features, int lastLine, int numConstants);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJavaScriptCoreparserSourceCodeh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/parser/SourceCode.h (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/parser/SourceCode.h        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/parser/SourceCode.h        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -70,6 +70,7 @@
</span><span class="cx">         SourceProvider* provider() const { return m_provider.get(); }
</span><span class="cx">         int firstLine() const { return m_firstLine; }
</span><span class="cx">         int startOffset() const { return m_startChar; }
</span><ins>+        int endOffset() const { return m_endChar; }
</ins><span class="cx">         const UChar* data() const { return m_provider-&gt;data() + m_startChar; }
</span><span class="cx">         int length() const { return m_endChar - m_startChar; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJavaScriptCoreruntimeFunctionConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/runtime/FunctionConstructor.cpp (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/runtime/FunctionConstructor.cpp        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/runtime/FunctionConstructor.cpp        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -66,75 +66,57 @@
</span><span class="cx">     return CallTypeHost;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static FunctionBodyNode* functionBody(ProgramNode* program)
+{
+    if (!program)
+        return 0;
+
+    StatementVector&amp; children = program-&gt;children();
+    if (children.size() != 1)
+        return 0;
+
+    ExprStatementNode* exprStatement = static_cast&lt;ExprStatementNode*&gt;(children[0].get()); 
+    ASSERT(exprStatement-&gt;isExprStatement());
+    if (!exprStatement || !exprStatement-&gt;isExprStatement())
+        return 0;
+
+    FuncExprNode* funcExpr = static_cast&lt;FuncExprNode*&gt;(exprStatement-&gt;expr());
+    ASSERT(funcExpr-&gt;isFuncExprNode());
+    if (!funcExpr || !funcExpr-&gt;isFuncExprNode())
+        return 0;
+
+    FunctionBodyNode* body = funcExpr-&gt;body();
+    ASSERT(body);
+    return body;
+}
+
</ins><span class="cx"> // ECMA 15.3.2 The Function Constructor
</span><span class="cx"> JSObject* constructFunction(ExecState* exec, const ArgList&amp; args, const Identifier&amp; functionName, const UString&amp; sourceURL, int lineNumber)
</span><span class="cx"> {
</span><del>-    UString p(&quot;&quot;);
-    UString body;
-    int argsSize = args.size();
-    if (argsSize == 0)
-        body = &quot;&quot;;
-    else if (argsSize == 1)
-        body = args.at(exec, 0)-&gt;toString(exec);
</del><ins>+    UString program;
+    if (args.isEmpty())
+        program = &quot;(function(){})&quot;;
+    else if (args.size() == 1)
+        program = &quot;(function(){&quot; + args.at(exec, 0)-&gt;toString(exec) + &quot;})&quot;;
</ins><span class="cx">     else {
</span><del>-        p = args.at(exec, 0)-&gt;toString(exec);
-        for (int k = 1; k &lt; argsSize - 1; k++)
-            p += &quot;,&quot; + args.at(exec, k)-&gt;toString(exec);
-        body = args.at(exec, argsSize - 1)-&gt;toString(exec);
</del><ins>+        program = &quot;(function(&quot; + args.at(exec, 0)-&gt;toString(exec);
+        for (size_t i = 1; i &lt; args.size() - 1; i++)
+            program += &quot;,&quot; + args.at(exec, i)-&gt;toString(exec);
+        program += &quot;){&quot; + args.at(exec, args.size() - 1)-&gt;toString(exec) + &quot;})&quot;;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // parse the source code
</del><span class="cx">     int errLine;
</span><span class="cx">     UString errMsg;
</span><del>-    SourceCode source = makeSource(body, sourceURL, lineNumber);
-    RefPtr&lt;FunctionBodyNode&gt; functionBody = exec-&gt;globalData().parser-&gt;parse&lt;FunctionBodyNode&gt;(exec, exec-&gt;dynamicGlobalObject()-&gt;debugger(), source, &amp;errLine, &amp;errMsg);
</del><ins>+    SourceCode source = makeSource(program, sourceURL, lineNumber);
+    RefPtr&lt;ProgramNode&gt; programNode = exec-&gt;globalData().parser-&gt;parse&lt;ProgramNode&gt;(exec, exec-&gt;dynamicGlobalObject()-&gt;debugger(), source, &amp;errLine, &amp;errMsg);
</ins><span class="cx"> 
</span><del>-    // No program node == syntax error - throw a syntax error
-    if (!functionBody)
-        // We can't return a Completion(Throw) here, so just set the exception
-        // and return it
</del><ins>+    FunctionBodyNode* body = functionBody(programNode.get());
+    if (!body)
</ins><span class="cx">         return throwError(exec, SyntaxError, errMsg, errLine, source.provider()-&gt;asID(), source.provider()-&gt;url());
</span><span class="cx"> 
</span><del>-    // parse parameter list. throw syntax error on illegal identifiers
-    int len = p.size();
-    const UChar* c = p.data();
-    int i = 0;
-    UString param;
-    Vector&lt;Identifier&gt; parameters;
-    while (i &lt; len) {
-        while (*c == ' ' &amp;&amp; i &lt; len)
-            c++, i++;
-        if (Lexer::isIdentStart(c[0])) {  // else error
-            param = UString(c, 1);
-            c++, i++;
-            while (i &lt; len &amp;&amp; (Lexer::isIdentPart(c[0]))) {
-                param.append(*c);
-                c++, i++;
-            }
-            while (i &lt; len &amp;&amp; *c == ' ')
-                c++, i++;
-            if (i == len) {
-                parameters.append(Identifier(exec, param));
-                break;
-            } else if (*c == ',') {
-                parameters.append(Identifier(exec, param));
-                c++, i++;
-                continue;
-            } // else error
-        }
-        return throwError(exec, SyntaxError, &quot;Syntax error in parameter list&quot;);
-    }
-    size_t count = parameters.size();
-    functionBody-&gt;finishParsing(parameters.releaseBuffer(), count);
-
</del><span class="cx">     JSGlobalObject* globalObject = exec-&gt;lexicalGlobalObject();
</span><span class="cx">     ScopeChain scopeChain(globalObject, globalObject-&gt;globalData(), exec-&gt;globalThisValue());
</span><del>-    JSFunction* function = new (exec) JSFunction(exec, functionName, functionBody.get(), scopeChain.node());
-
-    JSObject* prototype = constructEmptyObject(exec);
-    prototype-&gt;putDirect(exec-&gt;propertyNames().constructor, function, DontEnum);
-    function-&gt;putDirect(exec-&gt;propertyNames().prototype, prototype, DontDelete);
-    return function;
</del><ins>+    return new (exec) JSFunction(exec, functionName, body, scopeChain.node());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // ECMA 15.3.2 The Function Constructor
</span></span></pre></div>
<a id="trunkJavaScriptCoreruntimeIdentifierh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/runtime/Identifier.h (38634 => 38635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/runtime/Identifier.h        2008-11-20 23:23:16 UTC (rev 38634)
+++ trunk/JavaScriptCore/runtime/Identifier.h        2008-11-20 23:23:59 UTC (rev 38635)
</span><span class="lines">@@ -68,6 +68,7 @@
</span><span class="cx">         friend bool operator!=(const Identifier&amp;, const Identifier&amp;);
</span><span class="cx"> 
</span><span class="cx">         friend bool operator==(const Identifier&amp;, const char*);
</span><ins>+        friend bool operator!=(const Identifier&amp;, const char*);
</ins><span class="cx">     
</span><span class="cx">         static void remove(UString::Rep*);
</span><span class="cx"> 
</span><span class="lines">@@ -132,6 +133,11 @@
</span><span class="cx">         return Identifier::equal(a, b);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    inline bool operator!=(const Identifier&amp; a, const char* b)
+    {
+        return !Identifier::equal(a, b);
+    }
+
</ins><span class="cx">     IdentifierTable* createIdentifierTable();
</span><span class="cx">     void deleteIdentifierTable(IdentifierTable*);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>