JSC: FunctionParameters are memory hungry.
<http://webkit.org/b/108033>
<rdar://problem/13094803>
Reviewed by Sam Weinig.
Instead of inheriting from Vector<Identifier>, make FunctionParameters a simple fixed-size array
with a custom-allocating create() function. Removes one step of indirection and cuts memory usage
roughly in half.
2.73 MB progression on Membuster3.
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedFunctionExecutable::paramString):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* parser/Nodes.cpp:
(JSC::FunctionParameters::create):
(JSC::FunctionParameters::FunctionParameters):
(JSC::FunctionParameters::~FunctionParameters):
* parser/Nodes.h:
(FunctionParameters):
(JSC::FunctionParameters::size):
(JSC::FunctionParameters::at):
(JSC::FunctionParameters::identifiers):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@140947 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 1aba86b..32d9d01 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,5 +1,33 @@
2013-01-27 Andreas Kling <akling@apple.com>
+ JSC: FunctionParameters are memory hungry.
+ <http://webkit.org/b/108033>
+ <rdar://problem/13094803>
+
+ Reviewed by Sam Weinig.
+
+ Instead of inheriting from Vector<Identifier>, make FunctionParameters a simple fixed-size array
+ with a custom-allocating create() function. Removes one step of indirection and cuts memory usage
+ roughly in half.
+
+ 2.73 MB progression on Membuster3.
+
+ * bytecode/UnlinkedCodeBlock.cpp:
+ (JSC::UnlinkedFunctionExecutable::paramString):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ * parser/Nodes.cpp:
+ (JSC::FunctionParameters::create):
+ (JSC::FunctionParameters::FunctionParameters):
+ (JSC::FunctionParameters::~FunctionParameters):
+ * parser/Nodes.h:
+ (FunctionParameters):
+ (JSC::FunctionParameters::size):
+ (JSC::FunctionParameters::at):
+ (JSC::FunctionParameters::identifiers):
+
+2013-01-27 Andreas Kling <akling@apple.com>
+
JSC: SourceProviderCache is memory hungry.
<http://webkit.org/b/108029>
<rdar://problem/13094806>
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
index 5ceaac7..1fea8d1 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
@@ -150,7 +150,7 @@
for (size_t pos = 0; pos < parameters.size(); ++pos) {
if (!builder.isEmpty())
builder.appendLiteral(", ");
- builder.append(parameters[pos].string());
+ builder.append(parameters.at(pos).string());
}
return builder.toString();
}
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index c387cfe..f57e1bc 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -360,7 +360,7 @@
capturedArguments.resize(parameters.size());
for (size_t i = 0; i < parameters.size(); ++i) {
capturedArguments[i] = 0;
- if (!functionBody->captures(parameters[i]) && !shouldCaptureAllTheThings)
+ if (!functionBody->captures(parameters.at(i)) && !shouldCaptureAllTheThings)
continue;
capturesAnyArgumentByName = true;
capturedArguments[i] = addVar();
@@ -461,12 +461,12 @@
for (size_t i = 0; i < parameters.size(); ++i, --nextParameterIndex) {
int index = nextParameterIndex;
if (capturedArguments.size() && capturedArguments[i]) {
- ASSERT((functionBody->hasCapturedVariables() && functionBody->captures(parameters[i])) || shouldCaptureAllTheThings);
+ ASSERT((functionBody->hasCapturedVariables() && functionBody->captures(parameters.at(i))) || shouldCaptureAllTheThings);
index = capturedArguments[i]->index();
RegisterID original(nextParameterIndex);
emitMove(capturedArguments[i], &original);
}
- addParameter(parameters[i], index);
+ addParameter(parameters.at(i), index);
}
preserveLastVar();
diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp
index 03ee8ee..45bf356 100644
--- a/Source/JavaScriptCore/parser/Nodes.cpp
+++ b/Source/JavaScriptCore/parser/Nodes.cpp
@@ -151,16 +151,29 @@
// ------------------------------ FunctionBodyNode -----------------------------
-FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
+PassRefPtr<FunctionParameters> FunctionParameters::create(ParameterNode* firstParameter)
{
unsigned parameterCount = 0;
for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
++parameterCount;
- reserveInitialCapacity(parameterCount);
+ size_t objectSize = sizeof(FunctionParameters) - sizeof(void*) + sizeof(StringImpl*) * parameterCount;
+ void* slot = fastMalloc(objectSize);
+ return adoptRef(new (slot) FunctionParameters(firstParameter, parameterCount));
+}
+FunctionParameters::FunctionParameters(ParameterNode* firstParameter, unsigned size)
+ : m_size(size)
+{
+ unsigned i = 0;
for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
- uncheckedAppend(parameter->ident());
+ new (&identifiers()[i++]) Identifier(parameter->ident());
+}
+
+FunctionParameters::~FunctionParameters()
+{
+ for (unsigned i = 0; i < m_size; ++i)
+ identifiers()[i].~Identifier();
}
inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, const JSTokenLocation& location, bool inStrictContext)
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h
index 16ffd7d..5296e23 100644
--- a/Source/JavaScriptCore/parser/Nodes.h
+++ b/Source/JavaScriptCore/parser/Nodes.h
@@ -1393,13 +1393,23 @@
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
- class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> {
+ class FunctionParameters : public RefCounted<FunctionParameters> {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); }
+ static PassRefPtr<FunctionParameters> create(ParameterNode*);
+ ~FunctionParameters();
+
+ unsigned size() const { return m_size; }
+ const Identifier& at(unsigned index) const { ASSERT(index < m_size); return identifiers()[index]; }
private:
- FunctionParameters(ParameterNode*);
+ FunctionParameters(ParameterNode*, unsigned size);
+
+ Identifier* identifiers() { return reinterpret_cast<Identifier*>(&m_storage); }
+ const Identifier* identifiers() const { return reinterpret_cast<const Identifier*>(&m_storage); }
+
+ unsigned m_size;
+ void* m_storage;
};
enum FunctionNameIsInScopeToggle { FunctionNameIsNotInScope, FunctionNameIsInScope };