Use unique_ptr instead of deleteAllValues in XPath
https://bugs.webkit.org/show_bug.cgi?id=121082

Reviewed by Anders Carlsson.

* dom/Attr.h: Made the namespaceURI function public so it can be called by
code in XPath. Since the class is FINAL, calls won't do virtual dispatch.

* xml/XPathExpression.cpp:
(WebCore::XPathExpression::XPathExpression): Added. Use std::move.
(WebCore::XPathExpression::createExpression): Use the new Parser::parseStatement
and more std::move.
(WebCore::XPathExpression::~XPathExpression): Removed now-unneeded delete.
* xml/XPathExpression.h: Removed unused create function. Use std::unique_ptr.

* xml/XPathExpressionNode.cpp:
(WebCore::XPath::Expression::evaluationContext): Use NeverDestroyed instead of
DEFINE_STATIC_LOCAL.
(WebCore::XPath::Expression::setSubexpressions): Added. Used to set all the
subexpressions at once rather than adding one at a time.

* xml/XPathExpressionNode.h: Use plain unsigned instead of unsigned long.
Eliminated the ParseNode class, used only by the parser to delete objects,
which we now do with %destructor. Made more functions protected. Fixed the
capitalization of the word "subexpression". Made m_subexpressions be a Vector
of std::unique_ptr.

* xml/XPathFunctions.cpp: Marked all the classes FINAL and all their virtual
functions OVERRIDE. Reduced some of the boilerplate.
(WebCore::XPath::Function::setArguments): Passed in the name so we don't have
to store the function names in all the function objects.
(WebCore::XPath::FunId::evaluate): Use std::move instead of Value::adopt.
(WebCore::XPath::FunLocalName::evaluate): Use emptyString instead of "".
(WebCore::XPath::FunNamespaceURI::evaluate): Ditto.
(WebCore::XPath::FunName::evaluate): Ditto.
(WebCore::XPath::FunSubstringBefore::evaluate): Ditto.
(WebCore::XPath::FunSubstringAfter::evaluate): Ditto.
(WebCore::XPath::FunSubstring::evaluate): Ditto.
(WebCore::XPath::FunLang::evaluate): Use Value(false) so we can make the
constructor that takes a boolean explicit.
(WebCore::XPath::FunFalse::evaluate): Ditto.
(WebCore::XPath::populateFunctionMap): Changed idiom slightly to match other
maps we set up.
(WebCore::XPath::Function::create): Refactored createFunction into three
member functions of this name.

* xml/XPathFunctions.h: Made all the Function members private or protected
except for Function::create.

* xml/XPathGrammar.y: Changed the parser to use a reference instead of
a pointer, and to pass the reference through to yylex as well. Break up
the union into pieces and add %destructor as needed to make sure everything
gets deallocated if parsing fails. Added a new top level rule "Top" so that
we would not try to set the parse result multiple times during parsing.
Call setParseResult instead of setting m_topExpr directly. Use std::unique_ptr
to adopt pointers from the union. Removed all the register/unregister calls
that used to be used to manage storage. Also changed the four different node
types to be separate tokens instead of using string matching at this level
for them.

* xml/XPathNodeSet.cpp:
(WebCore::XPath::NodeSet::sort): Removed const_cast since m_isSorted and
m_nodes are now both marked mutable. Also set m_isSorted after sorting; this
was an oversight that hurt performance before.
(WebCore::XPath::NodeSet::traversalSort): Ditto.
(WebCore::XPath::NodeSet::firstNode): Use nullptr.
(WebCore::XPath::NodeSet::anyNode): Ditto.

* xml/XPathNodeSet.h: Removed unneeded extra includes. Removed the
WTF_MAKE_FAST_ALLOCATED for NodeSet since we never allocate these on the heap.
Added a constructor that takes a single node. Deleted the swap function, since
we now move instead of swap. Deleted the append function that takes a raw Node*,
since calling the PassRefPtr<Node> overload does the same thing. Removed the
unused reverse function. Marked both m_isSorted and m_nodes mutable so the
sort function can be const.

