Bug 1481171 - Remove failure path for lookupTrap(). r=luke
authorLars T Hansen <lhansen@mozilla.com>
Fri, 03 Aug 2018 12:04:53 +0200
changeset 486036 ac7bd965f86b3ae24921f35072eeea2204c82bba
parent 486035 413be91a02578a573edcb765117fc3e73ad6c427
child 486037 d999fb858fb2c007c5be4af72bce419c63c69b8e
child 486042 45e89feb5a66dfb031ec3c00fa785f3df4bdeb0b
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1481171
milestone63.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
Bug 1481171 - Remove failure path for lookupTrap(). r=luke With asm.js atomics gone and wasm atomics opting in to standard trap-based OOB handling, we should never fail to find a trap site. So assert that we always find it, and remove code that is now dead.
js/src/jit/arm/Simulator-arm.cpp
js/src/jit/arm64/vixl/MozSimulator-vixl.cpp
js/src/jit/mips32/Simulator-mips32.cpp
js/src/jit/mips64/Simulator-mips64.cpp
js/src/wasm/WasmBuiltins.cpp
js/src/wasm/WasmCode.cpp
js/src/wasm/WasmCode.h
js/src/wasm/WasmFrameIter.cpp
js/src/wasm/WasmGenerator.cpp
js/src/wasm/WasmModule.h
js/src/wasm/WasmSignalHandlers.cpp
js/src/wasm/WasmStubs.cpp
js/src/wasm/WasmTypes.cpp
js/src/wasm/WasmTypes.h
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -1617,21 +1617,19 @@ Simulator::handleWasmSegFault(int32_t ad
 
     MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code());
 
     if (!instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes))
         return false;
 
     wasm::Trap trap;
     wasm::BytecodeOffset bytecode;
-    if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) {
-        act->startWasmTrap(wasm::Trap::OutOfBounds, 0, registerState());
-        set_pc(int32_t(moduleSegment->outOfBoundsCode()));
-        return true;
-    }
+    MOZ_ALWAYS_TRUE(moduleSegment->code().lookupTrap(pc, &trap, &bytecode));
+
+    MOZ_RELEASE_ASSERT(trap == wasm::Trap::OutOfBounds);
 
     act->startWasmTrap(wasm::Trap::OutOfBounds, bytecode.offset(), registerState());
     set_pc(int32_t(moduleSegment->trapCode()));
     return true;
 }
 
 bool
 Simulator::handleWasmIllFault()
--- a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp
+++ b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp
@@ -261,21 +261,19 @@ Simulator::handle_wasm_seg_fault(uintptr
 
     MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code());
 
     if (!instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes))
         return false;
 
     js::wasm::Trap trap;
     js::wasm::BytecodeOffset bytecode;
-    if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) {
-        act->startWasmTrap(js::wasm::Trap::OutOfBounds, 0, registerState());
-        set_pc((Instruction*)moduleSegment->outOfBoundsCode());
-        return true;
-    }
+    MOZ_ALWAYS_TRUE(moduleSegment->code().lookupTrap(pc, &trap, &bytecode));
+
+    MOZ_RELEASE_ASSERT(trap == js::wasm::Trap::OutOfBounds);
 
     act->startWasmTrap(js::wasm::Trap::OutOfBounds, bytecode.offset(), registerState());
     set_pc((Instruction*)moduleSegment->trapCode());
     return true;
 }
 
 int64_t Simulator::call(uint8_t* entry, int argument_count, ...) {
   va_list parameters;
--- a/js/src/jit/mips32/Simulator-mips32.cpp
+++ b/js/src/jit/mips32/Simulator-mips32.cpp
@@ -1658,21 +1658,19 @@ Simulator::handleWasmFault(int32_t addr,
 
     if (!instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes))
          return false;
 
     LLBit_ = false;
 
     wasm::Trap trap;
     wasm::BytecodeOffset bytecode;
-    if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) {
-        act->startWasmTrap(wasm::Trap::OutOfBounds, 0, registerState());
-        set_pc(int32_t(moduleSegment->outOfBoundsCode()));
-        return true;
-    }
+    MOZ_ALWAYS_TRUE(moduleSegment->code().lookupTrap(pc, &trap, &bytecode));
+
+    MOZ_RELEASE_ASSERT(trap == wasm::Trap::OutOfBounds);
 
     act->startWasmTrap(wasm::Trap::OutOfBounds, bytecode.offset(), registerState());
     set_pc(int32_t(moduleSegment->trapCode()));
     return true;
 }
 
 bool
 Simulator::handleWasmTrapFault()
