Bug 891437 - Implement mozilla/Array.h, a class suitable for use where a C array would be used, with additional debug bounds-checking. r=Ms2ger
authorJeff Walden <jwalden@mit.edu>
Thu, 07 Feb 2013 15:32:20 -0800
changeset 146272 31aa18b9b25073aa2a6b82d3f95a54821e81cdb3
parent 146271 5a4b367aae64db4e6cdaabcf87d4b6c301bb5f3c
child 146273 cc877a2930f82b50bcc5b6dfa0d29c37b5826af8
push idunknown
push userunknown
push dateunknown
reviewersMs2ger
bugs891437
milestone25.0a1
Bug 891437 - Implement mozilla/Array.h, a class suitable for use where a C array would be used, with additional debug bounds-checking. r=Ms2ger
js/src/ion/AliasAnalysis.cpp
js/src/ion/BacktrackingAllocator.h
js/src/ion/FixedArityList.h
js/src/ion/LIR.h
js/src/ion/LiveRangeAllocator.h
js/src/ion/MIR.h
js/src/ion/Registers.h
mfbt/Array.h
mfbt/exported_headers.mk
--- a/js/src/ion/AliasAnalysis.cpp
+++ b/js/src/ion/AliasAnalysis.cpp
@@ -11,16 +11,18 @@
 #include "ion/MIRGraph.h"
 #include "ion/Ion.h"
 #include "ion/IonBuilder.h"
 #include "ion/IonSpewer.h"
 
 using namespace js;
 using namespace js::ion;
 