* xml/XPathParser.cpp: Moved the Token struct in here instead of the header.
(WebCore::XPath::populateAxisNamesMap):Renamed to match our normal naming scheme,
and changed to use add instead of set, use WTF_ARRAY_LENGTH, and not use a typedef.
(WebCore::XPath::parseAxisName): Related style changes, including renaming to
better reflect the way this works with a boolean.
(WebCore::XPath::Parser::nextTokenInternal): Updated to call parseAxisName,
and to produce four separate tokens for the four node type functions.
(WebCore::XPath::Parser::nextToken): Renamed local variable.
(WebCore::XPath::Parser::Parser): Made this a real constructor that takes arguments
and initializes all the fields. Deleted the unneeded reset function.
(WebCore::XPath::Parser::lex): Changed to take an argument of an appropriate type
instead of casting from void*. Also changed the string code to leak a StringImpl,
which is now what the grammar code expects.
(WebCore::XPath::Parser::expandQualifiedName): Renamed from expandQName. Changed
to set m_sawNamespaceError instead of relying on code in the grammar to do it.
(WebCore::XPath::Parser::parseStatement): Removed most of the code in this function.
Changed to a much simpler model. Also made this a static member function so it
takes care of creating the parser itself and does not need to call reset. Also
changed return value to be a std::unique_ptr to make ownership more clear.

* xml/XPathParser.h: Added a declaration of YYSTYPE. Removed unneeded forward
declarations and moved Token into the cpp file. Deleted most public functions,
leaving only parseStatement, the entry point, and the three functions needed by
the grammar, lex, expandQualifiedName, and setParseResult.

* xml/XPathPath.cpp:
(WebCore::XPath::Filter::Filter): Move in the arguments instead of copying them.
(WebCore::XPath::Filter::evaluate): Updated for name and type changes.
(WebCore::XPath::LocationPath::LocationPath): Ditto.
(WebCore::XPath::LocationPath::evaluate): Ditto. Also use std::move instead of
Value::adopt and instead of swap.
(WebCore::XPath::LocationPath::appendStep): Changed to take ownership of a
unique_ptr.
(WebCore::XPath::LocationPath::prependStep): Ditto. Renamed from insertFirstStep.
(WebCore::XPath::Path::Path): Move in the arguments.

* xml/XPathPath.h: Removed unneeded includes. Changed arugument types to use
std::unique_ptr to pass ownership in. Added override to all virtual functions.
Changed data members to use std::unique_ptr.

* xml/XPathPredicate.cpp:
(WebCore::XPath::StringExpression::StringExpression): Use move.
(WebCore::XPath::Negative::Negative): Added.
(WebCore::XPath::Negative::evaluate): Updated for name changes.
(WebCore::XPath::NumericOp::NumericOp): Use move.
(WebCore::XPath::NumericOp::evaluate): Tweak formatting.
(WebCore::XPath::EqTestOp::EqTestOp): Use move.
(WebCore::XPath::EqTestOp::evaluate): Updated for name changes.
(WebCore::XPath::LogicalOp::LogicalOp): Use move.
(WebCore::XPath::LogicalOp::shortCircuitOn): Made shorter.
(WebCore::XPath::LogicalOp::evaluate): Updated for name changes.
(WebCore::XPath::Union::Union): Added.
(WebCore::XPath::Union::evaluate): Updated for name changes.
(WebCore::XPath::evaluatePredicate): Updated for name changes, to use
ASCIILiteral, and to be a free function that takes an expression.
(WebCore::XPath::predicateIsContextPositionSensitive): Added.
Replaces the Predicate::isContextPositionSensitive function.

* xml/XPathPredicate.h: Made all the classes FINAL and added a lot of OVERRIDE.
Added a constructor for Negative and Union. Got rid of the Predicate class and
instead provided two functions that operate on an Expression.

