Bug 1341087 - Implement symbol equality comparison in Ion. r=h4writer
authorTom Schuster <evilpies@gmail.com>
Tue, 21 Feb 2017 14:24:09 +0100
changeset 373092 2a9f1f1516ec266eb29fc7bc268b5805dd42437c
parent 373091 e0ab3ae16c94d6bc42926c893c66138967c855f9
child 373093 f0e0d480f660c02bdd40c3d26a635a51fe03de75
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs1341087
milestone54.0a1
Bug 1341087 - Implement symbol equality comparison in Ion. r=h4writer
js/src/jit-test/tests/symbol-equality.js
js/src/jit/Lowering.cpp
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/jit/TypePolicy.cpp
js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/symbol-equality.js
@@ -0,0 +1,23 @@
+setJitCompilerOption("ion.warmup.trigger", 10);
+
+function simpleEquality() {
+    for (var i = 0; i < 150; i++) {
+        var x = Symbol();
+        var y = Symbol();
+        assertEq(x === y, false);
+        assertEq(x !== y, true);
+        assertEq(x == y, false);
+        assertEq(x != y, true);
+    }
+}
+
+function equalOperands() {
+    for (var i = 0; i < 150; i++) {
+        var x = Symbol();
+        assertEq(x === x, true);
+        assertEq(x !== x, false);
+    }
+}
+
+equalOperands();
+simpleEquality();
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -873,20 +873,21 @@ LIRGenerator::visitTest(MTest* test)
 
             LCompareBAndBranch* lir = new(alloc()) LCompareBAndBranch(comp, useBox(left),
                                                                       useRegisterOrConstant(right),
                                                                       ifTrue, ifFalse);
             add(lir, test);
             return;
         }
 
