Reviewed by Darin.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 23 Apr 2007 10:28:10 +0000 (10:28 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 23 Apr 2007 10:28:10 +0000 (10:28 +0000)
        - shrink FunctionImp / DeclaredFunctionImp by 4 bytes, by moving parameter list to function body

        I reconciled this with a similar change in KDE kjs by Maks Orlovich <maksim@kde.org>.

        * kjs/function.cpp:
        (KJS::FunctionImp::callAsFunction):
        (KJS::FunctionImp::passInParameters):
        (KJS::FunctionImp::lengthGetter):
        (KJS::FunctionImp::getParameterName):
        * kjs/function.h:
        * kjs/function_object.cpp:
        (FunctionProtoFunc::callAsFunction):
        (FunctionObjectImp::construct):
        * kjs/nodes.cpp:
        (FunctionBodyNode::addParam):
        (FunctionBodyNode::paramString):
        (FuncDeclNode::addParams):
        (FuncDeclNode::processFuncDecl):
        (FuncExprNode::addParams):
        (FuncExprNode::evaluate):
        * kjs/nodes.h:
        (KJS::Parameter::Parameter):
        (KJS::FunctionBodyNode::numParams):
        (KJS::FunctionBodyNode::paramName):
        (KJS::FunctionBodyNode::parameters):
        (KJS::FuncExprNode::FuncExprNode):
        (KJS::FuncDeclNode::FuncDeclNode):
        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Disable 64-bit warnings because
        they handle size_t badly.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@21032 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
JavaScriptCore/kjs/function.cpp
JavaScriptCore/kjs/function.h
JavaScriptCore/kjs/function_object.cpp
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h

index 8727df1..d3aa42e 100644 (file)
@@ -1,4 +1,38 @@
 2007-04-23  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+        
+        - shrink FunctionImp / DeclaredFunctionImp by 4 bytes, by moving parameter list to function body
+        
+        I reconciled this with a similar change in KDE kjs by Maks Orlovich <maksim@kde.org>.
+
+        * kjs/function.cpp:
+        (KJS::FunctionImp::callAsFunction):
+        (KJS::FunctionImp::passInParameters):
+        (KJS::FunctionImp::lengthGetter):
+        (KJS::FunctionImp::getParameterName):
+        * kjs/function.h:
+        * kjs/function_object.cpp:
+        (FunctionProtoFunc::callAsFunction):
+        (FunctionObjectImp::construct):
+        * kjs/nodes.cpp:
+        (FunctionBodyNode::addParam):
+        (FunctionBodyNode::paramString):
+        (FuncDeclNode::addParams):
+        (FuncDeclNode::processFuncDecl):
+        (FuncExprNode::addParams):
+        (FuncExprNode::evaluate):
+        * kjs/nodes.h:
+        (KJS::Parameter::Parameter):
+        (KJS::FunctionBodyNode::numParams):
+        (KJS::FunctionBodyNode::paramName):
+        (KJS::FunctionBodyNode::parameters):
+        (KJS::FuncExprNode::FuncExprNode):
+        (KJS::FuncDeclNode::FuncDeclNode):
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Disable 64-bit warnings because
+        they handle size_t badly.
+
+2007-04-23  Maciej Stachowiak  <mjs@apple.com>
  
         Reviewed by Darin.
 
index e7b700c..ddd297a 100644 (file)
@@ -56,7 +56,7 @@
                                UsePrecompiledHeader="0"
                                WarningLevel="4"
                                WarnAsError="true"
-                               Detect64BitPortabilityProblems="true"
+                               Detect64BitPortabilityProblems="false"
                                DebugInformationFormat="4"
                                DisableSpecificWarnings="4127;4355;4510;4512;4610;4706;4996"
                                ForcedIncludeFiles=""
index f797713..60a2cc4 100644 (file)
@@ -51,13 +51,6 @@ namespace KJS {
 
 const ClassInfo FunctionImp::info = {"Function", &InternalFunctionImp::info, 0, 0};
 
-  class Parameter {
-  public:
-    Parameter() {};
-    Parameter(const Identifier& n) : name(n) { }
-    Identifier name;
-  };
-
 FunctionImp::FunctionImp(ExecState* exec, const Identifier& n, FunctionBodyNode* b)
   : InternalFunctionImp(static_cast<FunctionPrototype*>
                         (exec->lexicalInterpreter()->builtinFunctionPrototype()), n)
@@ -88,7 +81,7 @@ JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const L
   ctx.setExecState(&newExec);
 
   // assign user supplied arguments to parameters
-  processParameters(&newExec, args);
+  passInParameters(&newExec, args);
   // add variable declarations (initialized to undefined)
   processVarDecls(&newExec);
 
@@ -152,36 +145,10 @@ JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const L
     return jsUndefined();
 }
 
-void FunctionImp::addParameter(const Identifier& n)
-{
-    if (!parameters)
-        parameters.set(new Vector<Parameter>);
-
-    parameters->append(Parameter(n));
-}
-
-UString FunctionImp::parameterString() const
-{
-    UString s;
-
-    if (!parameters)
-        return s;
-
-    for (size_t i = 0; i < parameters->size(); ++i) {
-        if (!s.isEmpty())
-            s += ", ";
-        s += parameters->at(i).name.ustring();
-    }
-
-    return s;
-}
-
-
 // ECMA 10.1.3q
-void FunctionImp::processParameters(ExecState* exec, const List& args)
+inline void FunctionImp::passInParameters(ExecState* exec, const List& args)
 {
-    if (!parameters)
-        return;
+    Vector<Parameter>& parameters = body->parameters();
 
     JSObject* variable = exec->context()->variableObject();
 
@@ -191,26 +158,14 @@ void FunctionImp::processParameters(ExecState* exec, const List& args)
           name().isEmpty() ? "(internal)" : name().ascii());
 #endif
 
-    ListIterator it = args.begin();
-
-    JSValue * v = *it;
-    for (size_t i = 0; i < parameters->size(); ++i) {
-      if (it != args.end()) {
-#ifdef KJS_VERBOSE
-        fprintf(stderr, "setting parameter %s ", parameters->at(i).name.ascii());
-        printInfo(exec, "to", *it);
-#endif
-        variable->put(exec, parameters->at(i).name, v);
-        v = ++it;
-      } else
-        variable->put(exec, parameters->at(i).name, jsUndefined());
-  }
+    size_t size = parameters.size();
+    for (size_t i = 0; i < size; ++i) {
 #ifdef KJS_VERBOSE
-  else {
-    for (int i = 0; i < args.size(); ++i)
-      printInfo(exec,"setting argument", args[i]);
-  }
+      fprintf(stderr, "setting parameter %s ", parameters->at(i).name.ascii());
+      printInfo(exec, "to", args[i]);
 #endif
+      variable->put(exec, parameters[i].name, args[i]);
+    }
 }
 
 void FunctionImp::processVarDecls(ExecState*)