* xml/XPathStep.cpp:
(WebCore::XPath::Step::Step): Use move instea dof copying.
(WebCore::XPath::Step::~Step): Removed calls to deleteAllValues.
(WebCore::XPath::Step::optimize): Use move instead of swap and copy. Also
operate directly on the data members of the node test instead of using functions
that just return references to those data members.
(WebCore::XPath::optimizeStepPair): Use references instead of pointers, move
instead of swap, and early return instead of nested if statements.
(WebCore::XPath::Step::predicatesAreContextListInsensitive): Use references.
(WebCore::XPath::Step::evaluate): Use references instead of pointers and move
instead of swap.
(WebCore::XPath::nodeMatchesBasicTest): Use references instead of pointers and
more specific types when possible.
(WebCore::XPath::nodeMatches): Ditto.
(WebCore::XPath::Step::nodesInAxis): Use references instead of pointers. Added
braces to match style. Use words instead of letters for local variable names.

* xml/XPathStep.h: Make almost everything in NodeTest private since callers
just set these up and Step is what actually uses them. Changed the predicate
vectors to be vectors of Predicate instead of Predicate*, since a Predicate
is just a wrapper around a single std::unique_ptr<Expression>. Changed to use
move instead of copy when making a Step and to use references instead of pointers.

* xml/XPathValue.cpp: Use std::numeric_limits explicitly instead of using using.
Got rid of Value::adopt.
(WebCore::XPath::Value::toNodeSet): Use NeverDestroyed instead of DEFINE_STATE_LOCAL.
Updated for name changes.
(WebCore::XPath::Value::modifiableNodeSet): Ditto.
(WebCore::XPath::Value::toBoolean): Ditto.
(WebCore::XPath::Value::toNumber): Ditto.
(WebCore::XPath::Value::toString): Ditto. Use ASCIILiteral.

* xml/XPathValue.h: Moved ValueData class inside the Value class and renamed
it Value::Data. Removed fancy trick that avoids turning pointers into bool, and
just take the risk. Made many, but not all, of the Value constructors explicit
since we normally are explicit at call sites. Removed unneeded unsigned long
overload of the constructor. Changed the NodeSet version of the constructor to
use std::move and use that instead of AdoptTag.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@157205 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/xml/XPathFunctions.cpp b/Source/WebCore/xml/XPathFunctions.cpp
index 2d24e1a..bc59325 100644
--- a/Source/WebCore/xml/XPathFunctions.cpp
+++ b/Source/WebCore/xml/XPathFunctions.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2006, 2009, 2013 Apple Inc. All rights reserved.
  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
 #include "XPathUtil.h"
 #include "XPathValue.h"
 #include <wtf/MathExtras.h>
+#include <wtf/NeverDestroyed.h>
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
@@ -45,8 +46,7 @@
     return c == ' ' || c == '\n' || c == '\r' || c == '\t';
 }
 
-
-#define DEFINE_FUNCTION_CREATOR(Class) static Function* create##Class() { return new Class; }
+#define DEFINE_FUNCTION_CREATOR(Suffix) static std::unique_ptr<Function> createFunction##Suffix() { return std::make_unique<Fun##Suffix>(); }
 
 class Interval {
 public:
@@ -63,201 +63,193 @@
     int m_max;
 };
 
-struct FunctionRec {
-    typedef Function *(*FactoryFn)();
-    FactoryFn factoryFn;
-    Interval args;
-};
-
-static HashMap<String, FunctionRec>* functionMap;
-
-class FunLast : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunLast FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 public:
     FunLast() { setIsContextSizeSensitive(true); }
 };
 
-class FunPosition : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunPosition FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 public:
     FunPosition() { setIsContextPositionSensitive(true); }
 };
 
-class FunCount : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunCount FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 };
 
-class FunId : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NodeSetValue; }
+class FunId FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NodeSetValue; }
 };
 
-class FunLocalName : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunLocalName FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 public:
     FunLocalName() { setIsContextNodeSensitive(true); } // local-name() with no arguments uses context node. 
 };
 
