- Revision
- 207060
- Author
- sbar...@apple.com
- Date
- 2016-10-11 00:28:08 -0700 (Tue, 11 Oct 2016)
Log Message
ValueAdd should be constant folded if the operands are constant String,Primitive or Primitive,String
https://bugs.webkit.org/show_bug.cgi?id=163182
Reviewed by Filip Pizlo.
JSTests:
* microbenchmarks/string-add-constant-folding.js: Added.
(assert):
(runTests):
(add):
(test):
Source/_javascript_Core:
This code pattern shows up in Dromaeo, so it's worth optimizing for.
This might also show up in real world JS code due to inlining and other
types of constant folding.
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGLazyJSValue.cpp:
(JSC::DFG::LazyJSValue::getValue):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
Modified Paths
Added Paths
Diff
Modified: trunk/JSTests/ChangeLog (207059 => 207060)
--- trunk/JSTests/ChangeLog 2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/JSTests/ChangeLog 2016-10-11 07:28:08 UTC (rev 207060)
@@ -1,3 +1,16 @@
+2016-10-11 Saam Barati <sbar...@apple.com>
+
+ ValueAdd should be constant folded if the operands are constant String,Primitive or Primitive,String
+ https://bugs.webkit.org/show_bug.cgi?id=163182
+
+ Reviewed by Filip Pizlo.
+
+ * microbenchmarks/string-add-constant-folding.js: Added.
+ (assert):
+ (runTests):
+ (add):
+ (test):
+
2016-10-07 Mark Lam <mark....@apple.com>
Object.freeze() and seal() should throw if [[PreventExtensions]]() fails.
Added: trunk/JSTests/microbenchmarks/string-add-constant-folding.js (0 => 207060)
--- trunk/JSTests/microbenchmarks/string-add-constant-folding.js (rev 0)
+++ trunk/JSTests/microbenchmarks/string-add-constant-folding.js 2016-10-11 07:28:08 UTC (rev 207060)
@@ -0,0 +1,68 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion.");
+}
+
+let tests = [];
+function test(f) {
+ noInline(f);
+ tests.push(f);
+}
+
+function runTests() {
+ let start = Date.now();
+ for (let f of tests) {
+ for (let i = 0; i < 40000; i++)
+ f();
+ }
+ const verbose = false;
+ if (verbose)
+ print(Date.now() - start);
+}
+
+function add(a,b) { return a + b; }
+noInline(add);
+
+test(function() {
+ let a = "foo";
+ let b = 20;
+ assert(a + b === add(a, b));
+ assert(b + a === add(b, a));
+});
+
+test(function() {
+ let a = "foo";
+ let b = null;
+ assert(a + b === add(a, b));
+ assert(b + a === add(b, a));
+});
+
+test(function() {
+ let a = "foo";
+ let b = undefined;
+ assert(a + b === add(a, b));
+ assert(b + a === add(b, a));
+});
+
+test(function() {
+ let a = "foo";
+ let b = 20.81239012821;
+ assert(a + b === add(a, b));
+ assert(b + a === add(b, a));
+});
+
+test(function() {
+ let a = "foo";
+ let b = true;
+ assert(a + b === add(a, b));
+ assert(b + a === add(b, a));
+});
+
+test(function() {
+ let a = "foo";
+ let b = false;
+ assert(a + b === add(a, b));
+ assert(b + a === add(b, a));
+});
+
+runTests();
Modified: trunk/Source/_javascript_Core/ChangeLog (207059 => 207060)
--- trunk/Source/_javascript_Core/ChangeLog 2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-10-11 07:28:08 UTC (rev 207060)
@@ -1,3 +1,21 @@
+2016-10-11 Saam Barati <sbar...@apple.com>
+
+ ValueAdd should be constant folded if the operands are constant String,Primitive or Primitive,String
+ https://bugs.webkit.org/show_bug.cgi?id=163182
+
+ Reviewed by Filip Pizlo.
+
+ This code pattern shows up in Dromaeo, so it's worth optimizing for.
+ This might also show up in real world JS code due to inlining and other
+ types of constant folding.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGLazyJSValue.cpp:
+ (JSC::DFG::LazyJSValue::getValue):
+ * dfg/DFGStrengthReductionPhase.cpp:
+ (JSC::DFG::StrengthReductionPhase::handleNode):
+
2016-10-10 Zan Dobersek <zdober...@igalia.com>
Add ENABLE_ENCRYPTED_MEDIA configuration option
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (207059 => 207060)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-11 07:28:08 UTC (rev 207060)
@@ -4239,7 +4239,12 @@
ByValInfo* byValInfo = m_inlineStackTop->m_byValInfos.get(CodeOrigin(currentCodeOrigin().bytecodeIndex));
// FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
// At that time, there is no information.
- if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent) && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
+ if (byValInfo
+ && byValInfo->stubInfo
+ && !byValInfo->tookSlowPath
+ && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
+ && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
+ && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
compiledAsPutById = true;
unsigned identifierNumber = m_graph.identifiers().ensure(byValInfo->cachedId.impl());
UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
Modified: trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp (207059 => 207060)
--- trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp 2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp 2016-10-11 07:28:08 UTC (rev 207060)
@@ -51,8 +51,9 @@
case SingleCharacterString:
return jsSingleCharacterString(&vm, u.character);
case KnownStringImpl:
+ return jsString(&vm, u.stringImpl);
case NewStringImpl:
- return jsString(&vm, u.stringImpl);
+ return jsString(&vm, AtomicStringImpl::add(u.stringImpl));
}
RELEASE_ASSERT_NOT_REACHED();
return JSValue();
Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (207059 => 207060)
--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp 2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp 2016-10-11 07:28:08 UTC (rev 207060)
@@ -322,8 +322,48 @@
// move these to the abstract interpreter once AbstractValue can support LazyJSValue.
// https://bugs.webkit.org/show_bug.cgi?id=155204
+ case ValueAdd: {
+ if (m_node->child1()->isConstant()
+ && m_node->child2()->isConstant()
+ && (!!m_node->child1()->tryGetString(m_graph) || !!m_node->child2()->tryGetString(m_graph))) {
+ auto tryGetConstantString = [&] (Node* node) -> String {
+ String string = node->tryGetString(m_graph);
+ if (!string.isEmpty())
+ return string;
+ JSValue value = node->constant()->value();
+ if (!value)
+ return String();
+ if (value.isInt32())
+ return String::number(value.asInt32());
+ if (value.isNumber())
+ return String::numberToStringECMAScript(value.asNumber());
+ if (value.isBoolean())
+ return value.asBoolean() ? ASCIILiteral("true") : ASCIILiteral("false");
+ if (value.isNull())
+ return ASCIILiteral("null");
+ if (value.isUndefined())
+ return ASCIILiteral("undefined");
+ return String();
+ };
+
+ String leftString = tryGetConstantString(m_node->child1().node());
+ if (!leftString)
+ break;
+ String rightString = tryGetConstantString(m_node->child2().node());
+ if (!rightString)
+ break;
+
+ StringBuilder builder;
+ builder.append(leftString);
+ builder.append(rightString);
+ m_node->convertToLazyJSConstant(
+ m_graph, LazyJSValue::newString(m_graph, builder.toString()));
+ m_changed = true;
+ }
+ break;
+ }
+
case MakeRope:
- case ValueAdd:
case StrCat: {
String leftString = m_node->child1()->tryGetString(m_graph);
if (!leftString)