--- a/js/src/jit/mips64/Simulator-mips64.cpp
+++ b/js/src/jit/mips64/Simulator-mips64.cpp
@@ -1662,21 +1662,19 @@ Simulator::handleWasmFault(uint64_t addr
 
     if (!instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes))
          return false;
 
     LLBit_ = false;
 
     wasm::Trap trap;
     wasm::BytecodeOffset bytecode;
-    if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) {
-        act->startWasmTrap(wasm::Trap::OutOfBounds, 0, registerState());
-        set_pc(int64_t(moduleSegment->outOfBoundsCode()));
-        return true;
-    }
+    MOZ_ALWAYS_TRUE(moduleSegment->code().lookupTrap(pc, &trap, &bytecode));
+
+    MOZ_RELEASE_ASSERT(trap == wasm::Trap::OutOfBounds);
 
     act->startWasmTrap(wasm::Trap::OutOfBounds, bytecode.offset(), registerState());
     set_pc(int64_t(moduleSegment->trapCode()));
     return true;
 }
 
 bool
 Simulator::handleWasmTrapFault()
--- a/js/src/wasm/WasmBuiltins.cpp
+++ b/js/src/wasm/WasmBuiltins.cpp
@@ -284,23 +284,16 @@ WasmHandleTrap()
       case Trap::Limit:
         break;
     }
 
     MOZ_CRASH("unexpected trap");
 }
 
 static void
-WasmReportOutOfBounds()
-{
-    JSContext* cx = TlsContext.get();
-    JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_OUT_OF_BOUNDS);
-}
-
-static void
 WasmReportUnalignedAccess()
 {
     JSContext* cx = TlsContext.get();
     JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_UNALIGNED_ACCESS);
 }
 
 static void
 WasmReportInt64JSCall()