-class FunNamespaceURI : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunNamespaceURI FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 public:
     FunNamespaceURI() { setIsContextNodeSensitive(true); } // namespace-uri() with no arguments uses context node. 
 };
 
-class FunName : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunName FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 public:
     FunName() { setIsContextNodeSensitive(true); } // name() with no arguments uses context node. 
 };
 
-class FunString : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunString FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 public:
     FunString() { setIsContextNodeSensitive(true); } // string() with no arguments uses context node. 
 };
 
-class FunConcat : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunConcat FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 };
 
-class FunStartsWith : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunStartsWith FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::BooleanValue; }
 };
 
-class FunContains : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunContains FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::BooleanValue; }
 };
 
-class FunSubstringBefore : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunSubstringBefore FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 };
 
-class FunSubstringAfter : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunSubstringAfter FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 };
 
-class FunSubstring : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunSubstring FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 };
 
-class FunStringLength : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunStringLength FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 public:
     FunStringLength() { setIsContextNodeSensitive(true); } // string-length() with no arguments uses context node. 
 };
 
-class FunNormalizeSpace : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunNormalizeSpace FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 public:
     FunNormalizeSpace() { setIsContextNodeSensitive(true); } // normalize-space() with no arguments uses context node. 
 };
 
-class FunTranslate : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::StringValue; }
+class FunTranslate FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::StringValue; }
 };
 
-class FunBoolean : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunBoolean FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::BooleanValue; }
 };
 
 class FunNot : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::BooleanValue; }
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::BooleanValue; }
 };
 
-class FunTrue : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunTrue FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::BooleanValue; }
 };
 
-class FunFalse : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunFalse FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::BooleanValue; }
 };
 
-class FunLang : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunLang FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::BooleanValue; }
 public:
     FunLang() { setIsContextNodeSensitive(true); } // lang() always works on context node. 
 };
 
-class FunNumber : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunNumber FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 public:
     FunNumber() { setIsContextNodeSensitive(true); } // number() with no arguments uses context node. 
 };
 
-class FunSum : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunSum FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 };
 
-class FunFloor : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunFloor FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 };
 
-class FunCeiling : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunCeiling FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 };
 
