Diff
Modified: trunk/LayoutTests/ChangeLog (153762 => 153763)
--- trunk/LayoutTests/ChangeLog 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/LayoutTests/ChangeLog 2013-08-06 21:20:10 UTC (rev 153763)
@@ -1,3 +1,17 @@
+2013-08-06 Oliver Hunt <[email protected]>
+
+ Delay Arguments creation in strict mode
+ https://bugs.webkit.org/show_bug.cgi?id=119505
+
+ Reviewed by Geoffrey Garen.
+
+ Add performance testcase for lazy creation of arguments in strict mode
+
+ * fast/js/regress/delay-tear-off-arguments-strictmode-expected.txt: Added.
+ * fast/js/regress/delay-tear-off-arguments-strictmode.html: Added.
+ * fast/js/regress/script-tests/delay-tear-off-arguments-strictmode.js: Added.
+ (bar):
+
2013-08-06 Bem Jones-Bey <[email protected]>
[CSS Shapes] New positioning model: support for shape-margin
Added: trunk/LayoutTests/fast/js/regress/delay-tear-off-arguments-strictmode-expected.txt (0 => 153763)
--- trunk/LayoutTests/fast/js/regress/delay-tear-off-arguments-strictmode-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/regress/delay-tear-off-arguments-strictmode-expected.txt 2013-08-06 21:20:10 UTC (rev 153763)
@@ -0,0 +1,10 @@
+JSRegress/delay-tear-off-arguments-strictmode
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/regress/delay-tear-off-arguments-strictmode.html (0 => 153763)
--- trunk/LayoutTests/fast/js/regress/delay-tear-off-arguments-strictmode.html (rev 0)
+++ trunk/LayoutTests/fast/js/regress/delay-tear-off-arguments-strictmode.html 2013-08-06 21:20:10 UTC (rev 153763)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/regress/script-tests/delay-tear-off-arguments-strictmode.js (0 => 153763)
--- trunk/LayoutTests/fast/js/regress/script-tests/delay-tear-off-arguments-strictmode.js (rev 0)
+++ trunk/LayoutTests/fast/js/regress/script-tests/delay-tear-off-arguments-strictmode.js 2013-08-06 21:20:10 UTC (rev 153763)
@@ -0,0 +1,15 @@
+function bar(x)
+{
+ "use strict";
+ var result = 0;
+ for (var i = 0; i < arguments.length; ++i)
+ result += arguments[i];
+ return result;
+}
+
+var result = 0;
+for (var i = 0; i < 100000; ++i)
+ result += bar(i, i + 1, i + 2, i + 3);
+
+if (result != 20000400000)
+ throw "Bad result: " + result;
Modified: trunk/Source/_javascript_Core/ChangeLog (153762 => 153763)
--- trunk/Source/_javascript_Core/ChangeLog 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-08-06 21:20:10 UTC (rev 153763)
@@ -1,3 +1,31 @@
+2013-08-05 Oliver Hunt <[email protected]>
+
+ Delay Arguments creation in strict mode
+ https://bugs.webkit.org/show_bug.cgi?id=119505
+
+ Reviewed by Geoffrey Garen.
+
+ Make use of the write tracking performed by the parser to
+ allow us to know if we're modifying the parameters to a function.
+ Then use that information to make strict mode function opt out
+ of eager arguments creation.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::createArgumentsIfNecessary):
+ (JSC::BytecodeGenerator::emitReturn):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::shouldTearOffArgumentsEagerly):
+ * parser/Nodes.h:
+ (JSC::ScopeNode::modifiesParameter):
+ * parser/Parser.cpp:
+ (JSC::::parseInner):
+ * parser/Parser.h:
+ (JSC::Scope::declareParameter):
+ (JSC::Scope::getCapturedVariables):
+ (JSC::Parser::declareWrite):
+ * parser/ParserModes.h:
+
2013-08-06 Patrick Gansterer <[email protected]>
Remove useless code from COMPILER(RVCT) JITStubs
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (153762 => 153763)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2013-08-06 21:20:10 UTC (rev 153763)
@@ -238,7 +238,7 @@
emitInitLazyRegister(argumentsRegister);
emitInitLazyRegister(unmodifiedArgumentsRegister);
- if (m_codeBlock->isStrictMode()) {
+ if (shouldTearOffArgumentsEagerly()) {
emitOpcode(op_create_arguments);
instructions().append(argumentsRegister->index());
}
@@ -268,7 +268,7 @@
}
}
- if (capturesAnyArgumentByName && !codeBlock->isStrictMode()) {
+ if (capturesAnyArgumentByName && !shouldTearOffArgumentsEagerly()) {
size_t parameterCount = m_symbolTable->parameterCount();
OwnArrayPtr<SlowArgument> slowArguments = adoptArrayPtr(new SlowArgument[parameterCount]);
for (size_t i = 0; i < parameterCount; ++i) {
@@ -1559,10 +1559,7 @@
if (!m_codeBlock->usesArguments())
return;
- // If we're in strict mode we tear off the arguments on function
- // entry, so there's no need to check if we need to create them
- // now
- if (m_codeBlock->isStrictMode())
+ if (shouldTearOffArgumentsEagerly())
return;
emitOpcode(op_create_arguments);
@@ -1749,7 +1746,7 @@
instructions().append(m_activationRegister->index());
}
- if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !m_codeBlock->isStrictMode()) {
+ if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !isStrictMode()) {
emitOpcode(op_tear_off_arguments);
instructions().append(m_codeBlock->argumentsRegister());
instructions().append(m_activationRegister ? m_activationRegister->index() : emitLoad(0, JSValue())->index());
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (153762 => 153763)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2013-08-06 21:20:10 UTC (rev 153763)
@@ -554,6 +554,11 @@
return true;
}
+ bool shouldTearOffArgumentsEagerly()
+ {
+ return m_codeType == FunctionCode && isStrictMode() && m_scopeNode->modifiesParameter();
+ }
+
RegisterID* emitThrowExpressionTooDeepException();
void createArgumentsIfNecessary();
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (153762 => 153763)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2013-08-06 21:20:10 UTC (rev 153763)
@@ -1385,6 +1385,7 @@
bool usesEval() const { return m_features & EvalFeature; }
bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); }
+ bool modifiesParameter() const { return m_features & ModifiedParameterFeature; }
bool isStrictMode() const { return m_features & StrictModeFeature; }
void setUsesArguments() { m_features |= ArgumentsFeature; }
bool usesThis() const { return m_features & ThisFeature; }
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (153762 => 153763)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2013-08-06 21:20:10 UTC (rev 153763)
@@ -121,12 +121,15 @@
}
IdentifierSet capturedVariables;
- scope->getCapturedVariables(capturedVariables);
+ bool modifiedParameter = false;
+ scope->getCapturedVariables(capturedVariables, modifiedParameter);
CodeFeatures features = context.features();
if (scope->strictMode())
features |= StrictModeFeature;
if (scope->shadowsArguments())
features |= ShadowsArgumentsFeature;
+ if (modifiedParameter)
+ features |= ModifiedParameterFeature;
didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
context.numConstants(), capturedVariables);
Modified: trunk/Source/_javascript_Core/parser/Parser.h (153762 => 153763)
--- trunk/Source/_javascript_Core/parser/Parser.h 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/Source/_javascript_Core/parser/Parser.h 2013-08-06 21:20:10 UTC (rev 153763)
@@ -217,6 +217,8 @@
bool isArguments = m_vm->propertyNames->arguments == *ident;
bool isValidStrictMode = m_declaredVariables.add(ident->string().impl()).isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments;
m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
+ m_declaredParameters.add(ident->string().impl());
+
if (isArguments)
m_shadowsArguments = true;
return isValidStrictMode;
@@ -254,18 +256,10 @@
return true;
}
- void getUncapturedWrittenVariables(IdentifierSet& writtenVariables)
+ void getCapturedVariables(IdentifierSet& capturedVariables, bool& modifiedParameter)
{
- IdentifierSet::iterator end = m_writtenVariables.end();
- for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) {
- if (!m_declaredVariables.contains(*ptr))
- writtenVariables.add(*ptr);
- }
- }
-
- void getCapturedVariables(IdentifierSet& capturedVariables)
- {
if (m_needsFullActivation || m_usesEval) {
+ modifiedParameter = true;
capturedVariables.swap(m_declaredVariables);
return;
}
@@ -274,6 +268,16 @@
continue;
capturedVariables.add(*ptr);
}
+ modifiedParameter = false;
+ if (m_declaredParameters.size()) {
+ IdentifierSet::iterator end = m_writtenVariables.end();
+ for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) {
+ if (!m_declaredParameters.contains(*ptr))
+ continue;
+ modifiedParameter = true;
+ break;
+ }
+ }
}
void setStrictMode() { m_strictMode = true; }
bool strictMode() const { return m_strictMode; }
@@ -327,6 +331,7 @@
typedef Vector<ScopeLabelInfo, 2> LabelStack;
OwnPtr<LabelStack> m_labels;
+ IdentifierSet m_declaredParameters;
IdentifierSet m_declaredVariables;
IdentifierSet m_usedVariables;
IdentifierSet m_closedVariables;
@@ -460,7 +465,7 @@
void declareWrite(const Identifier* ident)
{
- if (!m_syntaxAlreadyValidated)
+ if (!m_syntaxAlreadyValidated || strictMode())
m_scopeStack.last().declareWrite(ident);
}
Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (153762 => 153763)
--- trunk/Source/_javascript_Core/parser/ParserModes.h 2013-08-06 20:51:22 UTC (rev 153762)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h 2013-08-06 21:20:10 UTC (rev 153763)
@@ -47,8 +47,9 @@
const CodeFeatures ThisFeature = 1 << 4;
const CodeFeatures StrictModeFeature = 1 << 5;
const CodeFeatures ShadowsArgumentsFeature = 1 << 6;
+const CodeFeatures ModifiedParameterFeature = 1 << 7;
-const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature;
+const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature | ModifiedParameterFeature;
} // namespace JSC