A little bit of function call cleanup
https://bugs.webkit.org/show_bug.cgi?id=72314

Reviewed by Oliver Hunt.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitCall): Renamed callFrame to registerOffset
because this value doesn't give you the offset of the callee's call frame.

(JSC::BytecodeGenerator::emitReturn): Tightened to use equality instead
of greater-than. Removed comment since its reasoning was wrong.
        
(JSC::BytecodeGenerator::emitConstruct): Updated for rename mentioned above.

(JSC::BytecodeGenerator::isArgumentNumber): Provided a more precise way
to ask this question, giving the bytecode generator more freedom to change
internal implementation details.
        
* bytecompiler/BytecodeGenerator.h: Reduced default vector capacity because
16 was overkill.
(JSC::CallArguments::registerOffset): Updated for rename mentioned above.

* bytecompiler/NodesCodegen.cpp:
(JSC::CallArguments::CallArguments):
(JSC::CallArguments::newArgument): Factored out argument allocation into
a helper function, so I can change it later.

(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::FunctionBodyNode::emitBytecode): Use helper function mentioned above.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@100200 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index d282ebf..3d667b6 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,35 @@
+2011-11-14  Geoffrey Garen  <ggaren@apple.com>
+
+        A little bit of function call cleanup
+        https://bugs.webkit.org/show_bug.cgi?id=72314
+
+        Reviewed by Oliver Hunt.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitCall): Renamed callFrame to registerOffset
+        because this value doesn't give you the offset of the callee's call frame.
+
+        (JSC::BytecodeGenerator::emitReturn): Tightened to use equality instead
+        of greater-than. Removed comment since its reasoning was wrong.
+        
+        (JSC::BytecodeGenerator::emitConstruct): Updated for rename mentioned above.
+
+        (JSC::BytecodeGenerator::isArgumentNumber): Provided a more precise way
+        to ask this question, giving the bytecode generator more freedom to change
+        internal implementation details.
+        
+        * bytecompiler/BytecodeGenerator.h: Reduced default vector capacity because
+        16 was overkill.
+        (JSC::CallArguments::registerOffset): Updated for rename mentioned above.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::CallArguments::CallArguments):
+        (JSC::CallArguments::newArgument): Factored out argument allocation into
+        a helper function, so I can change it later.
+
+        (JSC::CallFunctionCallDotNode::emitBytecode):
+        (JSC::FunctionBodyNode::emitBytecode): Use helper function mentioned above.
+
 2011-11-14  Tony Chang  <tony@chromium.org>
 
         Remove the CSS3_FLEXBOX compile time flag and enable on all ports
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 3171415..fc72233 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -1821,7 +1821,7 @@
     emitOpcode(opcodeID);
     instructions().append(func->index()); // func
     instructions().append(callArguments.count()); // argCount
-    instructions().append(callArguments.callFrame()); // registerOffset
+    instructions().append(callArguments.registerOffset()); // registerOffset
     if (dst != ignoredResult()) {
         emitOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
@@ -1868,8 +1868,7 @@
         emitOpcode(op_tear_off_activation);
         instructions().append(m_activationRegister->index());
         instructions().append(m_codeBlock->argumentsRegister());
-    } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1
-               && !m_codeBlock->isStrictMode()) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
+    } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters != 1 && !m_codeBlock->isStrictMode()) {
         emitOpcode(op_tear_off_arguments);
         instructions().append(m_codeBlock->argumentsRegister());
     }
@@ -1922,7 +1921,7 @@
     emitOpcode(op_construct);
     instructions().append(func->index()); // func
     instructions().append(callArguments.count()); // argCount
-    instructions().append(callArguments.callFrame()); // registerOffset
+    instructions().append(callArguments.registerOffset()); // registerOffset
     if (dst != ignoredResult()) {
         emitOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
@@ -2358,14 +2357,12 @@
     m_codeBlock->setIsNumericCompareFunction(isNumericCompareFunction);
 }
 
-int BytecodeGenerator::argumentNumberFor(const Identifier& ident)
+bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
 {
-    int parameterCount = m_parameters.size(); // includes 'this'
     RegisterID* registerID = registerFor(ident);
-    if (!registerID)
-        return 0;
-    int index = registerID->index() + RegisterFile::CallFrameHeaderSize + parameterCount;
-    return (index > 0 && index < parameterCount) ? index : 0;
+    if (!registerID || registerID->index() >= 0)
+         return 0;
+    return registerID->index() - m_thisRegister.index() - 1 == argumentNumber;
 }
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 19433f4..274fa3d 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -55,15 +55,17 @@
 
         RegisterID* thisRegister() { return m_argv[0].get(); }
         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
-        unsigned callFrame() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize; }
+        unsigned registerOffset() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize; }
         unsigned count() { return m_argv.size(); }
         RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
 
     private:
+        void newArgument(BytecodeGenerator&);
+
         RefPtr<RegisterID> m_profileHookRegister;
         ArgumentsNode* m_argumentsNode;
-        Vector<RefPtr<RegisterID>, 16> m_argv;
+        Vector<RefPtr<RegisterID>, 8> m_argv;
     };
 
     struct FinallyContext {
@@ -110,8 +112,7 @@
         // require explicit reference counting.
         RegisterID* registerFor(const Identifier&);
 
-        // Returns the agument number if this is an argument, or 0 if not.
-        int argumentNumberFor(const Identifier&);
+        bool isArgumentNumber(const Identifier&, int);
 
         void setIsNumericCompareFunction(bool isNumericCompareFunction);
 
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index 72ee3de..fe8efcf 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -313,19 +313,24 @@
     return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
-CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
+inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
     : m_argumentsNode(argumentsNode)
 {
     if (generator.shouldEmitProfileHooks())
         m_profileHookRegister = generator.newTemporary();
-    m_argv.append(generator.newTemporary());
-    if (argumentsNode) {
-        for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) {
-            m_argv.append(generator.newTemporary());
-            // op_call requires the arguments to be a sequential range of registers
-            ASSERT(m_argv[m_argv.size() - 1]->index() == m_argv[m_argv.size() - 2]->index() + 1);
-        }
-    }
+
+    newArgument(generator); // 'this' register.
+    if (!argumentsNode)
+        return;
+    for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
+        newArgument(generator);
+}
+
+inline void CallArguments::newArgument(BytecodeGenerator& generator)
+{
+    RefPtr<RegisterID> tmp = generator.newTemporary();
+    ASSERT(m_argv.isEmpty() || tmp->index() == m_argv.last()->index() + 1); // Calling convention assumes that all arguments are contiguous.
+    m_argv.append(tmp.release());
 }
 
 // ------------------------------ EvalFunctionCallNode ----------------------------------
@@ -425,7 +430,6 @@
             generator.emitJump(end.get());
 
             m_args->m_listNode = oldList;
-
         } else {
             RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
             CallArguments callArguments(generator, m_args);
@@ -2031,9 +2035,12 @@
         if (returnValueExpression && returnValueExpression->isSubtract()) {
             ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
             ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
-            if (lhsExpression->isResolveNode() && rhsExpression->isResolveNode()) {
-                generator.setIsNumericCompareFunction(generator.argumentNumberFor(static_cast<ResolveNode*>(lhsExpression)->identifier()) == 1
-                    && generator.argumentNumberFor(static_cast<ResolveNode*>(rhsExpression)->identifier()) == 2);
+            if (lhsExpression->isResolveNode()
+                && rhsExpression->isResolveNode()
+                && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
+                && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
+                
+                generator.setIsNumericCompareFunction(true);
             }
         }
     }