-class FunRound : public Function {
-    virtual Value evaluate() const;
-    virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunRound FINAL : public Function {
+    virtual Value evaluate() const OVERRIDE;
+    virtual Value::Type resultType() const OVERRIDE { return Value::NumberValue; }
 public:
     static double round(double);
 };
 
-DEFINE_FUNCTION_CREATOR(FunLast)
-DEFINE_FUNCTION_CREATOR(FunPosition)
-DEFINE_FUNCTION_CREATOR(FunCount)
-DEFINE_FUNCTION_CREATOR(FunId)
-DEFINE_FUNCTION_CREATOR(FunLocalName)
-DEFINE_FUNCTION_CREATOR(FunNamespaceURI)
-DEFINE_FUNCTION_CREATOR(FunName)
+DEFINE_FUNCTION_CREATOR(Last)
+DEFINE_FUNCTION_CREATOR(Position)
+DEFINE_FUNCTION_CREATOR(Count)
+DEFINE_FUNCTION_CREATOR(Id)
+DEFINE_FUNCTION_CREATOR(LocalName)
+DEFINE_FUNCTION_CREATOR(NamespaceURI)
+DEFINE_FUNCTION_CREATOR(Name)
 
-DEFINE_FUNCTION_CREATOR(FunString)
-DEFINE_FUNCTION_CREATOR(FunConcat)
-DEFINE_FUNCTION_CREATOR(FunStartsWith)
-DEFINE_FUNCTION_CREATOR(FunContains)
-DEFINE_FUNCTION_CREATOR(FunSubstringBefore)
-DEFINE_FUNCTION_CREATOR(FunSubstringAfter)
-DEFINE_FUNCTION_CREATOR(FunSubstring)
-DEFINE_FUNCTION_CREATOR(FunStringLength)
-DEFINE_FUNCTION_CREATOR(FunNormalizeSpace)
-DEFINE_FUNCTION_CREATOR(FunTranslate)
+DEFINE_FUNCTION_CREATOR(String)
+DEFINE_FUNCTION_CREATOR(Concat)
+DEFINE_FUNCTION_CREATOR(StartsWith)
+DEFINE_FUNCTION_CREATOR(Contains)
+DEFINE_FUNCTION_CREATOR(SubstringBefore)
+DEFINE_FUNCTION_CREATOR(SubstringAfter)
+DEFINE_FUNCTION_CREATOR(Substring)
+DEFINE_FUNCTION_CREATOR(StringLength)
+DEFINE_FUNCTION_CREATOR(NormalizeSpace)
+DEFINE_FUNCTION_CREATOR(Translate)
 
-DEFINE_FUNCTION_CREATOR(FunBoolean)
-DEFINE_FUNCTION_CREATOR(FunNot)
-DEFINE_FUNCTION_CREATOR(FunTrue)
-DEFINE_FUNCTION_CREATOR(FunFalse)
-DEFINE_FUNCTION_CREATOR(FunLang)
+DEFINE_FUNCTION_CREATOR(Boolean)
+DEFINE_FUNCTION_CREATOR(Not)
+DEFINE_FUNCTION_CREATOR(True)
+DEFINE_FUNCTION_CREATOR(False)
+DEFINE_FUNCTION_CREATOR(Lang)
 
-DEFINE_FUNCTION_CREATOR(FunNumber)
-DEFINE_FUNCTION_CREATOR(FunSum)
-DEFINE_FUNCTION_CREATOR(FunFloor)
-DEFINE_FUNCTION_CREATOR(FunCeiling)
-DEFINE_FUNCTION_CREATOR(FunRound)
+DEFINE_FUNCTION_CREATOR(Number)
+DEFINE_FUNCTION_CREATOR(Sum)
+DEFINE_FUNCTION_CREATOR(Floor)
+DEFINE_FUNCTION_CREATOR(Ceiling)
+DEFINE_FUNCTION_CREATOR(Round)
 
 #undef DEFINE_FUNCTION_CREATOR
 
@@ -290,17 +282,17 @@
     return value >= m_min && value <= m_max;
 }
 
-void Function::setArguments(const Vector<Expression*>& args)
+void Function::setArguments(const String& name, Vector<std::unique_ptr<Expression>> arguments)
 {
-    ASSERT(!subExpressionCount());
+    ASSERT(!subexpressionCount());
 
-    // Some functions use context node as implicit argument, so when explicit arguments are added, they may no longer be context node sensitive.
-    if (m_name != "lang" && !args.isEmpty())
+    // Functions that use the context node as an implicit argument are context node sensitive when they
+    // have no arguments, but when explicit arguments are added, they are no longer context node sensitive.
+    // As of this writing, the only exception to this is the "lang" function.
+    if (name != "lang" && !arguments.isEmpty())
         setIsContextNodeSensitive(false);
 
-    Vector<Expression*>::const_iterator end = args.end();
-    for (Vector<Expression*>::const_iterator it = args.begin(); it != end; ++it)
-        addSubExpression(*it);
+    setSubexpressions(std::move(arguments));
 }
 
 Value FunLast::evaluate() const
@@ -358,7 +350,7 @@
     
     result.markSorted(false);
     
-    return Value(result, Value::adopt);
+    return Value(std::move(result));
 }
 
 static inline String expandedNameLocalPart(Node* node)
@@ -381,10 +373,10 @@
     if (argumentCount() > 0) {
         Value a = argument(0).evaluate();
         if (!a.isNodeSet())
-            return "";
+            return emptyString();
 
         Node* node = a.toNodeSet().firstNode();
-        return node ? expandedNameLocalPart(node) : "";
+        return node ? expandedNameLocalPart(node) : emptyString();
     }
 
     return expandedNameLocalPart(evaluationContext().node.get());