@@ -256,7 +211,7 @@ JSValue* FunctionImp::callerGetter(ExecState* exec, JSObject*, const Identifier&
 JSValue* FunctionImp::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
 {
     FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
-    return jsNumber(thisObj->parameters ? thisObj->parameters->size() : 0);
+    return jsNumber(thisObj->body->numParams());
 }
 
 bool FunctionImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -304,17 +259,17 @@ bool FunctionImp::deleteProperty(ExecState* exec, const Identifier& propertyName
  */
 Identifier FunctionImp::getParameterName(int index)
 {
-    if (!parameters)
-        return CommonIdentifiers::shared()->nullIdentifier;
+    Vector<Parameter>& parameters = body->parameters();
 
-    if (static_cast<size_t>(index) >= parameters->size())
+    if (static_cast<size_t>(index) >= body->numParams())
         return CommonIdentifiers::shared()->nullIdentifier;
   
-    Identifier name = parameters->at(index).name;
+    Identifier name = parameters[index].name;
 
     // Are there any subsequent parameters with the same name?
-    for (size_t i = index + 1; i < parameters->size(); ++i)
-        if (parameters->at(i).name == name)
+    size_t size = parameters.size();
+    for (size_t i = index + 1; i < size; ++i)
+        if (parameters[i].name == name)
             return CommonIdentifiers::shared()->nullIdentifier;
 
     return name;
index bb37283..a578cfb 100644 (file)
@@ -32,7 +32,6 @@ namespace KJS {
 
   class ActivationImp;
   class FunctionBodyNode;
-  class Parameter;
 
   /**
    * @short Implementation class for internal Functions.
@@ -49,10 +48,9 @@ namespace KJS {
 
     virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List& args);
 
-    void addParameter(const Identifier& n);
+    // Note: unlike body->paramName, this returns Identifier::null for parameters 
+    // that will never get set, due to later param having the same name
     Identifier getParameterName(int index);
-    // parameters in string representation, e.g. (a, b, c)
-    UString parameterString() const;
     virtual CodeType codeType() const = 0;
 
     virtual Completion execute(ExecState*) = 0;
@@ -92,8 +90,6 @@ namespace KJS {
     void setScope(const ScopeChain& s) { _scope = s; }
 
     virtual void mark();
-  protected:
-    OwnPtr<Vector<Parameter> > parameters;
 
   private:
     ScopeChain _scope;
@@ -102,7 +98,7 @@ namespace KJS {
     static JSValue* callerGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
     static JSValue* lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
 
-    void processParameters(ExecState*, const List&);
+    void passInParameters(ExecState*, const List&);
     virtual void processVarDecls(ExecState*);
   };
 
index f10f399..47d74c6 100644 (file)
@@ -83,7 +83,7 @@ JSValue* FunctionProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, c
     if (thisObj->inherits(&DeclaredFunctionImp::info)) {
         DeclaredFunctionImp *fi = static_cast<DeclaredFunctionImp*>(thisObj);
         return jsString("function " + fi->functionName().ustring() + "(" +
-                        fi->parameterString() + ") " + fi->body->toString());
+                        fi->body->paramString() + ") " + fi->body->toString());
      } else if (thisObj->inherits(&InternalFunctionImp::info) &&
                 !static_cast<InternalFunctionImp*>(thisObj)->functionName().isNull()) {
        result = jsString("\nfunction " + static_cast<InternalFunctionImp*>(thisObj)->functionName().ustring() + "() {\n"
@@ -228,11 +228,11 @@ JSObject* FunctionObjectImp::construct(ExecState* exec, const List& args, const
           while (i < len && *c == ' ')
               c++, i++;
           if (i == len) {
-              fimp->addParameter(Identifier(param));
+              bodyNode->addParam(Identifier(param));
               params++;
               break;
           } else if (*c == ',') {
-              fimp->addParameter(Identifier(param));
+              bodyNode->addParam(Identifier(param));
               params++;
               c++, i++;
               continue;
index 9299148..ede2949 100644 (file)
@@ -2392,8 +2392,33 @@ void FunctionBodyNode::processFuncDecl(ExecState *exec)
         source->processFuncDecl(exec);
 }
 
+void FunctionBodyNode::addParam(const Identifier& ident)
+{
+  m_parameters.append(Parameter(ident));
+}
+
+UString FunctionBodyNode::paramString() const
+{
+  UString s("");
+  size_t count = numParams();
+  for (size_t pos = 0; pos < count; ++pos) {
+    if (!s.isEmpty())
+        s += ", ";
+    s += paramName(pos).ustring();
+  }
+
+  return s;
+}
+
+
 // ------------------------------ FuncDeclNode ---------------------------------
 
+void FuncDeclNode::addParams() 
+{
+  for (ParameterNode *p = param.get(); p != 0L; p = p->nextParam())
+    body->addParam(p->ident());
+}
+
 // ECMA 13
 void FuncDeclNode::processFuncDecl(ExecState *exec)
 {
@@ -2406,11 +2431,7 @@ void FuncDeclNode::processFuncDecl(ExecState *exec)
   proto->put(exec, exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
   func->put(exec, exec->propertyNames().prototype, proto, Internal|DontDelete);
 
-  int plen = 0;
-  for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
-    func->addParameter(p->ident());
-
-  func->put(exec, exec->propertyNames().length, jsNumber(plen), ReadOnly|DontDelete|DontEnum);
+  func->put(exec, exec->propertyNames().length, jsNumber(body->numParams()), ReadOnly|DontDelete|DontEnum);
 
   // ECMA 10.2.2
   context->variableObject()->put(exec, ident, func, Internal | (context->codeType() == EvalCode ? 0 : DontDelete));
@@ -2435,6 +2456,12 @@ Completion FuncDeclNode::execute(ExecState *)
 // ------------------------------ FuncExprNode ---------------------------------
 
 // ECMA 13
+void FuncExprNode::addParams()
+{
+  for (ParameterNode *p = param.get(); p != 0L; p = p->nextParam())
+    body->addParam(p->ident());
+}
+
 JSValue *FuncExprNode::evaluate(ExecState *exec)
 {
   Context *context = exec->context();
@@ -2454,10 +2481,6 @@ JSValue *FuncExprNode::evaluate(ExecState *exec)
   proto->put(exec, exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
   func->put(exec, exec->propertyNames().prototype, proto, Internal | DontDelete);
 
-  int plen = 0;
-  for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
-    func->addParameter(p->ident());
-
   if (named) {
     functionScopeObject->put(exec, ident, func, Internal | ReadOnly | (context->codeType() == EvalCode ? 0 : DontDelete));
     context->popScope();
index 97e0c56..84c1271 100644 (file)
@@ -28,6 +28,7 @@
 #include "Parser.h"
 #include "internal.h"
 #include <wtf/ListRefPtr.h>
+#include <wtf/Vector.h>
 
 namespace KJS {
 
@@ -1003,6 +1004,13 @@ namespace KJS {
     ListRefPtr<ParameterNode> next;
   };
 
+  class Parameter {
+  public:
+    Parameter() { }
+    Parameter(const Identifier& n) : name(n) { }
+    Identifier name;
+  };
+
   // inherited by ProgramNode
   class FunctionBodyNode : public BlockNode {
   public:
@@ -1010,18 +1018,26 @@ namespace KJS {
     virtual void processFuncDecl(ExecState*);
     int sourceId() { return m_sourceId; }
     const UString& sourceURL() { return m_sourceURL; }
+
+    void addParam(const Identifier& ident);
+    size_t numParams() const { return m_parameters.size(); }
+    Identifier paramName(size_t pos) const { return m_parameters[pos].name; }
+    UString paramString() const;
+    Vector<Parameter>& parameters() { return m_parameters; }
   private:
     UString m_sourceURL;
     int m_sourceId;
+    Vector<Parameter> m_parameters;
   };
 
   class FuncExprNode : public Node {
   public:
     FuncExprNode(const Identifier &i, FunctionBodyNode *b, ParameterNode *p = 0)
-      : ident(i), param(p ? p->next.release() : 0), body(b) { if (p) { Parser::removeNodeCycle(param.get()); } }
+      : ident(i), param(p ? p->next.release() : 0), body(b) { if (p) { Parser::removeNodeCycle(param.get()); } addParams(); }
     virtual JSValue *evaluate(ExecState*);
     virtual void streamTo(SourceStream&) const;
   private:
+    void addParams();
     // Used for streamTo
     friend class PropertyNode;
     Identifier ident;
@@ -1032,13 +1048,14 @@ namespace KJS {
   class FuncDeclNode : public StatementNode {
   public:
     FuncDeclNode(const Identifier &i, FunctionBodyNode *b)
-      : ident(i), body(b) { }
+      : ident(i), body(b) { addParams(); }
     FuncDeclNode(const Identifier &i, ParameterNode *p, FunctionBodyNode *b)
-      : ident(i), param(p->next.release()), body(b) { Parser::removeNodeCycle(param.get()); }
+      : ident(i), param(p->next.release()), body(b) { Parser::removeNodeCycle(param.get()); addParams(); }
     virtual Completion execute(ExecState*);
     virtual void processFuncDecl(ExecState*);
     virtual void streamTo(SourceStream&) const;
   private:
+    void addParams();
     Identifier ident;
     RefPtr<ParameterNode> param;
     RefPtr<FunctionBodyNode> body;