-        // Compare and branch Int32 or Object pointers.
+        // Compare and branch Int32, Symbol or Object pointers.
         if (comp->isInt32Comparison() ||
             comp->compareType() == MCompare::Compare_UInt32 ||
-            comp->compareType() == MCompare::Compare_Object)
+            comp->compareType() == MCompare::Compare_Object ||
+            comp->compareType() == MCompare::Compare_Symbol)
         {
             JSOp op = ReorderComparison(comp->jsop(), &left, &right);
             LAllocation lhs = useRegister(left);
             LAllocation rhs;
             if (comp->isInt32Comparison() || comp->compareType() == MCompare::Compare_UInt32)
                 rhs = useAnyOrConstant(right);
             else
                 rhs = useRegister(right);
@@ -1118,20 +1119,21 @@ LIRGenerator::visitCompare(MCompare* com
         MOZ_ASSERT(left->type() == MIRType::Value);
         MOZ_ASSERT(right->type() == MIRType::Boolean);
 
         LCompareB* lir = new(alloc()) LCompareB(useBox(left), useRegisterOrConstant(right));
         define(lir, comp);
         return;
     }
 
-    // Compare Int32 or Object pointers.
+    // Compare Int32, Symbol or Object pointers.
     if (comp->isInt32Comparison() ||
         comp->compareType() == MCompare::Compare_UInt32 ||
-        comp->compareType() == MCompare::Compare_Object)
+        comp->compareType() == MCompare::Compare_Object ||
+        comp->compareType() == MCompare::Compare_Symbol)
     {
         JSOp op = ReorderComparison(comp->jsop(), &left, &right);
         LAllocation lhs = useRegister(left);
         LAllocation rhs;
         if (comp->isInt32Comparison() ||
             comp->compareType() == MCompare::Compare_UInt32)
         {
             rhs = useAnyOrConstant(right);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -3693,16 +3693,18 @@ MCompare::inputType()
       case Compare_DoubleMaybeCoerceLHS:
       case Compare_DoubleMaybeCoerceRHS:
         return MIRType::Double;
       case Compare_Float32:
         return MIRType::Float32;
       case Compare_String:
       case Compare_StrictString:
         return MIRType::String;
+      case Compare_Symbol:
+        return MIRType::Symbol;
       case Compare_Object:
         return MIRType::Object;
       case Compare_Unknown:
       case Compare_Bitwise:
         return MIRType::Value;
       default:
         MOZ_CRASH("No known conversion");
     }
@@ -3807,16 +3809,20 @@ MCompare::determineCompareType(JSOp op, 
     // Handle object comparison.
     if (!relationalEq && lhs == MIRType::Object && rhs == MIRType::Object)
         return Compare_Object;
 
     // Handle string comparisons. (Relational string compares are still unsupported).
     if (!relationalEq && lhs == MIRType::String && rhs == MIRType::String)
         return Compare_String;
 
+    // Handle symbol comparisons. (Relaational compare will throw)
+    if (!relationalEq && lhs == MIRType::Symbol && rhs == MIRType::Symbol)
+        return Compare_Symbol;
+
     // Handle strict string compare.
     if (strictEq && lhs == MIRType::String)
         return Compare_StrictString;
     if (strictEq && rhs == MIRType::String)
         return Compare_StrictString;
 
     // Handle compare with lhs or rhs being Undefined or Null.
     if (!relationalEq && IsNullOrUndefined(lhs))
@@ -4407,17 +4413,18 @@ MCompare::tryFoldEqualOperands(bool* res
     MOZ_ASSERT(compareType_ == Compare_Undefined || compareType_ == Compare_Null ||
                compareType_ == Compare_Boolean || compareType_ == Compare_Int32 ||
                compareType_ == Compare_Int32MaybeCoerceBoth ||
                compareType_ == Compare_Int32MaybeCoerceLHS ||
                compareType_ == Compare_Int32MaybeCoerceRHS || compareType_ == Compare_UInt32 ||
                compareType_ == Compare_Double || compareType_ == Compare_DoubleMaybeCoerceLHS ||
                compareType_ == Compare_DoubleMaybeCoerceRHS || compareType_ == Compare_Float32 ||
                compareType_ == Compare_String || compareType_ == Compare_StrictString ||
-               compareType_ == Compare_Object || compareType_ == Compare_Bitwise);
+               compareType_ == Compare_Object || compareType_ == Compare_Bitwise ||
+               compareType_ == Compare_Symbol);
 
     if (isDoubleComparison() || isFloat32Comparison()) {
         if (!operandsAreNeverNaN())
             return false;
     }
 
     lhs()->setGuardRangeBailoutsUnchecked();
 
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -4540,16 +4540,19 @@ class MCompare
         Compare_DoubleMaybeCoerceRHS,
 
         // Float compared to Float
         Compare_Float32,
 
         // String compared to String
         Compare_String,
 
+        // Symbol compared to Symbol
+        Compare_Symbol,
+
         // Undefined compared to String
         // Null      compared to String
         // Boolean   compared to String
         // Int32     compared to String
         // Double    compared to String
         // Object    compared to String
         // Value     compared to String
         Compare_StrictString,
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -201,18 +201,18 @@ ComparePolicy::adjustInputs(TempAllocato
         compare->compareType() == MCompare::Compare_Null)
     {
         // Nothing to do for undefined and null, lowering handles all types.
         return true;
     }
 
     // Convert all inputs to the right input type
     MIRType type = compare->inputType();
-    MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Double ||
-               type == MIRType::Object || type == MIRType::String || type == MIRType::Float32);
+    MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Double || type == MIRType::Float32 ||
+               type == MIRType::Object || type == MIRType::String || type == MIRType::Symbol);
     for (size_t i = 0; i < 2; i++) {
         MDefinition* in = def->getOperand(i);
         if (in->type() == type)
             continue;
 
         MInstruction* replace;
 
         switch (type) {
@@ -246,16 +246,19 @@ ComparePolicy::adjustInputs(TempAllocato
             break;
           }
           case MIRType::Object:
             replace = MUnbox::New(alloc, in, MIRType::Object, MUnbox::Infallible);
             break;
           case MIRType::String:
             replace = MUnbox::New(alloc, in, MIRType::String, MUnbox::Infallible);
             break;
+          case MIRType::Symbol:
+            replace = MUnbox::New(alloc, in, MIRType::Symbol, MUnbox::Infallible);
+            break;
           default:
             MOZ_CRASH("Unknown compare specialization");
         }
 
         def->block()->insertBefore(def, replace);
         def->replaceOperand(i, replace);
 
         if (!replace->typePolicy()->adjustInputs(alloc, replace))
--- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
+++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
@@ -133,17 +133,19 @@ CodeGeneratorMIPSShared::visitCompare(LC
 {
     MCompare* mir = comp->mir();
     Assembler::Condition cond = JSOpToCondition(mir->compareType(), comp->jsop());
     const LAllocation* left = comp->getOperand(0);
     const LAllocation* right = comp->getOperand(1);
     const LDefinition* def = comp->getDef(0);
 
 #ifdef JS_CODEGEN_MIPS64
-    if (mir->compareType() == MCompare::Compare_Object) {
+    if (mir->compareType() == MCompare::Compare_Object ||
+        mir->compareType() == MCompare::Compare_Symbol)
+    {
         if (right->isGeneralReg())
             masm.cmpPtrSet(cond, ToRegister(left), ToRegister(right), ToRegister(def));
         else
             masm.cmpPtrSet(cond, ToRegister(left), ToAddress(right), ToRegister(def));
         return;
     }
 #endif
 
@@ -157,17 +159,18 @@ CodeGeneratorMIPSShared::visitCompare(LC
 
 void
 CodeGeneratorMIPSShared::visitCompareAndBranch(LCompareAndBranch* comp)
 {
     MCompare* mir = comp->cmpMir();
     Assembler::Condition cond = JSOpToCondition(mir->compareType(), comp->jsop());
 
 #ifdef JS_CODEGEN_MIPS64
-    if (mir->compareType() == MCompare::Compare_Object) {
+    if (mir->compareType() == MCompare::Compare_Object ||
+        mir->compareType() == MCompare::Compare_Symbol)
         if (comp->right()->isGeneralReg()) {
             emitBranch(ToRegister(comp->left()), ToRegister(comp->right()), cond,
                        comp->ifTrue(), comp->ifFalse());
         } else {
             masm.loadPtr(ToAddress(comp->right()), ScratchRegister);
             emitBranch(ToRegister(comp->left()), ScratchRegister, cond,
                        comp->ifTrue(), comp->ifFalse());
         }
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ -143,17 +143,17 @@ CodeGeneratorX86Shared::visitBitAndAndBr
         masm.test32(ToRegister(baab->left()), ToRegister(baab->right()));
     emitBranch(baab->cond(), baab->ifTrue(), baab->ifFalse());
 }
 
 void
 CodeGeneratorX86Shared::emitCompare(MCompare::CompareType type, const LAllocation* left, const LAllocation* right)
 {
 #ifdef JS_CODEGEN_X64
-    if (type == MCompare::Compare_Object) {
+    if (type == MCompare::Compare_Object || type == MCompare::Compare_Symbol) {
         masm.cmpPtr(ToRegister(left), ToOperand(right));
         return;
     }
 #endif
 
     if (right->isConstant())
         masm.cmp32(ToRegister(left), Imm32(ToInt32(right)));
     else