@@ -395,10 +387,10 @@
     if (argumentCount() > 0) {
         Value a = argument(0).evaluate();
         if (!a.isNodeSet())
-            return "";
+            return emptyString();
 
         Node* node = a.toNodeSet().firstNode();
-        return node ? node->namespaceURI().string() : "";
+        return node ? node->namespaceURI().string() : emptyString();
     }
 
     return evaluationContext().node->namespaceURI().string();
@@ -409,10 +401,10 @@
     if (argumentCount() > 0) {
         Value a = argument(0).evaluate();
         if (!a.isNodeSet())
-            return "";
+            return emptyString();
 
         Node* node = a.toNodeSet().firstNode();
-        return node ? expandedName(node) : "";
+        return node ? expandedName(node) : emptyString();
     }
 
     return expandedName(evaluationContext().node.get());
@@ -473,12 +465,12 @@
     String s2 = argument(1).evaluate().toString();
 
     if (s2.isEmpty())
-        return "";
+        return emptyString();
 
     size_t i = s1.find(s2);
 
     if (i == notFound)
-        return "";
+        return emptyString();
 
     return s1.left(i);
 }
@@ -490,7 +482,7 @@
 
     size_t i = s1.find(s2);
     if (i == notFound)
-        return "";
+        return emptyString();
 
     return s1.substring(i + s2.length());
 }
@@ -500,25 +492,25 @@
     String s = argument(0).evaluate().toString();
     double doublePos = argument(1).evaluate().toNumber();
     if (std::isnan(doublePos))
-        return "";
+        return emptyString();
     long pos = static_cast<long>(FunRound::round(doublePos));
     bool haveLength = argumentCount() == 3;
     long len = -1;
     if (haveLength) {
         double doubleLen = argument(2).evaluate().toNumber();
         if (std::isnan(doubleLen))
-            return "";
+            return emptyString();
         len = static_cast<long>(FunRound::round(doubleLen));
     }
 
     if (pos > long(s.length())) 
-        return "";
+        return emptyString();
 
     if (pos < 1) {
         if (haveLength) {
             len -= 1 - pos;
             if (len < 1)
-                return "";
+                return emptyString();
         }
         pos = 1;
     }
@@ -669,62 +661,78 @@
     return round(argument(0).evaluate().toNumber());
 }
 
