summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2015-05-20 09:56:07 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2015-05-20 09:56:07 +0000
commit41386e9cb918eed93b3f13648cbef387e371e451 (patch)
treea97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
parente15dd966d523731101f70ccf768bba12435a0208 (diff)
downloadWebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp217
1 files changed, 60 insertions, 157 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
index 03515d52a..3aa991c48 100644
--- a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,14 +28,12 @@
#if ENABLE(DFG_JIT)
-#include "DFGAbstractHeap.h"
-#include "DFGClobberize.h"
#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "DFGPredictionPropagationPhase.h"
#include "DFGVariableAccessDataDump.h"
-#include "JSCInlines.h"
+#include "Operations.h"
namespace JSC { namespace DFG {
@@ -72,163 +70,73 @@ private:
{
switch (m_node->op()) {
case BitOr:
- handleCommutativity();
-
- if (m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
- convertToIdentityOverChild1();
- break;
+ if (m_node->child1()->isConstant()) {
+ JSValue op1 = m_graph.valueOfJSConstant(m_node->child1().node());
+ if (op1.isInt32() && !op1.asInt32()) {
+ convertToIdentityOverChild2();
+ break;
+ }
+ }
+ if (m_node->child2()->isConstant()) {
+ JSValue op2 = m_graph.valueOfJSConstant(m_node->child2().node());
+ if (op2.isInt32() && !op2.asInt32()) {
+ convertToIdentityOverChild1();
+ break;
+ }
}
- break;
-
- case BitXor:
- case BitAnd:
- handleCommutativity();
break;
case BitLShift:
case BitRShift:
case BitURShift:
- if (m_node->child2()->isInt32Constant() && !(m_node->child2()->asInt32() & 0x1f)) {
- convertToIdentityOverChild1();
- break;
- }
- break;
-
- case UInt32ToNumber:
- if (m_node->child1()->op() == BitURShift
- && m_node->child1()->child2()->isInt32Constant()
- && (m_node->child1()->child2()->asInt32() & 0x1f)
- && m_node->arithMode() != Arith::DoOverflow) {
- m_node->convertToIdentity();
- m_changed = true;
- break;
- }
- break;
-
- case ArithAdd:
- handleCommutativity();
-
- if (m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
- convertToIdentityOverChild1();
- break;
- }
- break;
-
- case ArithMul:
- handleCommutativity();
- break;
-
- case ArithSub:
- if (m_node->child2()->isInt32Constant()
- && m_node->isBinaryUseKind(Int32Use)) {
- int32_t value = m_node->child2()->asInt32();
- if (-value != value) {
- m_node->setOp(ArithAdd);
- m_node->child2().setNode(
- m_insertionSet.insertConstant(
- m_nodeIndex, m_node->origin, jsNumber(-value)));
- m_changed = true;
- break;
- }
- }
- break;
-
- case ArithPow:
- if (m_node->child2()->isNumberConstant()) {
- double yOperandValue = m_node->child2()->asNumber();
- if (yOperandValue == 1) {
+ if (m_node->child2()->isConstant()) {
+ JSValue op2 = m_graph.valueOfJSConstant(m_node->child2().node());
+ if (op2.isInt32() && !(op2.asInt32() & 0x1f)) {
convertToIdentityOverChild1();
- } else if (yOperandValue == 0.5) {
- m_insertionSet.insertCheck(m_nodeIndex, m_node);
- m_node->convertToArithSqrt();
- m_changed = true;
+ break;
}
}
break;
-
- case ValueRep:
- case Int52Rep:
- case DoubleRep: {
- // This short-circuits circuitous conversions, like ValueRep(DoubleRep(value)) or
- // even more complicated things. Like, it can handle a beast like
- // ValueRep(DoubleRep(Int52Rep(value))).
- // The only speculation that we would do beyond validating that we have a type that
- // can be represented a certain way is an Int32 check that would appear on Int52Rep
- // nodes. For now, if we see this and the final type we want is an Int52, we use it
- // as an excuse not to fold. The only thing we would need is a Int52RepInt32Use kind.
- bool hadInt32Check = false;
- if (m_node->op() == Int52Rep) {
- if (m_node->child1().useKind() != Int32Use)
- break;
- hadInt32Check = true;
- }
- for (Node* node = m_node->child1().node(); ; node = node->child1().node()) {
- if (canonicalResultRepresentation(node->result()) ==
- canonicalResultRepresentation(m_node->result())) {
- m_insertionSet.insertCheck(m_nodeIndex, m_node);
- if (hadInt32Check) {
- // FIXME: Consider adding Int52RepInt32Use or even DoubleRepInt32Use,
- // which would be super weird. The latter would only arise in some
- // seriously circuitous conversions.
- if (canonicalResultRepresentation(node->result()) != NodeResultJS)
- break;
-
- m_insertionSet.insertCheck(
- m_nodeIndex, m_node->origin, Edge(node, Int32Use));
- }
- m_node->child1() = node->defaultEdge();
+ case UInt32ToNumber:
+ if (m_node->child1()->op() == BitURShift
+ && m_node->child1()->child2()->isConstant()) {
+ JSValue shiftAmount = m_graph.valueOfJSConstant(
+ m_node->child1()->child2().node());
+ if (shiftAmount.isInt32() && (shiftAmount.asInt32() & 0x1f)) {
m_node->convertToIdentity();
m_changed = true;
break;
}
-
- switch (node->op()) {
- case Int52Rep:
- if (node->child1().useKind() != Int32Use)
- break;
- hadInt32Check = true;
- continue;
-
- case DoubleRep:
- case ValueRep:
- continue;
-
- default:
- break;
- }
- break;
}
break;
- }
- case Flush: {
- ASSERT(m_graph.m_form != SSA);
+ case GetArrayLength:
+ if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node))
+ foldTypedArrayPropertyToConstant(view, jsNumber(view->length()));
+ break;
- Node* setLocal = nullptr;
- VirtualRegister local = m_node->local();
+ case GetTypedArrayByteOffset:
+ if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node->child1().node()))
+ foldTypedArrayPropertyToConstant(view, jsNumber(view->byteOffset()));
+ break;
- for (unsigned i = m_nodeIndex; i--;) {
- Node* node = m_block->at(i);
- if (node->op() == SetLocal && node->local() == local) {
- setLocal = node;
+ case GetIndexedPropertyStorage:
+ if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) {
+ if (view->mode() != FastTypedArray) {
+ prepareToFoldTypedArray(view);
+ m_node->convertToConstantStoragePointer(view->vector());
+ m_changed = true;
break;
+ } else {
+ // FIXME: It would be awesome to be able to fold the property storage for
+ // these GC-allocated typed arrays. For now it doesn't matter because the
+ // most common use-cases for constant typed arrays involve large arrays with
+ // aliased buffer views.
+ // https://bugs.webkit.org/show_bug.cgi?id=125425
}
- if (accessesOverlap(m_graph, node, AbstractHeap(Stack, local)))
- break;
}
-
- if (!setLocal)
- break;
-
- // The Flush should become a PhantomLocal at this point. This means that we want the
- // local's value during OSR, but we don't care if the value is stored to the stack. CPS
- // rethreading can canonicalize PhantomLocals for us.
- m_node->convertFlushToPhantomLocal();
- m_graph.dethread();
- m_changed = true;
break;
- }
default:
break;
@@ -237,7 +145,8 @@ private:
void convertToIdentityOverChild(unsigned childIndex)
{
- m_insertionSet.insertCheck(m_nodeIndex, m_node);
+ m_insertionSet.insertNode(
+ m_nodeIndex, SpecNone, Phantom, m_node->codeOrigin, m_node->children);
m_node->children.removeEdge(childIndex ^ 1);
m_node->convertToIdentity();
m_changed = true;
@@ -253,26 +162,20 @@ private:
convertToIdentityOverChild(1);
}
- void handleCommutativity()
+ void foldTypedArrayPropertyToConstant(JSArrayBufferView* view, JSValue constant)
{
- // If the right side is a constant then there is nothing left to do.
- if (m_node->child2()->hasConstant())
- return;
-
- // This case ensures that optimizations that look for x + const don't also have
- // to look for const + x.
- if (m_node->child1()->hasConstant()) {
- std::swap(m_node->child1(), m_node->child2());
- m_changed = true;
- return;
- }
-
- // This case ensures that CSE is commutativity-aware.
- if (m_node->child1().node() > m_node->child2().node()) {
- std::swap(m_node->child1(), m_node->child2());
- m_changed = true;
- return;
- }
+ prepareToFoldTypedArray(view);
+ m_graph.convertToConstant(m_node, constant);
+ m_changed = true;
+ }
+
+ void prepareToFoldTypedArray(JSArrayBufferView* view)
+ {
+ m_insertionSet.insertNode(
+ m_nodeIndex, SpecNone, TypedArrayWatchpoint, m_node->codeOrigin,
+ OpInfo(view));
+ m_insertionSet.insertNode(
+ m_nodeIndex, SpecNone, Phantom, m_node->codeOrigin, m_node->children);
}
InsertionSet m_insertionSet;