Title: [206640] trunk
Revision
206640
Author
[email protected]
Date
2016-09-30 09:59:24 -0700 (Fri, 30 Sep 2016)

Log Message

Air should have a way of expressing additional instruction flags
https://bugs.webkit.org/show_bug.cgi?id=162699

Reviewed by Mark Lam.
Source/_javascript_Core:

        
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):

Source/WTF:


* wtf/CommaPrinter.h:
(WTF::CommaPrinter::CommaPrinter):
(WTF::CommaPrinter::dump):
(WTF::CommaPrinter::didPrint):

Websites/webkit.org:


* docs/b3/assembly-intermediate-representation.html:

Modified Paths

Added Paths

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
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to