+using mozilla::Array;
+
 // Iterates over the flags in an AliasSet.
 class AliasSetIterator
 {
   private:
     uint32_t flags;
     unsigned pos;
 
   public:
@@ -112,17 +114,17 @@ IonSpewAliasInfo(const char *pre, MDefin
 // having an implicit dependency on the last instruction of the loop header, so that
 // it's never moved before the loop header.
 //
 // The algorithm depends on the invariant that both control instructions and effectful
 // instructions (stores) are never hoisted.
 bool
 AliasAnalysis::analyze()
 {
-    FixedArityList<MDefinitionVector, AliasSet::NumCategories> stores;
+    Array<MDefinitionVector, AliasSet::NumCategories> stores;
 
     // Initialize to the first instruction.
     MDefinition *firstIns = *graph_.begin()->begin();
     for (unsigned i=0; i < AliasSet::NumCategories; i++) {
         if (!stores[i].append(firstIns))
             return false;
     }
 
--- a/js/src/ion/BacktrackingAllocator.h
+++ b/js/src/ion/BacktrackingAllocator.h
@@ -2,16 +2,18 @@
  * vim: set ts=8 sts=4 et sw=4 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/. */
 
 #ifndef ion_BacktrackingAllocator_h
 #define ion_BacktrackingAllocator_h
 
+#include "mozilla/Array.h"
+
 #include "ion/LiveRangeAllocator.h"
 
 #include "ds/PriorityQueue.h"
 #include "ds/SplayTree.h"
 
 // Backtracking priority queue based register allocator based on that described
 // in the following blog post:
 //
@@ -155,17 +157,17 @@ class BacktrackingAllocator : public Liv
     // that register is currently allocated.
     struct PhysicalRegister {
         bool allocatable;
         AnyRegister reg;
         AllocatedRangeSet allocations;
 
         PhysicalRegister() : allocatable(false) {}
     };
-    FixedArityList<PhysicalRegister, AnyRegister::Total> registers;
+    mozilla::Array<PhysicalRegister, AnyRegister::Total> registers;
 
     // Ranges of code which are considered to be hot, for which good allocation
     // should be prioritized.
     AllocatedRangeSet hotcode;
 
   public:
     BacktrackingAllocator(MIRGenerator *mir, LIRGenerator *lir, LIRGraph &graph)
       : LiveRangeAllocator<BacktrackingVirtualRegister>(mir, lir, graph, /* forLSRA = */ false)
deleted file mode 100644
--- a/js/src/ion/FixedArityList.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 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/. */
-
-#ifndef ion_FixedArityList_h
-#define ion_FixedArityList_h
-
-namespace js {
-namespace ion {
-
-template <typename T, size_t Arity>
-class FixedArityList
-{
-    T list_[Arity];
-
-  public:
-    FixedArityList()
-      : list_()
-    { }
-
-    T &operator [](size_t index) {
-        JS_ASSERT(index < Arity);
-        return list_[index];
-    }
-    const T &operator [](size_t index) const {
-        JS_ASSERT(index < Arity);
-        return list_[index];
-    }
-};
-
-template <typename T>
-class FixedArityList<T, 0>
-{
-  public:
-    T &operator [](size_t index) {
-        MOZ_ASSUME_UNREACHABLE("no items");
-    }
-    const T &operator [](size_t index) const {
-        MOZ_ASSUME_UNREACHABLE("no items");
-    }
-};
-
-} // namespace ion
-} // namespace js
-
-#endif /* ion_FixedArityList_h */
--- a/js/src/ion/LIR.h
+++ b/js/src/ion/LIR.h
@@ -5,20 +5,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ion_LIR_h
 #define ion_LIR_h
 
 // This file declares the core data structures for LIR: storage allocations for
 // inputs and outputs, as well as the interface instructions must conform to.
 
+#include "mozilla/Array.h"
+
 #include "jscntxt.h"
+
 #include "ion/IonAllocPolicy.h"
 #include "ion/InlineList.h"
-#include "ion/FixedArityList.h"
 #include "ion/LOpcodes.h"
 #include "ion/Registers.h"
 #include "ion/MIR.h"
 #include "ion/MIRGraph.h"
 #include "ion/shared/Assembler-shared.h"
 #include "ion/Safepoints.h"
 #include "ion/Bailouts.h"
 #include "ion/VMFunctions.h"
@@ -800,19 +802,19 @@ class LBlock : public TempObject
     Label *label();
     LMoveGroup *getEntryMoveGroup();
     LMoveGroup *getExitMoveGroup();
 };
 
 template <size_t Defs, size_t Operands, size_t Temps>
 class LInstructionHelper : public LInstruction
 {
-    FixedArityList<LDefinition, Defs> defs_;
-    FixedArityList<LAllocation, Operands> operands_;
-    FixedArityList<LDefinition, Temps> temps_;
+    mozilla::Array<LDefinition, Defs> defs_;
+    mozilla::Array<LAllocation, Operands> operands_;
+    mozilla::Array<LDefinition, Temps> temps_;
 
   public:
     size_t numDefs() const MOZ_FINAL MOZ_OVERRIDE {
         return Defs;
     }
     LDefinition *getDef(size_t index) MOZ_FINAL MOZ_OVERRIDE {
         return &defs_[index];
     }
--- a/js/src/ion/LiveRangeAllocator.h
+++ b/js/src/ion/LiveRangeAllocator.h
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 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/. */
 
 #ifndef ion_LiveRangeAllocator_h
 #define ion_LiveRangeAllocator_h
 
+#include "mozilla/Array.h"
 #include "mozilla/DebugOnly.h"
 
 #include "ion/RegisterAllocator.h"
 #include "ion/StackSlotAllocator.h"
 
 // Common structures and functions used by register allocators that operate on
 // virtual register live ranges.
 
@@ -517,17 +518,17 @@ typedef InlineList<LiveInterval>::revers
 
 template <typename VREG>
 class LiveRangeAllocator : public RegisterAllocator
 {
   protected:
     // Computed inforamtion
     BitSet **liveIn;
     VirtualRegisterMap<VREG> vregs;
-    FixedArityList<LiveInterval *, AnyRegister::Total> fixedIntervals;
+    mozilla::Array<LiveInterval *, AnyRegister::Total> fixedIntervals;
 
     // Union of all ranges in fixedIntervals, used to quickly determine
     // whether an interval intersects with a fixed register.
     LiveInterval *fixedIntervalsUnion;
 
     // Whether the underlying allocator is LSRA. This changes the generated
     // live ranges in various ways: inserting additional fixed uses of
     // registers, and shifting the boundaries of live ranges by small amounts.
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -1,28 +1,32 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 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/. */
 
+/*
+ * Everything needed to build actual MIR instructions: the actual opcodes and
+ * instructions, the instruction interface, and use chains.
+ */
+
 #ifndef ion_MIR_h
 #define ion_MIR_h
 
-// This file declares everything needed to build actual MIR instructions: the
-// actual opcodes and instructions themselves, the instruction interface, and
-// use chains.
+#include "mozilla/Array.h"
+
 #include "jscntxt.h"
+#include "jsinfer.h"
 #include "jslibmath.h"
-#include "jsinfer.h"
+
 #include "ion/TypePolicy.h"
 #include "ion/IonAllocPolicy.h"
 #include "ion/InlineList.h"
 #include "ion/MOpcodes.h"
-#include "ion/FixedArityList.h"
 #include "ion/IonMacroAssembler.h"
 #include "ion/Bailouts.h"
 #include "ion/FixedList.h"
 #include "ion/CompilerRoot.h"
 #include "vm/ScopeObject.h"
 
 namespace js {
 
@@ -621,17 +625,17 @@ class MInstruction
     bool accept(MInstructionVisitor *visitor) {                             \
         return visitor->visit##opcode(this);                                \
     }
 
 template <size_t Arity>
 class MAryInstruction : public MInstruction
 {
   protected:
-    FixedArityList<MUse, Arity> operands_;
+    mozilla::Array<MUse, Arity> operands_;
 
     void setOperand(size_t index, MDefinition *operand) MOZ_FINAL MOZ_OVERRIDE {
         operands_[index].set(operand, this, index);
         operand->addUse(&operands_[index]);
     }
 
     MUse *getUseFor(size_t index) MOZ_FINAL MOZ_OVERRIDE {
         return &operands_[index];
@@ -938,18 +942,18 @@ class MTableSwitch MOZ_FINAL
     size_t numOperands() const {
         return 1;
     }
 };
 
 template <size_t Arity, size_t Successors>
 class MAryControlInstruction : public MControlInstruction
 {
-    FixedArityList<MUse, Arity> operands_;
-    FixedArityList<MBasicBlock *, Successors> successors_;
+    mozilla::Array<MUse, Arity> operands_;
+    mozilla::Array<MBasicBlock *, Successors> successors_;
 
   protected:
     void setOperand(size_t index, MDefinition *operand) MOZ_FINAL MOZ_OVERRIDE {
         operands_[index].set(operand, this, index);
         operand->addUse(&operands_[index]);
     }
     void setSuccessor(size_t index, MBasicBlock *successor) {
         successors_[index] = successor;
--- a/js/src/ion/Registers.h
+++ b/js/src/ion/Registers.h
@@ -2,26 +2,27 @@
  * vim: set ts=8 sts=4 et sw=4 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/. */
 
 #ifndef ion_Registers_h
 #define ion_Registers_h
 
+#include "mozilla/Array.h"
+
 #include "jsutil.h"
 #include "ion/IonTypes.h"
 #if defined(JS_CPU_X86)
 # include "ion/x86/Architecture-x86.h"
 #elif defined(JS_CPU_X64)
 # include "ion/x64/Architecture-x64.h"
 #elif defined(JS_CPU_ARM)
 # include "ion/arm/Architecture-arm.h"
 #endif
-#include "ion/FixedArityList.h"
 
 // ARM defines the RegisterID within Architecture-arm.h
 #if !defined(JS_CPU_ARM)
 #include "assembler/assembler/MacroAssembler.h"
 #endif
 
 namespace js {
 namespace ion {
@@ -82,18 +83,18 @@ struct FloatRegister {
     bool volatile_() const {
         return !!((1 << code()) & FloatRegisters::VolatileMask);
     }
 };
 
 // Information needed to recover machine register state.
 class MachineState
 {
-    FixedArityList<uintptr_t *, Registers::Total> regs_;
-    FixedArityList<double *, FloatRegisters::Total> fpregs_;
+    mozilla::Array<uintptr_t *, Registers::Total> regs_;
+    mozilla::Array<double *, FloatRegisters::Total> fpregs_;
 
   public:
     static MachineState FromBailout(uintptr_t regs[Registers::Total],
                                     double fpregs[FloatRegisters::Total]);
 
     void setRegisterLocation(Register reg, uintptr_t *up) {
         regs_[reg.code()] = up;
     }
new file mode 100644
--- /dev/null
+++ b/mfbt/Array.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/* A compile-time constant-length array with bounds-checking assertions. */
+
+#ifndef mozilla_Array_h_
+#define mozilla_Array_h_
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+
+#include <stddef.h>
+
+namespace mozilla {
+
+template<typename T, size_t Length>
+class Array
+{
+    T arr[Length];
+
+  public:
+    T& operator[](size_t i) {
+      MOZ_ASSERT(i < Length);
+      return arr[i];
+    }
+
+    const T& operator[](size_t i) const {
+      MOZ_ASSERT(i < Length);
+      return arr[i];
+    }
+};
+
+template<typename T>
+class Array<T, 0>
+{
+  public:
+    T& operator[](size_t i) {
+      MOZ_ASSUME_UNREACHABLE("indexing into zero-length array");
+    }
+
+    const T& operator[](size_t i) const {
+      MOZ_ASSUME_UNREACHABLE("indexing into zero-length array");
+    }
+};
+
+}  /* namespace mozilla */
+
+#endif /* mozilla_Array_h_ */
--- a/mfbt/exported_headers.mk
+++ b/mfbt/exported_headers.mk
@@ -5,16 +5,17 @@
 # This file defines the headers exported by mfbt.  It is included by mfbt
 # itself and by the JS engine, which, when built standalone, must install
 # mfbt's exported headers itself.
 
 EXPORTS_NAMESPACES += mozilla
 
 EXPORTS_mozilla += \
   AllocPolicy.h \
+  Array.h \
   Assertions.h \
   Atomics.h \
   Attributes.h \
   BloomFilter.h \
   Casting.h \
   Char16.h \
   CheckedInt.h \
   Compiler.h \