Improve loading elements from arrays with holes on x86, bug 727857. r=sstangl
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 10 Dec 2012 06:18:43 -0700
changeset 124595 e5082df102225e816deca3dc71ae5b4f9d0d4884
parent 124594 03e4cc5b322d1cdfc9f5204390acb9236316f66e
child 124596 14a96f465272ae10551fadb65605fffffdbfa69d
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs727857
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Improve loading elements from arrays with holes on x86, bug 727857. r=sstangl
js/src/ion/IonBuilder.cpp
js/src/ion/Lowering.cpp
js/src/ion/shared/Lowering-shared.h
js/src/ion/x86/CodeGenerator-x86.cpp
js/src/ion/x86/Lowering-x86.h
js/src/ion/x86/MacroAssembler-x86.h
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=4 sw=4 et tw=99:
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IonAnalysis.h"
 #include "IonBuilder.h"
+#include "Lowering.h"
 #include "MIRGraph.h"
 #include "Ion.h"
 #include "IonAnalysis.h"
 #include "IonSpewer.h"
 #include "frontend/BytecodeEmitter.h"
 
 #include "jsscriptinlines.h"
 #include "jstypedarrayinlines.h"
@@ -5238,26 +5239,31 @@ IonBuilder::jsop_getelem_dense()
     types::StackTypeSet *types = oracle->propertyRead(script_, pc);
     bool needsHoleCheck = !oracle->elementReadIsPacked(script_, pc);
     bool maybeUndefined = types->hasType(types::Type::UndefinedType());
 
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     JSValueType knownType = JSVAL_TYPE_UNKNOWN;
-    if (!needsHoleCheck && !barrier) {
+    if (!barrier) {
         knownType = types->getKnownTypeTag();
 
         // Null and undefined have no payload so they can't be specialized.
         // Since folding null/undefined while building SSA is not safe (see the
         // comment in IsPhiObservable), we just add an untyped load instruction
         // and rely on pushTypeBarrier and DCE to replace it with a null/undefined
         // constant.
         if (knownType == JSVAL_TYPE_UNDEFINED || knownType == JSVAL_TYPE_NULL)
             knownType = JSVAL_TYPE_UNKNOWN;
+
+        // Different architectures may want typed element reads which require
+        // hole checks to be done as either value or typed reads.
+        if (needsHoleCheck && !LIRGenerator::allowTypedElementHoleCheck())
+            knownType = JSVAL_TYPE_UNKNOWN;
     }
 
     // Ensure id is an integer.
     MInstruction *idInt32 = MToInt32::New(id);
     current->add(idInt32);
     id = idInt32;
 
     // Get the elements vector.
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -1483,19 +1483,23 @@ LIRGenerator::visitLoadElement(MLoadElem
         return defineBox(lir, ins);
       }
       case MIRType_Undefined:
       case MIRType_Null:
         JS_ASSERT(!"typed load must have a payload");
         return false;
 
       default:
-        JS_ASSERT(!ins->fallible());
-        return define(new LLoadElementT(useRegister(ins->elements()),
-                                        useRegisterOrConstant(ins->index())), ins);
+      {
+        LLoadElementT *lir = new LLoadElementT(useRegister(ins->elements()),
+                                               useRegisterOrConstant(ins->index()));
+        if (ins->fallible() && !assignSnapshot(lir))
+            return false;
+        return define(lir, ins);
+      }
     }
 }
 
 bool
 LIRGenerator::visitLoadElementHole(MLoadElementHole *ins)
 {
     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
     JS_ASSERT(ins->index()->type() == MIRType_Int32);
--- a/js/src/ion/shared/Lowering-shared.h
+++ b/js/src/ion/shared/Lowering-shared.h
@@ -161,16 +161,21 @@ class LIRGeneratorShared : public MInstr
 
     // Marks this instruction as needing to call into either the VM or GC. This
     // function may build a snapshot that captures the result of its own
     // instruction, and as such, should generally be called after define*().
     bool assignSafepoint(LInstruction *ins, MInstruction *mir);
 
   public:
     bool visitConstant(MConstant *ins);
+
+    // Whether to generate typed reads for element accesses with hole checks.
+    static bool allowTypedElementHoleCheck() {
+        return false;
+    }
 };
 
 } // namespace ion
 } // namespace js
 
 #endif // jsion_lowering_shared_h__
 
 
--- a/js/src/ion/x86/CodeGenerator-x86.cpp
+++ b/js/src/ion/x86/CodeGenerator-x86.cpp
@@ -225,22 +225,27 @@ CodeGeneratorX86::visitStoreSlotT(LStore
     return true;
 }
 
 bool
 CodeGeneratorX86::visitLoadElementT(LLoadElementT *load)
 {
     Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index());
 
+    if (load->mir()->needsHoleCheck()) {
+        Assembler::Condition cond = masm.testMagic(Assembler::Equal, source);
+        if (!bailoutIf(cond, load->snapshot()))
+            return false;
+    }
+
     if (load->mir()->type() == MIRType_Double)
         masm.loadInt32OrDouble(source, ToFloatRegister(load->output()));
     else
         masm.movl(masm.ToPayload(source), ToRegister(load->output()));
 
-    JS_ASSERT(!load->mir()->needsHoleCheck());
     return true;
 }
 
 void
 CodeGeneratorX86::storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
                                     const Register &elements, const LAllocation *index)
 {
     Operand dest = createArrayElementOperand(elements, index);
--- a/js/src/ion/x86/Lowering-x86.h
+++ b/js/src/ion/x86/Lowering-x86.h
@@ -44,16 +44,20 @@ class LIRGeneratorX86 : public LIRGenera
 
   public:
     bool visitConstant(MConstant *ins);
     bool visitBox(MBox *box);
     bool visitUnbox(MUnbox *unbox);
     bool visitReturn(MReturn *ret);
     bool visitStoreTypedArrayElement(MStoreTypedArrayElement *ins);
     bool lowerPhi(MPhi *phi);
+
+    static bool allowTypedElementHoleCheck() {
+        return true;
+    }
 };
 
 typedef LIRGeneratorX86 LIRGeneratorSpecific;
 
 } // namespace js
 } // namespace ion
 
 #endif // jsion_ion_lowering_x86_h__
--- a/js/src/ion/x86/MacroAssembler-x86.h
+++ b/js/src/ion/x86/MacroAssembler-x86.h
@@ -267,16 +267,21 @@ class MacroAssemblerX86 : public MacroAs
         cmpl(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
         return cond;
     }
     Condition testMagic(Condition cond, const Register &tag) {
         JS_ASSERT(cond == Equal || cond == NotEqual);
         cmpl(tag, ImmTag(JSVAL_TAG_MAGIC));
         return cond;
     }
+    Condition testMagic(Condition cond, const Operand &operand) {
+        JS_ASSERT(cond == Equal || cond == NotEqual);
+        cmpl(ToType(operand), ImmTag(JSVAL_TAG_MAGIC));
+        return cond;
+    }
     Condition testPrimitive(Condition cond, const Register &tag) {
         JS_ASSERT(cond == Equal || cond == NotEqual);
         cmpl(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
         return cond == Equal ? Below : AboveOrEqual;
     }
     Condition testError(Condition cond, const Register &tag) {
         return testMagic(cond, tag);
     }