- Revision
- 220852
- Author
- [email protected]
- Date
- 2017-08-17 05:15:48 -0700 (Thu, 17 Aug 2017)
Log Message
[JSC] Avoid code bloating for iteration if block does not have "break"
https://bugs.webkit.org/show_bug.cgi?id=173228
Reviewed by Keith Miller.
Currently, we always emit code for breaked path when emitting for-of iteration.
But we can know that this breaked path can be used when emitting the bytecode.
This patch adds LabelScope::breakTargetMayBeBound(), which returns true if
the break label may be bound. We emit a breaked path only when it returns
true. This reduces bytecode bloating when using for-of iteration.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::Label::setLocation):
(JSC::BytecodeGenerator::newLabel):
(JSC::BytecodeGenerator::emitLabel):
(JSC::BytecodeGenerator::pushFinallyControlFlowScope):
(JSC::BytecodeGenerator::breakTarget):
(JSC::BytecodeGenerator::continueTarget):
(JSC::BytecodeGenerator::emitEnumeration):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/Label.h:
(JSC::Label::bind const):
(JSC::Label::hasOneRef const):
(JSC::Label::isBound const):
(JSC::Label::Label): Deleted.
* bytecompiler/LabelScope.h:
(JSC::LabelScope::hasOneRef const):
(JSC::LabelScope::breakTargetMayBeBound const):
* bytecompiler/NodesCodegen.cpp:
(JSC::ContinueNode::trivialTarget):
(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::trivialTarget):
(JSC::BreakNode::emitBytecode):
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (220851 => 220852)
--- trunk/Source/_javascript_Core/ChangeLog 2017-08-17 10:02:08 UTC (rev 220851)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-08-17 12:15:48 UTC (rev 220852)
@@ -1,3 +1,40 @@
+2017-08-17 Yusuke Suzuki <[email protected]>
+
+ [JSC] Avoid code bloating for iteration if block does not have "break"
+ https://bugs.webkit.org/show_bug.cgi?id=173228
+
+ Reviewed by Keith Miller.
+
+ Currently, we always emit code for breaked path when emitting for-of iteration.
+ But we can know that this breaked path can be used when emitting the bytecode.
+
+ This patch adds LabelScope::breakTargetMayBeBound(), which returns true if
+ the break label may be bound. We emit a breaked path only when it returns
+ true. This reduces bytecode bloating when using for-of iteration.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::Label::setLocation):
+ (JSC::BytecodeGenerator::newLabel):
+ (JSC::BytecodeGenerator::emitLabel):
+ (JSC::BytecodeGenerator::pushFinallyControlFlowScope):
+ (JSC::BytecodeGenerator::breakTarget):
+ (JSC::BytecodeGenerator::continueTarget):
+ (JSC::BytecodeGenerator::emitEnumeration):
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/Label.h:
+ (JSC::Label::bind const):
+ (JSC::Label::hasOneRef const):
+ (JSC::Label::isBound const):
+ (JSC::Label::Label): Deleted.
+ * bytecompiler/LabelScope.h:
+ (JSC::LabelScope::hasOneRef const):
+ (JSC::LabelScope::breakTargetMayBeBound const):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ContinueNode::trivialTarget):
+ (JSC::ContinueNode::emitBytecode):
+ (JSC::BreakNode::trivialTarget):
+ (JSC::BreakNode::emitBytecode):
+
2017-08-17 Csaba Osztrogonác <[email protected]>
ARM build fix after r220807 and r220834.
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (220851 => 220852)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-08-17 10:02:08 UTC (rev 220851)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-08-17 12:15:48 UTC (rev 220852)
@@ -70,13 +70,13 @@
segmentedVector.removeLast();
}
-void Label::setLocation(unsigned location)
+void Label::setLocation(BytecodeGenerator& generator, unsigned location)
{
m_location = location;
unsigned size = m_unresolvedJumps.size();
for (unsigned i = 0; i < size; ++i)
- m_generator.instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
+ generator.instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
}
void Variable::dump(PrintStream& out) const
@@ -1228,7 +1228,7 @@
shrinkToFit(m_labels);
// Allocate new label ID.
- m_labels.append(*this);
+ m_labels.append();
return m_labels.last();
}
@@ -1242,7 +1242,7 @@
void BytecodeGenerator::emitLabel(Label& l0)
{
unsigned newLabelIndex = instructions().size();
- l0.setLocation(newLabelIndex);
+ l0.setLocation(*this, newLabelIndex);
if (m_codeBlock->numberOfJumpTargets()) {
unsigned lastLabelIndex = m_codeBlock->lastJumpTarget();
@@ -3836,8 +3836,6 @@
FinallyContext* BytecodeGenerator::pushFinallyControlFlowScope(Label& finallyLabel)
{
- shrinkToFit(m_labelScopes);
-
ControlFlowScope scope(ControlFlowScope::Finally, currentLexicalScopeIndex(), FinallyContext(m_currentFinallyContext, finallyLabel));
m_controlFlowScopeStack.append(WTFMove(scope));
@@ -3857,7 +3855,7 @@
return m_controlFlowScopeStack.takeLast().finallyContext;
}
-RefPtr<LabelScope> BytecodeGenerator::breakTarget(const Identifier& name)
+LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
{
shrinkToFit(m_labelScopes);
@@ -3884,7 +3882,7 @@
return nullptr;
}
-RefPtr<LabelScope> BytecodeGenerator::continueTarget(const Identifier& name)
+LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
{
shrinkToFit(m_labelScopes);
@@ -4371,12 +4369,15 @@
emitJump(loopStart.get());
}
- emitLabel(scope->breakTarget());
+ bool breakLabelIsBound = scope->breakTargetMayBeBound();
+ if (breakLabelIsBound)
+ emitLabel(scope->breakTarget());
+ popFinallyControlFlowScope();
+ if (breakLabelIsBound) {
+ // IteratorClose sequence for break-ed control flow.
+ emitIteratorClose(iterator.get(), node);
+ }
}
-
- // IteratorClose sequence for break-ed control flow.
- popFinallyControlFlowScope();
- emitIteratorClose(iterator.get(), node);
emitLabel(loopDone.get());
}
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (220851 => 220852)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-08-17 10:02:08 UTC (rev 220851)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-08-17 12:15:48 UTC (rev 220852)
@@ -898,8 +898,8 @@
void popStructureForInScope(RegisterID* local);
void invalidateForInContextForLocal(RegisterID* local);
- RefPtr<LabelScope> breakTarget(const Identifier&);
- RefPtr<LabelScope> continueTarget(const Identifier&);
+ LabelScope* breakTarget(const Identifier&);
+ LabelScope* continueTarget(const Identifier&);
void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
void endSwitch(uint32_t clauseCount, const Vector<Ref<Label>, 8>&, ExpressionNode**, Label& defaultLabel, int32_t min, int32_t range);
Modified: trunk/Source/_javascript_Core/bytecompiler/Label.h (220851 => 220852)
--- trunk/Source/_javascript_Core/bytecompiler/Label.h 2017-08-17 10:02:08 UTC (rev 220851)
+++ trunk/Source/_javascript_Core/bytecompiler/Label.h 2017-08-17 12:15:48 UTC (rev 220852)
@@ -40,17 +40,13 @@
class Label {
WTF_MAKE_NONCOPYABLE(Label);
public:
- explicit Label(BytecodeGenerator& generator)
- : m_refCount(0)
- , m_location(invalidLocation)
- , m_generator(generator)
- {
- }
+ Label() = default;
- void setLocation(unsigned);
+ void setLocation(BytecodeGenerator&, unsigned);
int bind(int opcode, int offset) const
{
+ m_bound = true;
if (m_location == invalidLocation) {
m_unresolvedJumps.append(std::make_pair(opcode, offset));
return 0;
@@ -65,6 +61,7 @@
ASSERT(m_refCount >= 0);
}
int refCount() const { return m_refCount; }
+ bool hasOneRef() const { return m_refCount == 1; }
bool isForward() const { return m_location == invalidLocation; }
@@ -74,14 +71,16 @@
return bind(0, 0);
}
+ bool isBound() const { return m_bound; }
+
private:
typedef Vector<std::pair<int, int>, 8> JumpVector;
static const unsigned invalidLocation = UINT_MAX;
- int m_refCount;
- unsigned m_location;
- BytecodeGenerator& m_generator;
+ int m_refCount { 0 };
+ unsigned m_location { invalidLocation };
+ mutable bool m_bound { false };
mutable JumpVector m_unresolvedJumps;
};
Modified: trunk/Source/_javascript_Core/bytecompiler/LabelScope.h (220851 => 220852)
--- trunk/Source/_javascript_Core/bytecompiler/LabelScope.h 2017-08-17 10:02:08 UTC (rev 220851)
+++ trunk/Source/_javascript_Core/bytecompiler/LabelScope.h 2017-08-17 12:15:48 UTC (rev 220852)
@@ -63,7 +63,17 @@
ASSERT(m_refCount >= 0);
}
int refCount() const { return m_refCount; }
+ bool hasOneRef() const { return m_refCount == 1; }
+ bool breakTargetMayBeBound() const
+ {
+ if (!hasOneRef())
+ return true;
+ if (!m_breakTarget->hasOneRef())
+ return true;
+ return m_breakTarget->isBound();
+ }
+
private:
int m_refCount;
Type m_type;
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (220851 => 220852)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-08-17 10:02:08 UTC (rev 220851)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-08-17 12:15:48 UTC (rev 220852)
@@ -3076,7 +3076,7 @@
if (generator.shouldEmitDebugHooks())
return nullptr;
- RefPtr<LabelScope> scope = generator.continueTarget(m_ident);
+ LabelScope* scope = generator.continueTarget(m_ident);
ASSERT(scope);
if (generator.labelScopeDepth() != scope->scopeDepth())
@@ -3087,7 +3087,7 @@
void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
- RefPtr<LabelScope> scope = generator.continueTarget(m_ident);
+ LabelScope* scope = generator.continueTarget(m_ident);
ASSERT(scope);
bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), *scope->continueTarget());
@@ -3107,7 +3107,7 @@
if (generator.shouldEmitDebugHooks())
return nullptr;
- RefPtr<LabelScope> scope = generator.breakTarget(m_ident);
+ LabelScope* scope = generator.breakTarget(m_ident);
ASSERT(scope);
if (generator.labelScopeDepth() != scope->scopeDepth())
@@ -3118,7 +3118,7 @@
void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
- RefPtr<LabelScope> scope = generator.breakTarget(m_ident);
+ LabelScope* scope = generator.breakTarget(m_ident);
ASSERT(scope);
bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget());