Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (206639 => 206640)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2016-09-30 16:59:24 UTC (rev 206640)
@@ -88,6 +88,7 @@
b3/air/AirInsertionSet.cpp
b3/air/AirInst.cpp
b3/air/AirIteratedRegisterCoalescing.cpp
+ b3/air/AirKind.cpp
b3/air/AirLogRegisterPressure.cpp
b3/air/AirLowerAfterRegAlloc.cpp
b3/air/AirLowerEntrySwitch.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (206639 => 206640)
--- trunk/Source/_javascript_Core/ChangeLog 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-09-30 16:59:24 UTC (rev 206640)
@@ -1,5 +1,96 @@
2016-09-29 Filip Pizlo <[email protected]>
+ Air should have a way of expressing additional instruction flags
+ https://bugs.webkit.org/show_bug.cgi?id=162699
+
+ Reviewed by Mark Lam.
+
+ This follows a similar change in B3 (r206595) and replaces Air::Opcode with Air::Kind,
+ which holds onto the opcode and some additional flags. Because Air is an orthogonal ISA
+ (the opcode tells you what the operation does but each operand is allowed to also contain
+ effectively instructions for what to do to read or write that operand), the flags are
+ meant to be orthogonal to opcode. This allows us to say things like Add32<Trap>, which
+ makes sense if any of the operands to the Add32 are addresses.
+
+ To demonstrate the flags facility this partly adds a trap flag to Air. B3 doesn't use it
+ yet, but I made sure that Air respects it. Basically that means blocking DCE when the flag
+ is set, by making it imply hasNonArgNonControlEffects.
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * b3/B3CheckSpecial.cpp:
+ (JSC::B3::Air::numB3Args):
+ (JSC::B3::CheckSpecial::Key::Key):
+ (JSC::B3::CheckSpecial::Key::dump):
+ (JSC::B3::CheckSpecial::CheckSpecial):
+ (JSC::B3::CheckSpecial::hiddenBranch):
+ (JSC::B3::CheckSpecial::forEachArg):
+ (JSC::B3::CheckSpecial::generate):
+ (JSC::B3::CheckSpecial::dumpImpl):
+ (JSC::B3::CheckSpecial::deepDumpImpl):
+ * b3/B3CheckSpecial.h:
+ (JSC::B3::CheckSpecial::Key::Key):
+ (JSC::B3::CheckSpecial::Key::operator==):
+ (JSC::B3::CheckSpecial::Key::kind):
+ (JSC::B3::CheckSpecial::Key::hash):
+ (JSC::B3::CheckSpecial::Key::opcode): Deleted.
+ * b3/B3Kind.cpp:
+ (JSC::B3::Kind::dump):
+ * b3/air/AirDumpAsJS.cpp:
+ (JSC::B3::Air::dumpAsJS):
+ * b3/air/AirFixObviousSpills.cpp:
+ * b3/air/AirFixPartialRegisterStalls.cpp:
+ * b3/air/AirGenerate.cpp:
+ (JSC::B3::Air::generate):
+ * b3/air/AirHandleCalleeSaves.cpp:
+ (JSC::B3::Air::handleCalleeSaves):
+ * b3/air/AirInst.cpp:
+ (JSC::B3::Air::Inst::jsHash):
+ (JSC::B3::Air::Inst::dump):
+ * b3/air/AirInst.h:
+ (JSC::B3::Air::Inst::Inst):
+ (JSC::B3::Air::Inst::kind):
+ (JSC::B3::Air::Inst::operator bool):
+ (JSC::B3::Air::Inst::opcode): Deleted.
+ * b3/air/AirInstInlines.h:
+ (JSC::B3::Air::Inst::extraClobberedRegs):
+ (JSC::B3::Air::Inst::extraEarlyClobberedRegs):
+ (JSC::B3::Air::Inst::forEachDefWithExtraClobberedRegs):
+ (JSC::B3::Air::Inst::reportUsedRegisters):
+ (JSC::B3::Air::Inst::shouldTryAliasingDef):
+ * b3/air/AirIteratedRegisterCoalescing.cpp:
+ * b3/air/AirKind.cpp: Added.
+ (JSC::B3::Air::Kind::dump):
+ * b3/air/AirKind.h: Added.
+ (JSC::B3::Air::Kind::Kind):
+ (JSC::B3::Air::Kind::operator==):
+ (JSC::B3::Air::Kind::operator!=):
+ (JSC::B3::Air::Kind::hash):
+ (JSC::B3::Air::Kind::operator bool):
+ * b3/air/AirLowerAfterRegAlloc.cpp:
+ (JSC::B3::Air::lowerAfterRegAlloc):
+ * b3/air/AirLowerEntrySwitch.cpp:
+ (JSC::B3::Air::lowerEntrySwitch):
+ * b3/air/AirLowerMacros.cpp:
+ (JSC::B3::Air::lowerMacros):
+ * b3/air/AirOptimizeBlockOrder.cpp:
+ (JSC::B3::Air::optimizeBlockOrder):
+ * b3/air/AirReportUsedRegisters.cpp:
+ (JSC::B3::Air::reportUsedRegisters):
+ * b3/air/AirSimplifyCFG.cpp:
+ (JSC::B3::Air::simplifyCFG):
+ * b3/air/AirTmpWidth.cpp:
+ (JSC::B3::Air::TmpWidth::recompute):
+ * b3/air/AirUseCounts.h:
+ (JSC::B3::Air::UseCounts::UseCounts):
+ * b3/air/AirValidate.cpp:
+ * b3/air/opcode_generator.rb:
+ * b3/testb3.cpp:
+ (JSC::B3::testTernarySubInstructionSelection):
+ (JSC::B3::testBranchBitAndImmFusion):
+
+2016-09-29 Filip Pizlo <[email protected]>
+
REGRESSION(r206555): It made Dromaeo/jslib-style-jquery.html crash
https://bugs.webkit.org/show_bug.cgi?id=162721
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (206639 => 206640)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-09-30 16:59:24 UTC (rev 206640)
@@ -728,6 +728,8 @@
0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; };
0FDF67D21D9C6D27001B9825 /* B3Kind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDF67D11D9C6086001B9825 /* B3Kind.h */; };
0FDF67D31D9C6D2A001B9825 /* B3Kind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDF67D01D9C6086001B9825 /* B3Kind.cpp */; };
+ 0FDF67D61D9DC440001B9825 /* AirKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */; };
+ 0FDF67D71D9DC442001B9825 /* AirKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDF67D51D9DC43E001B9825 /* AirKind.h */; };
0FDF70851D3F2C2200927449 /* AirLowerEntrySwitch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDF70831D3F2C1F00927449 /* AirLowerEntrySwitch.cpp */; };
0FDF70861D3F2C2500927449 /* AirLowerEntrySwitch.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDF70841D3F2C1F00927449 /* AirLowerEntrySwitch.h */; };
0FE050141AA9091100D33B33 /* ArgumentsMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE0500C1AA9091100D33B33 /* ArgumentsMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2987,6 +2989,8 @@
0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = "<group>"; };
0FDF67D01D9C6086001B9825 /* B3Kind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3Kind.cpp; path = b3/B3Kind.cpp; sourceTree = "<group>"; };
0FDF67D11D9C6086001B9825 /* B3Kind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3Kind.h; path = b3/B3Kind.h; sourceTree = "<group>"; };
+ 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirKind.cpp; path = b3/air/AirKind.cpp; sourceTree = "<group>"; };
+ 0FDF67D51D9DC43E001B9825 /* AirKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirKind.h; path = b3/air/AirKind.h; sourceTree = "<group>"; };
0FDF70831D3F2C1F00927449 /* AirLowerEntrySwitch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirLowerEntrySwitch.cpp; path = b3/air/AirLowerEntrySwitch.cpp; sourceTree = "<group>"; };
0FDF70841D3F2C1F00927449 /* AirLowerEntrySwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLowerEntrySwitch.h; path = b3/air/AirLowerEntrySwitch.h; sourceTree = "<group>"; };
0FE0500C1AA9091100D33B33 /* ArgumentsMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgumentsMode.h; sourceTree = "<group>"; };
@@ -5013,6 +5017,8 @@
0FEC855C1BDACDC70080FF74 /* AirInstInlines.h */,
26718BA21BE99F780052017B /* AirIteratedRegisterCoalescing.cpp */,
26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */,
+ 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */,
+ 0FDF67D51D9DC43E001B9825 /* AirKind.h */,
2684D4371C00161C0081D663 /* AirLiveness.h */,
0FE34C171C4B39AE0003A512 /* AirLogRegisterPressure.cpp */,
0FE34C181C4B39AE0003A512 /* AirLogRegisterPressure.h */,
@@ -7559,6 +7565,7 @@
A7D89CFE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h in Headers */,
0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */,
0F40E4A71C497F7400A577FA /* AirOpcode.h in Headers */,
+ 0FDF67D71D9DC442001B9825 /* AirKind.h in Headers */,
0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */,
@@ -8928,6 +8935,7 @@
0F4570381BE44C910062A629 /* AirEliminateDeadCode.cpp in Sources */,
43AB26C71C1A535C00D82AE6 /* B3MathExtras.cpp in Sources */,
0FEC85781BDACDC70080FF74 /* AirGenerate.cpp in Sources */,
+ 0FDF67D61D9DC440001B9825 /* AirKind.cpp in Sources */,
0FEC85931BDB1E100080FF74 /* AirGenerated.cpp in Sources */,
53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */,
0FEC857B1BDACDC70080FF74 /* AirHandleCalleeSaves.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/b3/B3CheckSpecial.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/B3CheckSpecial.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/B3CheckSpecial.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -40,9 +40,9 @@
namespace {
-unsigned numB3Args(B3::Opcode opcode)
+unsigned numB3Args(B3::Kind kind)
{
- switch (opcode) {
+ switch (kind.opcode()) {
case CheckAdd:
case CheckSub:
case CheckMul:
@@ -57,7 +57,7 @@
unsigned numB3Args(Value* value)
{
- return numB3Args(value->opcode());
+ return numB3Args(value->kind());
}
unsigned numB3Args(Inst& inst)
@@ -69,7 +69,7 @@
CheckSpecial::Key::Key(const Inst& inst)
{
- m_opcode = inst.opcode;
+ m_kind = inst.kind;
m_numArgs = inst.args.size();
m_stackmapRole = SameAsRep;
}
@@ -76,19 +76,19 @@
void CheckSpecial::Key::dump(PrintStream& out) const
{
- out.print(m_opcode, "(", m_numArgs, ",", m_stackmapRole, ")");
+ out.print(m_kind, "(", m_numArgs, ",", m_stackmapRole, ")");
}
-CheckSpecial::CheckSpecial(Air::Opcode opcode, unsigned numArgs, RoleMode stackmapRole)
- : m_checkOpcode(opcode)
+CheckSpecial::CheckSpecial(Air::Kind kind, unsigned numArgs, RoleMode stackmapRole)
+ : m_checkKind(kind)
, m_stackmapRole(stackmapRole)
, m_numCheckArgs(numArgs)
{
- ASSERT(isDefinitelyTerminal(opcode));
+ ASSERT(isDefinitelyTerminal(kind.opcode));
}
CheckSpecial::CheckSpecial(const CheckSpecial::Key& key)
- : CheckSpecial(key.opcode(), key.numArgs(), key.stackmapRole())
+ : CheckSpecial(key.kind(), key.numArgs(), key.stackmapRole())
{
}
@@ -98,7 +98,7 @@
Inst CheckSpecial::hiddenBranch(const Inst& inst) const
{
- Inst hiddenBranch(m_checkOpcode, inst.origin);
+ Inst hiddenBranch(m_checkKind, inst.origin);
hiddenBranch.args.reserveInitialCapacity(m_numCheckArgs);
for (unsigned i = 0; i < m_numCheckArgs; ++i)
hiddenBranch.args.append(inst.args[i + 1]);
@@ -116,7 +116,7 @@
});
Optional<unsigned> firstRecoverableIndex;
- if (m_checkOpcode == BranchAdd32 || m_checkOpcode == BranchAdd64)
+ if (m_checkKind.opcode == BranchAdd32 || m_checkKind.opcode == BranchAdd64)
firstRecoverableIndex = 1;
forEachArgImpl(numB3Args(inst), m_numCheckArgs + 1, inst, m_stackmapRole, firstRecoverableIndex, callback);
}
@@ -164,7 +164,7 @@
fail.link(&jit);
// If necessary, undo the operation.
- switch (m_checkOpcode) {
+ switch (m_checkKind.opcode) {
case BranchAdd32:
if ((m_numCheckArgs == 4 && args[1] == args[2] && args[2] == args[3])
|| (m_numCheckArgs == 3 && args[1] == args[2])) {
@@ -235,12 +235,12 @@
void CheckSpecial::dumpImpl(PrintStream& out) const
{
- out.print(m_checkOpcode, "(", m_numCheckArgs, ",", m_stackmapRole, ")");
+ out.print(m_checkKind, "(", m_numCheckArgs, ",", m_stackmapRole, ")");
}
void CheckSpecial::deepDumpImpl(PrintStream& out) const
{
- out.print("B3::CheckValue lowered to ", m_checkOpcode, " with ", m_numCheckArgs, " args.");
+ out.print("B3::CheckValue lowered to ", m_checkKind, " with ", m_numCheckArgs, " args.");
}
} } // namespace JSC::B3
Modified: trunk/Source/_javascript_Core/b3/B3CheckSpecial.h (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/B3CheckSpecial.h 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/B3CheckSpecial.h 2016-09-30 16:59:24 UTC (rev 206640)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 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,7 +28,7 @@
#if ENABLE(B3_JIT)
#include "AirArg.h"
-#include "AirOpcode.h"
+#include "AirKind.h"
#include "B3StackmapSpecial.h"
#include <wtf/HashMap.h>
@@ -55,14 +55,13 @@
class Key {
public:
Key()
- : m_opcode(Air::Nop)
- , m_stackmapRole(SameAsRep)
+ : m_stackmapRole(SameAsRep)
, m_numArgs(0)
{
}
- Key(Air::Opcode opcode, unsigned numArgs, RoleMode stackmapRole = SameAsRep)
- : m_opcode(opcode)
+ Key(Air::Kind kind, unsigned numArgs, RoleMode stackmapRole = SameAsRep)
+ : m_kind(kind)
, m_stackmapRole(stackmapRole)
, m_numArgs(numArgs)
{
@@ -72,7 +71,7 @@
bool operator==(const Key& other) const
{
- return m_opcode == other.m_opcode
+ return m_kind == other.m_kind
&& m_numArgs == other.m_numArgs
&& m_stackmapRole == other.m_stackmapRole;
}
@@ -84,7 +83,7 @@
explicit operator bool() const { return *this != Key(); }
- Air::Opcode opcode() const { return m_opcode; }
+ Air::Kind kind() const { return m_kind; }
unsigned numArgs() const { return m_numArgs; }
RoleMode stackmapRole() const { return m_stackmapRole; }
@@ -91,8 +90,7 @@
void dump(PrintStream& out) const;
Key(WTF::HashTableDeletedValueType)
- : m_opcode(Air::Nop)
- , m_stackmapRole(SameAsRep)
+ : m_stackmapRole(SameAsRep)
, m_numArgs(1)
{
}
@@ -105,16 +103,16 @@
unsigned hash() const
{
// Seriously, we don't need to be smart here. It just doesn't matter.
- return m_opcode + m_numArgs + m_stackmapRole;
+ return m_kind.hash() + m_numArgs + m_stackmapRole;
}
private:
- Air::Opcode m_opcode;
+ Air::Kind m_kind;
RoleMode m_stackmapRole;
unsigned m_numArgs;
};
- CheckSpecial(Air::Opcode, unsigned numArgs, RoleMode stackmapRole = SameAsRep);
+ CheckSpecial(Air::Kind, unsigned numArgs, RoleMode stackmapRole = SameAsRep);
CheckSpecial(const Key&);
~CheckSpecial();
@@ -136,7 +134,7 @@
void deepDumpImpl(PrintStream&) const override;
private:
- Air::Opcode m_checkOpcode;
+ Air::Kind m_checkKind;
RoleMode m_stackmapRole;
unsigned m_numCheckArgs;
};
Modified: trunk/Source/_javascript_Core/b3/B3Kind.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/B3Kind.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/B3Kind.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -35,14 +35,12 @@
void Kind::dump(PrintStream& out) const
{
out.print(m_opcode);
- if (!hasExtraBits())
- return;
- CommaPrinter comma;
- out.print("<");
+ CommaPrinter comma(", ", "<");
if (isChill())
out.print(comma, "Chill");
- out.print(">");
+ if (comma.didPrint())
+ out.print(">");
}
} } // namespace JSC::B3
Modified: trunk/Source/_javascript_Core/b3/air/AirDumpAsJS.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirDumpAsJS.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirDumpAsJS.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -118,7 +118,9 @@
out.println(varName(block), ".predecessors.push(", varName(predecessor), ");");
for (Inst& inst : *block) {
- out.println("inst = new Inst(", inst.opcode, ");");
+ // FIXME: This should do something for flags.
+ // https://bugs.webkit.org/show_bug.cgi?id=162751
+ out.println("inst = new Inst(", inst.kind.opcode, ");");
inst.forEachArg(
[&] (Arg& arg, Arg::Role, Arg::Type, Arg::Width) {
@@ -197,7 +199,7 @@
out.println("inst.args.push(arg);");
});
- if (inst.opcode == Patch) {
+ if (inst.kind.opcode == Patch) {
if (inst.hasNonArgEffects())
out.println("inst.patchHasNonArgEffects = true;");
@@ -221,7 +223,7 @@
});
}
- if (inst.opcode == CCall || inst.opcode == ColdCCall) {
+ if (inst.kind.opcode == CCall || inst.kind.opcode == ColdCCall) {
out.println("inst.cCallType = ", inst.origin->type());
out.println("inst.cCallArgTypes = [];");
for (unsigned i = 1; i < inst.origin->numChildren(); ++i)
Modified: trunk/Source/_javascript_Core/b3/air/AirFixObviousSpills.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirFixObviousSpills.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirFixObviousSpills.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -121,7 +121,7 @@
m_state.clobber(arg);
});
- switch (inst.opcode) {
+ switch (inst.kind.opcode) {
case Move:
if (inst.args[0].isSomeImm()) {
if (inst.args[1].isReg())
Modified: trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -45,7 +45,7 @@
bool hasPartialXmmRegUpdate(const Inst& inst)
{
- switch (inst.opcode) {
+ switch (inst.kind.opcode) {
case ConvertDoubleToFloat:
case ConvertFloatToDouble:
case ConvertInt32ToDouble:
@@ -68,7 +68,7 @@
bool isDependencyBreaking(const Inst& inst)
{
// "xorps reg, reg" is used by the frontend to remove the dependency on its argument.
- return inst.opcode == MoveZeroToDouble;
+ return inst.kind.opcode == MoveZeroToDouble;
}
// FIXME: find a good distance per architecture experimentally.
Modified: trunk/Source/_javascript_Core/b3/air/AirGenerate.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirGenerate.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirGenerate.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -227,13 +227,13 @@
context.indexInBlock = block->size() - 1;
- if (block->last().opcode == Jump
+ if (block->last().kind.opcode == Jump
&& block->successorBlock(0) == code.findNextBlock(block))
continue;
addItem(block->last());
- if (isReturn(block->last().opcode)) {
+ if (isReturn(block->last().kind.opcode)) {
// We currently don't represent the full prologue/epilogue in Air, so we need to
// have this override.
if (code.frameSize()) {
Modified: trunk/Source/_javascript_Core/b3/air/AirHandleCalleeSaves.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirHandleCalleeSaves.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirHandleCalleeSaves.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -48,7 +48,7 @@
usedCalleeSaves.set(tmp.reg());
});
- if (inst.opcode == Patch)
+ if (inst.kind.opcode == Patch)
usedCalleeSaves.merge(inst.extraClobberedRegs());
}
}
Modified: trunk/Source/_javascript_Core/b3/air/AirInst.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirInst.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirInst.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -47,7 +47,9 @@
unsigned Inst::jsHash() const
{
- unsigned result = static_cast<unsigned>(opcode);
+ // FIXME: This should do something for flags.
+ // https://bugs.webkit.org/show_bug.cgi?id=162751
+ unsigned result = static_cast<unsigned>(kind.opcode);
for (const Arg& arg : args)
result += arg.jsHash();
@@ -57,7 +59,7 @@
void Inst::dump(PrintStream& out) const
{
- out.print(opcode, " ", listDump(args));
+ out.print(kind, " ", listDump(args));
if (origin) {
if (args.size())
out.print(", ");
Modified: trunk/Source/_javascript_Core/b3/air/AirInst.h (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirInst.h 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirInst.h 2016-09-30 16:59:24 UTC (rev 206640)
@@ -28,7 +28,7 @@
#if ENABLE(B3_JIT)
#include "AirArg.h"
-#include "AirOpcode.h"
+#include "AirKind.h"
#include "CCallHelpers.h"
namespace JSC {
@@ -50,39 +50,38 @@
Inst()
: origin(nullptr)
- , opcode(Nop)
{
}
- Inst(Opcode opcode, Value* origin)
+ Inst(Kind kind, Value* origin)
: origin(origin)
- , opcode(opcode)
+ , kind(kind)
{
}
template<typename... Arguments>
- Inst(Opcode opcode, Value* origin, Arg arg, Arguments... arguments)
+ Inst(Kind kind, Value* origin, Arg arg, Arguments... arguments)
: args{ arg, arguments... }
, origin(origin)
- , opcode(opcode)
+ , kind(kind)
{
}
- Inst(Opcode opcode, Value* origin, const ArgList& arguments)
+ Inst(Kind kind, Value* origin, const ArgList& arguments)
: args(arguments)
, origin(origin)
- , opcode(opcode)
+ , kind(kind)
{
}
- Inst(Opcode opcode, Value* origin, ArgList&& arguments)
+ Inst(Kind kind, Value* origin, ArgList&& arguments)
: args(WTFMove(arguments))
, origin(origin)
- , opcode(opcode)
+ , kind(kind)
{
}
- explicit operator bool() const { return origin || opcode != Nop || args.size(); }
+ explicit operator bool() const { return origin || kind || args.size(); }
void append() { }
@@ -200,7 +199,7 @@
ArgList args;
Value* origin; // The B3::Value that this originated from.
- Opcode opcode;
+ Kind kind;
};
} } } // namespace JSC::B3::Air
Modified: trunk/Source/_javascript_Core/b3/air/AirInstInlines.h (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirInstInlines.h 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirInstInlines.h 2016-09-30 16:59:24 UTC (rev 206640)
@@ -46,13 +46,13 @@
inline const RegisterSet& Inst::extraClobberedRegs()
{
- ASSERT(opcode == Patch);
+ ASSERT(kind.opcode == Patch);
return args[0].special()->extraClobberedRegs(*this);
}
inline const RegisterSet& Inst::extraEarlyClobberedRegs()
{
- ASSERT(opcode == Patch);
+ ASSERT(kind.opcode == Patch);
return args[0].special()->extraEarlyClobberedRegs(*this);
}
@@ -89,12 +89,12 @@
functor(Thing(reg), regDefRole, type, Arg::conservativeWidth(type));
};
- if (prevInst && prevInst->opcode == Patch) {
+ if (prevInst && prevInst->kind.opcode == Patch) {
regDefRole = Arg::Def;
prevInst->extraClobberedRegs().forEach(reportReg);
}
- if (nextInst && nextInst->opcode == Patch) {
+ if (nextInst && nextInst->kind.opcode == Patch) {
regDefRole = Arg::EarlyDef;
nextInst->extraEarlyClobberedRegs().forEach(reportReg);
}
@@ -102,7 +102,7 @@
inline void Inst::reportUsedRegisters(const RegisterSet& usedRegisters)
{
- ASSERT(opcode == Patch);
+ ASSERT(kind.opcode == Patch);
args[0].special()->reportUsedRegisters(*this, usedRegisters);
}
@@ -116,7 +116,7 @@
if (!isX86())
return Nullopt;
- switch (opcode) {
+ switch (kind.opcode) {
case Add32:
case Add64:
case And32:
Modified: trunk/Source/_javascript_Core/b3/air/AirIteratedRegisterCoalescing.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirIteratedRegisterCoalescing.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirIteratedRegisterCoalescing.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -1040,7 +1040,7 @@
{
switch (type) {
case Arg::GP:
- switch (inst.opcode) {
+ switch (inst.kind.opcode) {
case Move:
case Move32:
break;
@@ -1049,7 +1049,7 @@
}
break;
case Arg::FP:
- switch (inst.opcode) {
+ switch (inst.kind.opcode) {
case MoveFloat:
case MoveDouble:
break;
@@ -1074,7 +1074,7 @@
// Note that the input property requires an analysis over ZDef's, so it's only valid so long
// as the input gets a register. We don't know if the input gets a register, but we do know
// that if it doesn't get a register then we will still emit this Move32.
- if (inst.opcode == Move32) {
+ if (inst.kind.opcode == Move32) {
if (!tmpWidth)
return false;
@@ -1382,11 +1382,11 @@
// equivalent if the destination's high bits are not observable or if the source's high
// bits are all zero. Note that we don't have the opposite optimization for other
// architectures, which may prefer Move over Move32, because Move is canonical already.
- if (type == Arg::GP && inst.opcode == Move
+ if (type == Arg::GP && inst.kind.opcode == Move
&& inst.args[0].isTmp() && inst.args[1].isTmp()) {
if (m_tmpWidth.useWidth(inst.args[1].tmp()) <= Arg::Width32
|| m_tmpWidth.defWidth(inst.args[0].tmp()) <= Arg::Width32)
- inst.opcode = Move32;
+ inst.kind.opcode = Move32;
}
inst.forEachTmpFast([&] (Tmp& tmp) {
@@ -1453,7 +1453,7 @@
// Move is the canonical way to move data between GPRs.
bool canUseMove32IfDidSpill = false;
bool didSpill = false;
- if (type == Arg::GP && inst.opcode == Move) {
+ if (type == Arg::GP && inst.kind.opcode == Move) {
if ((inst.args[0].isTmp() && m_tmpWidth.width(inst.args[0].tmp()) <= Arg::Width32)
|| (inst.args[1].isTmp() && m_tmpWidth.width(inst.args[1].tmp()) <= Arg::Width32))
canUseMove32IfDidSpill = true;
@@ -1488,7 +1488,7 @@
Arg::Width spillWidth = m_tmpWidth.requiredWidth(arg.tmp());
if (Arg::isAnyDef(role) && width < spillWidth)
return;
- ASSERT(inst.opcode == Move || !(Arg::isAnyUse(role) && width > spillWidth));
+ ASSERT(inst.kind.opcode == Move || !(Arg::isAnyUse(role) && width > spillWidth));
if (spillWidth != Arg::Width32)
canUseMove32IfDidSpill = false;
@@ -1500,7 +1500,7 @@
});
if (didSpill && canUseMove32IfDidSpill)
- inst.opcode = Move32;
+ inst.kind.opcode = Move32;
// For every other case, add Load/Store as needed.
inst.forEachTmp([&] (Tmp& tmp, Arg::Role role, Arg::Type argType, Arg::Width) {
Added: trunk/Source/_javascript_Core/b3/air/AirKind.cpp (0 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirKind.cpp (rev 0)
+++ trunk/Source/_javascript_Core/b3/air/AirKind.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "AirKind.h"
+
+#if ENABLE(B3_JIT)
+
+#include <wtf/CommaPrinter.h>
+
+namespace JSC { namespace B3 { namespace Air {
+
+void Kind::dump(PrintStream& out) const
+{
+ out.print(opcode);
+
+ CommaPrinter comma(", ", "<");
+ if (traps)
+ out.print(comma, "Traps");
+ if (comma.didPrint())
+ out.print(">");
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
Added: trunk/Source/_javascript_Core/b3/air/AirKind.h (0 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirKind.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/air/AirKind.h 2016-09-30 16:59:24 UTC (rev 206640)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AirKind_h
+#define AirKind_h
+
+#if ENABLE(B3_JIT)
+
+#include "AirOpcode.h"
+#include <wtf/PrintStream.h>
+
+namespace JSC { namespace B3 { namespace Air {
+
+// Air opcodes are always carried around with some flags. These flags are understood as having no
+// meaning if they are set for an opcode to which they do not apply. This makes sense, since Air
+// is a complex instruction set and most of these flags can apply to basically any opcode. In
+// fact, it's recommended to only represent something as a flag if you believe that it is largely
+// opcode-agnostic.
+
+struct Kind {
+ Kind(Opcode opcode)
+ : opcode(opcode)
+ , traps(false)
+ {
+ }
+
+ Kind()
+ : Kind(Nop)
+ {
+ }
+
+ bool operator==(const Kind& other) const
+ {
+ return opcode == other.opcode
+ && traps == other.traps;
+ }
+
+ bool operator!=(const Kind& other) const
+ {
+ return !(*this == other);
+ }
+
+ unsigned hash() const
+ {
+ return static_cast<unsigned>(opcode) + (static_cast<unsigned>(traps) << 16);
+ }
+
+ explicit operator bool() const
+ {
+ return *this != Kind();
+ }
+
+ void dump(PrintStream&) const;
+
+ Opcode opcode;
+
+ // This is an opcode-agnostic flag that indicates that we expect that this instruction will
+ // trap. This causes the compiler to assume that this side-exits and therefore has non-control
+ // non-arg effects. This also causes the compiler to tell you about all of these instructions.
+ // Note that this is just one of several ways of supporting trapping in Air, and it's the less
+ // precise variant because it's origin-based. This means that if an instruction was fused out
+ // of B3 values that had different origins, then the origin at which you'll appear to trap
+ // will be somewhat random. The upside of this approach is that it imposes by far the least
+ // overhead on the compiler.
+ // FIXME: Make this completely work.
+ // https://bugs.webkit.org/show_bug.cgi?id=162689
+ bool traps : 1;
+};
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
+#endif // AirKind_h
+
Modified: trunk/Source/_javascript_Core/b3/air/AirLowerAfterRegAlloc.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirLowerAfterRegAlloc.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirLowerAfterRegAlloc.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -68,7 +68,7 @@
RegisterSet set;
- bool isRelevant = inst.opcode == Shuffle || inst.opcode == ColdCCall;
+ bool isRelevant = inst.kind.opcode == Shuffle || inst.kind.opcode == ColdCCall;
if (isRelevant) {
for (Reg reg : localCalc.live())
@@ -110,7 +110,7 @@
for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
Inst& inst = block->at(instIndex);
- switch (inst.opcode) {
+ switch (inst.kind.opcode) {
case Shuffle: {
RegisterSet set = usedRegisters.get(&inst);
Vector<ShufflePair> pairs;
@@ -141,6 +141,7 @@
case ColdCCall: {
CCallValue* value = inst.origin->as<CCallValue>();
+ Kind oldKind = inst.kind;
RegisterSet liveRegs = usedRegisters.get(&inst);
RegisterSet regsToSave = liveRegs;
@@ -195,6 +196,8 @@
instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
inst = buildCCall(code, inst.origin, destinations);
+ if (oldKind.traps)
+ inst.kind.traps = true;
// Now we need to emit code to restore registers.
pairs.resize(0);
Modified: trunk/Source/_javascript_Core/b3/air/AirLowerEntrySwitch.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirLowerEntrySwitch.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirLowerEntrySwitch.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -43,7 +43,7 @@
// Figure out the set of blocks that should be duplicated.
BlockWorklist worklist;
for (BasicBlock* block : code) {
- if (block->last().opcode == EntrySwitch)
+ if (block->last().kind.opcode == EntrySwitch)
worklist.push(block);
}
@@ -61,7 +61,7 @@
Vector<FrequencyClass> entrypointFrequencies(code.proc().numEntrypoints(), FrequencyClass::Rare);
for (BasicBlock* block : code) {
- if (block->last().opcode != EntrySwitch)
+ if (block->last().kind.opcode != EntrySwitch)
continue;
for (unsigned entrypointIndex = code.proc().numEntrypoints(); entrypointIndex--;) {
entrypointFrequencies[entrypointIndex] = maxFrequency(
@@ -71,10 +71,10 @@
}
auto fixEntrySwitch = [&] (BasicBlock* block, unsigned entrypointIndex) {
- if (block->last().opcode != EntrySwitch)
+ if (block->last().kind.opcode != EntrySwitch)
return;
FrequentedBlock target = block->successor(entrypointIndex);
- block->last().opcode = Jump;
+ block->last().kind.opcode = Jump;
block->successors().resize(1);
block->successor(0) = target;
};
Modified: trunk/Source/_javascript_Core/b3/air/AirLowerMacros.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirLowerMacros.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirLowerMacros.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -47,9 +47,10 @@
for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
Inst& inst = block->at(instIndex);
- switch (inst.opcode) {
+ switch (inst.kind.opcode) {
case CCall: {
CCallValue* value = inst.origin->as<CCallValue>();
+ Kind oldKind = inst.kind;
Vector<Arg> destinations = computeCCallingConvention(code, value);
@@ -70,6 +71,8 @@
Arg resultDst = value->type() == Void ? Arg() : inst.args[1];
inst = buildCCall(code, inst.origin, destinations);
+ if (oldKind.traps)
+ inst.kind.traps = true;
Tmp result = cCallResult(value->type());
switch (value->type()) {
Modified: trunk/Source/_javascript_Core/b3/air/AirOptimizeBlockOrder.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirOptimizeBlockOrder.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirOptimizeBlockOrder.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -160,7 +160,7 @@
// optimization. You'll probably realize that as soon as you look at the disassembly, and it
// certainly won't cause any correctness issues.
- switch (branch.opcode) {
+ switch (branch.kind.opcode) {
case Branch8:
case Branch32:
case Branch64:
Modified: trunk/Source/_javascript_Core/b3/air/AirReportUsedRegisters.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirReportUsedRegisters.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirReportUsedRegisters.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -73,7 +73,7 @@
inst = Inst();
}
- if (inst.opcode == Patch) {
+ if (inst.kind.opcode == Patch) {
RegisterSet registerSet;
for (Reg reg : localCalc.live())
registerSet.set(reg);
Modified: trunk/Source/_javascript_Core/b3/air/AirSimplifyCFG.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirSimplifyCFG.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirSimplifyCFG.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -78,7 +78,7 @@
for (BasicBlock*& successor : block->successorBlocks()) {
if (successor != block
&& successor->size() == 1
- && successor->last().opcode == Jump) {
+ && successor->last().kind.opcode == Jump) {
BasicBlock* newSuccessor = successor->successorBlock(0);
if (newSuccessor != successor) {
if (verbose) {
Modified: trunk/Source/_javascript_Core/b3/air/AirTmpWidth.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirTmpWidth.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirTmpWidth.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -88,7 +88,7 @@
Vector<Inst*> moves;
for (BasicBlock* block : code) {
for (Inst& inst : *block) {
- if (inst.opcode == Move && inst.args[1].isTmp()) {
+ if (inst.kind.opcode == Move && inst.args[1].isTmp()) {
if (inst.args[0].isTmp()) {
// Make sure that both sides of the Move have a width already initialized. The
// fixpoint below assumes that it never has to add things to the HashMap.
@@ -135,7 +135,7 @@
while (changed) {
changed = false;
for (Inst* move : moves) {
- ASSERT(move->opcode == Move);
+ ASSERT(move->kind.opcode == Move);
ASSERT(move->args[0].isTmp());
ASSERT(move->args[1].isTmp());
Modified: trunk/Source/_javascript_Core/b3/air/AirUseCounts.h (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirUseCounts.h 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirUseCounts.h 2016-09-30 16:59:24 UTC (rev 206640)
@@ -88,7 +88,7 @@
counts.numDefs += frequency;
});
- if ((inst.opcode == Move || inst.opcode == Move32)
+ if ((inst.kind.opcode == Move || inst.kind.opcode == Move32)
&& inst.args[0].isSomeImm()
&& inst.args[1].is<Thing>())
m_counts.add(inst.args[1].as<Thing>(), Counts()).iterator->value.numConstDefs++;
Modified: trunk/Source/_javascript_Core/b3/air/AirValidate.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/AirValidate.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/AirValidate.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -95,10 +95,15 @@
VALIDATE(&arg <= &inst.args.last(), ("At ", arg, " in ", inst, " in ", *block));
});
- switch (inst.opcode) {
+ switch (inst.kind.opcode) {
case EntrySwitch:
VALIDATE(block->numSuccessors() == m_code.proc().numEntrypoints(), ("At ", inst, " in ", *block));
break;
+ case Shuffle:
+ // We can't handle trapping shuffles because of how we lower them. That could
+ // be fixed though.
+ VALIDATE(!inst.kind.traps, ("At ", inst, " in ", *block));
+ break;
default:
break;
}
Modified: trunk/Source/_javascript_Core/b3/air/opcode_generator.rb (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/air/opcode_generator.rb 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/air/opcode_generator.rb 2016-09-30 16:59:24 UTC (rev 206640)
@@ -545,7 +545,7 @@
end
def matchInstOverload(outp, speed, inst)
- outp.puts "switch (#{inst}->opcode) {"
+ outp.puts "switch (#{inst}->kind.opcode) {"
$opcodes.values.each {
| opcode |
outp.puts "case #{opcode.name}:"
@@ -836,7 +836,7 @@
outp.puts "bool Inst::admitsStack(unsigned argIndex)"
outp.puts "{"
- outp.puts "switch (opcode) {"
+ outp.puts "switch (kind.opcode) {"
$opcodes.values.each {
| opcode |
outp.puts "case #{opcode.name}:"
@@ -978,7 +978,7 @@
outp.puts "bool Inst::isTerminal()"
outp.puts "{"
- outp.puts "switch (opcode) {"
+ outp.puts "switch (kind.opcode) {"
foundTrue = false
$opcodes.values.each {
| opcode |
@@ -1004,7 +1004,9 @@
outp.puts "bool Inst::hasNonArgNonControlEffects()"
outp.puts "{"
- outp.puts "switch (opcode) {"
+ outp.puts "if (kind.traps)"
+ outp.puts "return true;"
+ outp.puts "switch (kind.opcode) {"
foundTrue = false
$opcodes.values.each {
| opcode |
@@ -1030,7 +1032,9 @@
outp.puts "bool Inst::hasNonArgEffects()"
outp.puts "{"
- outp.puts "switch (opcode) {"
+ outp.puts "if (kind.traps)"
+ outp.puts "return true;"
+ outp.puts "switch (kind.opcode) {"
foundTrue = false
$opcodes.values.each {
| opcode |
Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (206639 => 206640)
--- trunk/Source/_javascript_Core/b3/testb3.cpp 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp 2016-09-30 16:59:24 UTC (rev 206640)
@@ -2217,7 +2217,7 @@
auto block = proc.code()[0];
unsigned numberOfSubInstructions = 0;
for (auto instruction : *block) {
- if (instruction.opcode == expectedOpcode) {
+ if (instruction.kind.opcode == expectedOpcode) {
CHECK_EQ(instruction.args.size(), 3ul);
CHECK_EQ(instruction.args[0].kind(), Air::Arg::Tmp);
CHECK_EQ(instruction.args[1].kind(), Air::Arg::Tmp);
@@ -12972,7 +12972,7 @@
// The first basic block must end in a BranchTest64(resCond, tmp, bitImm).
Air::Inst terminal = proc.code()[0]->last();
- CHECK_EQ(terminal.opcode, expectedOpcode);
+ CHECK_EQ(terminal.kind.opcode, expectedOpcode);
CHECK_EQ(terminal.args[0].kind(), Air::Arg::ResCond);
CHECK_EQ(terminal.args[1].kind(), firstKind);
CHECK(terminal.args[2].kind() == Air::Arg::BitImm || terminal.args[2].kind() == Air::Arg::BitImm64);
Modified: trunk/Source/WTF/ChangeLog (206639 => 206640)
--- trunk/Source/WTF/ChangeLog 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/WTF/ChangeLog 2016-09-30 16:59:24 UTC (rev 206640)
@@ -1,3 +1,15 @@
+2016-09-29 Filip Pizlo <[email protected]>
+
+ Air should have a way of expressing additional instruction flags
+ https://bugs.webkit.org/show_bug.cgi?id=162699
+
+ Reviewed by Mark Lam.
+
+ * wtf/CommaPrinter.h:
+ (WTF::CommaPrinter::CommaPrinter):
+ (WTF::CommaPrinter::dump):
+ (WTF::CommaPrinter::didPrint):
+
2016-09-30 Youenn Fablet <[email protected]>
Add a way to go from a RefPtr<T> to Ref<const T>
Modified: trunk/Source/WTF/wtf/CommaPrinter.h (206639 => 206640)
--- trunk/Source/WTF/wtf/CommaPrinter.h 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Source/WTF/wtf/CommaPrinter.h 2016-09-30 16:59:24 UTC (rev 206640)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,16 +32,18 @@
class CommaPrinter {
public:
- CommaPrinter(const char* comma = ", ")
+ CommaPrinter(const char* comma = ", ", const char* start = "")
: m_comma(comma)
- , m_isFirst(true)
+ , m_start(start)
+ , m_didPrint(false)
{
}
void dump(PrintStream& out) const
{
- if (m_isFirst) {
- m_isFirst = false;
+ if (!m_didPrint) {
+ out.print(m_start);
+ m_didPrint = true;
return;
}
@@ -48,9 +50,12 @@
out.print(m_comma);
}
+ bool didPrint() const { return m_didPrint; }
+
private:
const char* m_comma;
- mutable bool m_isFirst;
+ const char* m_start;
+ mutable bool m_didPrint;
};
} // namespace WTF
Modified: trunk/Websites/webkit.org/ChangeLog (206639 => 206640)
--- trunk/Websites/webkit.org/ChangeLog 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Websites/webkit.org/ChangeLog 2016-09-30 16:59:24 UTC (rev 206640)
@@ -1,3 +1,12 @@
+2016-09-30 Filip Pizlo <[email protected]>
+
+ Air should have a way of expressing additional instruction flags
+ https://bugs.webkit.org/show_bug.cgi?id=162699
+
+ Reviewed by Mark Lam.
+
+ * docs/b3/assembly-intermediate-representation.html:
+
2016-09-28 Filip Pizlo <[email protected]>
B3 opcodes should leave room for flags
Modified: trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html (206639 => 206640)
--- trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html 2016-09-30 16:52:47 UTC (rev 206639)
+++ trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html 2016-09-30 16:59:24 UTC (rev 206640)
@@ -28,10 +28,11 @@
<a href=""
Air has an explicit control flow graph: each basic block has predecessor and successor blocks.
Execution always begins at the first basic block (<code>code[0]</code>). The <code>Inst</code>s
- in each block are executed in order. Each <code>Inst</code> has an opcode, an array of
- arguments
+ in each block are executed in order. Each <code>Inst</code> has an opcode, some flags, an
+ array of arguments
(<a href=""
- and an origin. The origin is simply a B3 IR
+ and an origin. The opcode and flags are wrapped in a <code>Kind</code>, to make it
+ convenient to carry them around together. The origin is simply a B3 IR
<a href=""
Some opcodes use the origin for additional meta-data. This works because Air code always
coexists with the B3 procedure from which it was generated.</p>
@@ -251,6 +252,32 @@
<li><code>func(%rcx, UseZDef, GP, Width32)</code></li>
</ol>
+ <p>It's important to remember that Air's summaries of what instructions do to arguments are
+ not meant to be exhaustive. For example, if an instruction claims to use an address, this
+ tells you that the instruction will perform a load but it tells you nothing about how that
+ load will be performed. This means that unless you know exactly what it means to use/def an
+ argument, you cannot perform this transformation:</p>
+
+ <ul>
+ <li>Before:
+ <pre><code>Foo32 (%rax)</code></pre></li>
+ <li>After:
+ <pre><code>Move32 (%rax), %tmp
+Foo32 %tmp</code></pre></li>
+ </ul>
+
+ <p>Even if you know that Foo32 only uses its argument, you cannot do this because Move32 may
+ not load from the address using exactly the same kind of load that Foo32 would have done.
+ Memory accesses have many dimensions of options: alignment semantics (if you're lucky then
+ misaligned accesses run fast but sometimes they ignore low bits, trap if unaligned, or run
+ super slow when unaligned, and this behavior may depend on the opcode), temporality and
+ memory ordering, determinism of trapping, etc. Just seeing that an instruction uses an
+ address does not tell you what kind of load will happen, and currently Air does not have the
+ ability to answer such questions. Fortunately, Air does not have much need to move memory
+ accesses out of instructions. Uses and defs of temporaries, registers, immediates, and spill
+ slots don't have these caveats and so those arguments can be moved from one instruction to
+ another without worries.</p>
+
<p>Air's introspection of <code>Inst</code>s tends to be quite fast thanks to the use of template
specialization and C++ lambdas. The <code>forEachArg()</code> template method uses an efficient
arrangement of switch statements to determine the opcode and overload. If <code>func</code> is