-struct FunctionMapping {
-    const char* name;
-    FunctionRec function;
+struct FunctionMapValue {
+    std::unique_ptr<Function> (*creationFunction)();
+    Interval argumentCountInterval;
 };
 
-static void createFunctionMap()
+static void populateFunctionMap(HashMap<String, FunctionMapValue>& functionMap)
 {
-    static const FunctionMapping functions[] = {
-        { "boolean", { &createFunBoolean, 1 } },
-        { "ceiling", { &createFunCeiling, 1 } },
-        { "concat", { &createFunConcat, Interval(2, Interval::Inf) } },
-        { "contains", { &createFunContains, 2 } },
-        { "count", { &createFunCount, 1 } },
-        { "false", { &createFunFalse, 0 } },
-        { "floor", { &createFunFloor, 1 } },
-        { "id", { &createFunId, 1 } },
-        { "lang", { &createFunLang, 1 } },
-        { "last", { &createFunLast, 0 } },
-        { "local-name", { &createFunLocalName, Interval(0, 1) } },
-        { "name", { &createFunName, Interval(0, 1) } },
-        { "namespace-uri", { &createFunNamespaceURI, Interval(0, 1) } },
-        { "normalize-space", { &createFunNormalizeSpace, Interval(0, 1) } },
-        { "not", { &createFunNot, 1 } },
-        { "number", { &createFunNumber, Interval(0, 1) } },
-        { "position", { &createFunPosition, 0 } },
-        { "round", { &createFunRound, 1 } },
-        { "starts-with", { &createFunStartsWith, 2 } },
-        { "string", { &createFunString, Interval(0, 1) } },
-        { "string-length", { &createFunStringLength, Interval(0, 1) } },
-        { "substring", { &createFunSubstring, Interval(2, 3) } },
-        { "substring-after", { &createFunSubstringAfter, 2 } },
-        { "substring-before", { &createFunSubstringBefore, 2 } },
-        { "sum", { &createFunSum, 1 } },
-        { "translate", { &createFunTranslate, 3 } },
-        { "true", { &createFunTrue, 0 } },
+    struct FunctionMapping {
+        const char* name;
+        FunctionMapValue function;
     };
 
-    functionMap = new HashMap<String, FunctionRec>;
+    static const FunctionMapping functions[] = {
+        { "boolean", { createFunctionBoolean, 1 } },
+        { "ceiling", { createFunctionCeiling, 1 } },
+        { "concat", { createFunctionConcat, Interval(2, Interval::Inf) } },
+        { "contains", { createFunctionContains, 2 } },
+        { "count", { createFunctionCount, 1 } },
+        { "false", { createFunctionFalse, 0 } },
+        { "floor", { createFunctionFloor, 1 } },
+        { "id", { createFunctionId, 1 } },
+        { "lang", { createFunctionLang, 1 } },
+        { "last", { createFunctionLast, 0 } },
+        { "local-name", { createFunctionLocalName, Interval(0, 1) } },
+        { "name", { createFunctionName, Interval(0, 1) } },
+        { "namespace-uri", { createFunctionNamespaceURI, Interval(0, 1) } },
+        { "normalize-space", { createFunctionNormalizeSpace, Interval(0, 1) } },
+        { "not", { createFunctionNot, 1 } },
+        { "number", { createFunctionNumber, Interval(0, 1) } },
+        { "position", { createFunctionPosition, 0 } },
+        { "round", { createFunctionRound, 1 } },
+        { "starts-with", { createFunctionStartsWith, 2 } },
+        { "string", { createFunctionString, Interval(0, 1) } },
+        { "string-length", { createFunctionStringLength, Interval(0, 1) } },
+        { "substring", { createFunctionSubstring, Interval(2, 3) } },
+        { "substring-after", { createFunctionSubstringAfter, 2 } },
+        { "substring-before", { createFunctionSubstringBefore, 2 } },
+        { "sum", { createFunctionSum, 1 } },
+        { "translate", { createFunctionTranslate, 3 } },
+        { "true", { createFunctionTrue, 0 } },
+    };
+
     for (size_t i = 0; i < WTF_ARRAY_LENGTH(functions); ++i)
-        functionMap->set(functions[i].name, functions[i].function);
+        functionMap.add(functions[i].name, functions[i].function);
 }
 
-Function* createFunction(const String& name, const Vector<Expression*>& args)
+std::unique_ptr<Function> Function::create(const String& name, unsigned numArguments)
 {
-    if (!functionMap)
-        createFunctionMap();
+    static NeverDestroyed<HashMap<String, FunctionMapValue>> functionMap;
+    if (functionMap.get().isEmpty())
+        populateFunctionMap(functionMap);
 
-    HashMap<String, FunctionRec>::iterator functionMapIter = functionMap->find(name);
-    FunctionRec* functionRec = 0;
+    auto it = functionMap.get().find(name);
+    if (it == functionMap.get().end())
+        return nullptr;
 
-    if (functionMapIter == functionMap->end() || !(functionRec = &functionMapIter->value)->args.contains(args.size()))
-        return 0;
+    if (!it->value.argumentCountInterval.contains(numArguments))
+        return nullptr;
 
-    Function* function = functionRec->factoryFn();
-    function->setArguments(args);
-    function->setName(name);
+    return it->value.creationFunction();
+}
+
+std::unique_ptr<Function> Function::create(const String& name)
+{
+    return create(name, 0);
+}
+
+std::unique_ptr<Function> Function::create(const String& name, Vector<std::unique_ptr<Expression>> arguments)
+{
+    std::unique_ptr<Function> function = create(name, arguments.size());
+    if (function)
+        function->setArguments(name, std::move(arguments));
     return function;
 }