@@ -512,19 +505,16 @@ AddressOf(SymbolicAddress imm, ABIFuncti
         *abiType = Args_General0;
         return FuncCast(WasmHandleDebugTrap, *abiType);
       case SymbolicAddress::HandleThrow:
         *abiType = Args_General0;
         return FuncCast(WasmHandleThrow, *abiType);
       case SymbolicAddress::HandleTrap:
         *abiType = Args_General0;
         return FuncCast(WasmHandleTrap, *abiType);
-      case SymbolicAddress::ReportOutOfBounds:
-        *abiType = Args_General0;
-        return FuncCast(WasmReportOutOfBounds, *abiType);
       case SymbolicAddress::ReportUnalignedAccess:
         *abiType = Args_General0;
         return FuncCast(WasmReportUnalignedAccess, *abiType);
       case SymbolicAddress::ReportInt64JSCall:
         *abiType = Args_General0;
         return FuncCast(WasmReportInt64JSCall, *abiType);
       case SymbolicAddress::CallImport_Void:
         *abiType = Args_General4;
@@ -695,17 +685,16 @@ bool
 wasm::NeedsBuiltinThunk(SymbolicAddress sym)
 {
     // Some functions don't want to a thunk, because they already have one or
     // they don't have frame info.
     switch (sym) {
       case SymbolicAddress::HandleDebugTrap:          // GenerateDebugTrapStub
       case SymbolicAddress::HandleThrow:              // GenerateThrowStub
       case SymbolicAddress::HandleTrap:               // GenerateTrapExit
-      case SymbolicAddress::ReportOutOfBounds:        // GenerateOutOfBoundsExit
       case SymbolicAddress::ReportUnalignedAccess:    // GenerateUnalignedExit
       case SymbolicAddress::CallImport_Void:          // GenerateImportInterpExit
       case SymbolicAddress::CallImport_I32:
       case SymbolicAddress::CallImport_I64:
       case SymbolicAddress::CallImport_F64:
       case SymbolicAddress::CallImport_Ref:
       case SymbolicAddress::CoerceInPlace_ToInt32:    // GenerateImportJitExit
       case SymbolicAddress::CoerceInPlace_ToNumber:
--- a/js/src/wasm/WasmCode.cpp
+++ b/js/src/wasm/WasmCode.cpp
@@ -273,17 +273,16 @@ SendCodeRangesToProfiler(const ModuleSeg
 }
 
 ModuleSegment::ModuleSegment(Tier tier,
                              UniqueCodeBytes codeBytes,
                              uint32_t codeLength,
                              const LinkDataTier& linkData)
   : CodeSegment(std::move(codeBytes), codeLength, CodeSegment::Kind::Module),
     tier_(tier),
-    outOfBoundsCode_(base() + linkData.outOfBoundsOffset),
     unalignedAccessCode_(base() + linkData.unalignedAccessOffset),
     trapCode_(base() + linkData.trapOffset)
 {
 }
 
 /* static */ UniqueModuleSegment
 ModuleSegment::create(Tier tier, MacroAssembler& masm, const LinkDataTier& linkData)
 {
--- a/js/src/wasm/WasmCode.h
+++ b/js/src/wasm/WasmCode.h
@@ -134,17 +134,16 @@ class CodeSegment
 
 // A wasm ModuleSegment owns the allocated executable code for a wasm module.
 
 typedef UniquePtr<ModuleSegment> UniqueModuleSegment;
 
 class ModuleSegment : public CodeSegment
 {
     const Tier      tier_;
-    uint8_t* const  outOfBoundsCode_;
     uint8_t* const  unalignedAccessCode_;
     uint8_t* const  trapCode_;
 
   public:
     ModuleSegment(Tier tier,
                   UniqueCodeBytes codeBytes,
                   uint32_t codeLength,
                   const LinkDataTier& linkData);
@@ -161,17 +160,16 @@ class ModuleSegment : public CodeSegment
                     const LinkDataTier& linkData,
                     const Metadata& metadata,
                     const MetadataTier& metadataTier);
 
     Tier tier() const { return tier_; }
 
     // Pointers to stubs to which PC is redirected from the signal-handler.
 
-    uint8_t* outOfBoundsCode() const { return outOfBoundsCode_; }
     uint8_t* unalignedAccessCode() const { return unalignedAccessCode_; }
     uint8_t* trapCode() const { return trapCode_; }
 
     // Structured clone support:
 
     size_t serializedSize() const;
     uint8_t* serialize(uint8_t* cursor, const LinkDataTier& linkData) const;
     static const uint8_t* deserialize(const uint8_t* cursor, const LinkDataTier& linkData,
--- a/js/src/wasm/WasmFrameIter.cpp
+++ b/js/src/wasm/WasmFrameIter.cpp
@@ -795,17 +795,16 @@ ProfilingFrameIterator::initFromExitFP(c
         callerFP_ = fp->callerFP;
         AssertMatchesCallSite(callerPC_, callerFP_);
         break;
       case CodeRange::ImportJitExit:
       case CodeRange::ImportInterpExit:
       case CodeRange::BuiltinThunk:
       case CodeRange::TrapExit:
       case CodeRange::DebugTrap:
-      case CodeRange::OutOfBoundsExit:
       case CodeRange::UnalignedExit:
       case CodeRange::Throw:
       case CodeRange::FarJumpIsland:
         MOZ_CRASH("Unexpected CodeRange kind");
     }
 
     MOZ_ASSERT(!done());
 }
@@ -984,17 +983,16 @@ js::wasm::StartUnwinding(const RegisterS
             fixedPC = pc;
             fixedFP = fp;
             *unwoundCaller = false;
             AssertMatchesCallSite(fp->returnAddress, fp->callerFP);
             break;
         }
         break;
       case CodeRange::TrapExit:
-      case CodeRange::OutOfBoundsExit:
       case CodeRange::UnalignedExit:
         // These code stubs execute after the prologue/epilogue have completed
         // so pc/fp contains the right values here.
         fixedPC = pc;
         fixedFP = fp;
         *unwoundCaller = false;
         AssertMatchesCallSite(fp->returnAddress, fp->callerFP);
         break;
@@ -1136,17 +1134,16 @@ ProfilingFrameIterator::operator++()
 
     switch (codeRange_->kind()) {
       case CodeRange::Function:
       case CodeRange::ImportJitExit:
       case CodeRange::ImportInterpExit:
       case CodeRange::BuiltinThunk:
       case CodeRange::TrapExit:
       case CodeRange::DebugTrap:
-      case CodeRange::OutOfBoundsExit:
       case CodeRange::UnalignedExit:
       case CodeRange::FarJumpIsland:
         stackAddress_ = callerFP_;
         callerPC_ = callerFP_->returnAddress;
         AssertMatchesCallSite(callerPC_, callerFP_->callerFP);
         callerFP_ = callerFP_->callerFP;
         break;
       case CodeRange::InterpEntry:
@@ -1163,17 +1160,16 @@ ProfilingFrameIterator::operator++()
 static const char*
 ThunkedNativeToDescription(SymbolicAddress func)
 {
     MOZ_ASSERT(NeedsBuiltinThunk(func));
     switch (func) {
       case SymbolicAddress::HandleDebugTrap:
       case SymbolicAddress::HandleThrow:
       case SymbolicAddress::HandleTrap:
-      case SymbolicAddress::ReportOutOfBounds:
       case SymbolicAddress::ReportUnalignedAccess:
       case SymbolicAddress::CallImport_Void:
       case SymbolicAddress::CallImport_I32:
       case SymbolicAddress::CallImport_I64:
       case SymbolicAddress::CallImport_F64:
       case SymbolicAddress::CallImport_Ref:
       case SymbolicAddress::CoerceInPlace_ToInt32:
       case SymbolicAddress::CoerceInPlace_ToNumber:
@@ -1319,17 +1315,16 @@ ProfilingFrameIterator::label() const
       case CodeRange::Function:          return code_->profilingLabel(codeRange_->funcIndex());
       case CodeRange::InterpEntry:       MOZ_CRASH("should be an ExitReason");
       case CodeRange::JitEntry:          return "fast entry trampoline (in wasm)";
       case CodeRange::ImportJitExit:     return importJitDescription;
       case CodeRange::BuiltinThunk:      return builtinNativeDescription;
       case CodeRange::ImportInterpExit:  return importInterpDescription;
       case CodeRange::TrapExit:          return trapDescription;
       case CodeRange::DebugTrap:         return debugTrapDescription;
-      case CodeRange::OutOfBoundsExit:   return "out-of-bounds stub (in wasm)";
       case CodeRange::UnalignedExit:     return "unaligned trap stub (in wasm)";
       case CodeRange::FarJumpIsland:     return "interstitial (in wasm)";
       case CodeRange::Throw:             MOZ_CRASH("does not have a frame");
     }
 
     MOZ_CRASH("bad code range kind");
 }
 
--- a/js/src/wasm/WasmGenerator.cpp
+++ b/js/src/wasm/WasmGenerator.cpp
@@ -510,20 +510,16 @@ ModuleGenerator::noteCodeRange(uint32_t 
         break;
       case CodeRange::ImportInterpExit:
         metadataTier_->funcImports[codeRange.funcIndex()].initInterpExitOffset(codeRange.begin());
         break;
       case CodeRange::DebugTrap:
         MOZ_ASSERT(!debugTrapCodeOffset_);
         debugTrapCodeOffset_ = codeRange.begin();
         break;
-      case CodeRange::OutOfBoundsExit:
-        MOZ_ASSERT(!linkDataTier_->outOfBoundsOffset);
-        linkDataTier_->outOfBoundsOffset = codeRange.begin();
-        break;
       case CodeRange::UnalignedExit:
         MOZ_ASSERT(!linkDataTier_->unalignedAccessOffset);
         linkDataTier_->unalignedAccessOffset = codeRange.begin();
         break;
       case CodeRange::TrapExit:
         MOZ_ASSERT(!linkDataTier_->trapOffset);
         linkDataTier_->trapOffset = codeRange.begin();
         break;
--- a/js/src/wasm/WasmModule.h
+++ b/js/src/wasm/WasmModule.h
@@ -38,17 +38,16 @@ struct CompileArgs;
 //
 // LinkData is built incrementally by ModuleGenerator and then stored immutably
 // in Module. LinkData is distinct from Metadata in that LinkData is owned and
 // destroyed by the Module since it is not needed after instantiation; Metadata
 // is needed at runtime.
 
 struct LinkDataTierCacheablePod
 {
-    uint32_t outOfBoundsOffset = 0;
     uint32_t unalignedAccessOffset = 0;
     uint32_t trapOffset = 0;
 
     LinkDataTierCacheablePod() = default;
 };
 
 struct LinkDataTier : LinkDataTierCacheablePod
 {
--- a/js/src/wasm/WasmSignalHandlers.cpp
+++ b/js/src/wasm/WasmSignalHandlers.cpp
@@ -735,24 +735,17 @@ MOZ_COLD static MOZ_MUST_USE bool
 HandleOutOfBounds(CONTEXT* context, uint8_t* pc, uint8_t* faultingAddress,
                   const ModuleSegment* segment, const Instance& instance, JitActivation* activation,
                   uint8_t** ppc)
 {
     MOZ_RELEASE_ASSERT(segment->code().containsCodePC(pc));
 
     Trap trap;
     BytecodeOffset bytecode;
-    if (!segment->code().lookupTrap(pc, &trap, &bytecode)) {
-        // If there is no associated TrapSite for the faulting PC, this must be
-        // an Atomics access. When these are converted to non-experimental wasm
-        // features, this case, as well as outOfBoundsCode, can be removed.
-        activation->startWasmTrap(Trap::OutOfBounds, 0, ToRegisterState(context));
-        *ppc = segment->outOfBoundsCode();
-        return true;
-    }
+    MOZ_ALWAYS_TRUE(segment->code().lookupTrap(pc, &trap, &bytecode));
 
     if (trap != Trap::OutOfBounds)
         return false;
 
     if (bytecode.isValid()) {
         activation->startWasmTrap(Trap::OutOfBounds, bytecode.offset(), ToRegisterState(context));
         *ppc = segment->trapCode();
         return true;
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -1623,23 +1623,16 @@ GenerateGenericMemoryAccessTrap(MacroAss
 
     masm.call(reporter);
     masm.jump(throwLabel);
 
     return FinishOffsets(masm, offsets);
 }
 
 static bool
-GenerateOutOfBoundsExit(MacroAssembler& masm, Label* throwLabel, Offsets* offsets)
-{
-    return GenerateGenericMemoryAccessTrap(masm, SymbolicAddress::ReportOutOfBounds, throwLabel,
-                                           offsets);
-}
-
-static bool
 GenerateUnalignedExit(MacroAssembler& masm, Label* throwLabel, Offsets* offsets)
 {
     return GenerateGenericMemoryAccessTrap(masm, SymbolicAddress::ReportUnalignedAccess, throwLabel,
                                            offsets);
 }
 
 // Generate a stub that restores the stack pointer to what it was on entry to
 // the wasm activation, sets the return register to 'false' and then executes a
@@ -1807,21 +1800,16 @@ wasm::GenerateStubs(const ModuleEnvironm
             return false;
         }
     }
 
     JitSpew(JitSpew_Codegen, "# Emitting wasm exit stubs");
 
     Offsets offsets;
 
-    if (!GenerateOutOfBoundsExit(masm, &throwLabel, &offsets))
-        return false;
-    if (!code->codeRanges.emplaceBack(CodeRange::OutOfBoundsExit, offsets))
-        return false;
-
     if (!GenerateUnalignedExit(masm, &throwLabel, &offsets))
         return false;
     if (!code->codeRanges.emplaceBack(CodeRange::UnalignedExit, offsets))
         return false;
 
     if (!GenerateTrapExit(masm, &throwLabel, &offsets))
         return false;
     if (!code->codeRanges.emplaceBack(CodeRange::TrapExit, offsets))
--- a/js/src/wasm/WasmTypes.cpp
+++ b/js/src/wasm/WasmTypes.cpp
@@ -859,17 +859,16 @@ CodeRange::CodeRange(Kind kind, Offsets 
     end_(offsets.end),
     kind_(kind)
 {
     MOZ_ASSERT(begin_ <= end_);
     PodZero(&u);
 #ifdef DEBUG
     switch (kind_) {
       case FarJumpIsland:
-      case OutOfBoundsExit:
       case UnalignedExit:
       case TrapExit:
       case Throw:
         break;
       default:
         MOZ_CRASH("should use more specific constructor");
     }
 #endif
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -1442,17 +1442,16 @@ class CodeRange
         InterpEntry,       // calls into wasm from C++
         JitEntry,          // calls into wasm from jit code
         ImportInterpExit,  // slow-path calling from wasm into C++ interp
         ImportJitExit,     // fast-path calling from wasm into jit code
         BuiltinThunk,      // fast-path calling from wasm into a C++ native
         TrapExit,          // calls C++ to report and jumps to throw stub
         DebugTrap,         // calls C++ to handle debug event
         FarJumpIsland,     // inserted to connect otherwise out-of-range insns
-        OutOfBoundsExit,   // stub jumped to by non-standard asm.js Atomics
         UnalignedExit,     // stub jumped to by wasm Atomics and non-standard
                            // ARM unaligned trap
         Throw              // special stack-unwinding stub jumped to by other stubs
     };
 
   private:
     // All fields are treated as cacheable POD:
     uint32_t begin_;
@@ -1757,17 +1756,16 @@ enum class SymbolicAddress
     NearbyIntF,
     ExpD,
     LogD,
     PowD,
     ATan2D,
     HandleDebugTrap,
     HandleThrow,
     HandleTrap,
-    ReportOutOfBounds,
     ReportUnalignedAccess,
     ReportInt64JSCall,
     CallImport_Void,
     CallImport_I32,
     CallImport_I64,
     CallImport_F64,
     CallImport_Ref,
     CoerceInPlace_ToInt32,