From b1470f953773926b8f48705fe2c855a32bd0fffb Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 30 Jun 2016 14:42:09 +0200 Subject: [PATCH] Bug 1268024: Add an unaligned access trap; r=luke MozReview-Commit-ID: HvAF3lvlfw3 --HG-- extra : rebase_source : 4c326dd9af59cc0df9e1351786c3d3739fa27e0f extra : histedit_source : 2e530129632340c6c1f1f465668aecc12c559abf --- js/src/asmjs/WasmCode.cpp | 1 + js/src/asmjs/WasmCode.h | 4 +++- js/src/asmjs/WasmGenerator.cpp | 1 + js/src/asmjs/WasmJS.cpp | 3 +++ js/src/asmjs/WasmModule.h | 1 + js/src/asmjs/WasmStubs.cpp | 1 + js/src/asmjs/WasmTypes.cpp | 3 +++ js/src/asmjs/WasmTypes.h | 3 +++ js/src/jit/Ion.cpp | 6 ++++++ js/src/jit/Ion.h | 1 + js/src/jit/arm/Architecture-arm.cpp | 9 +++++++-- js/src/jit/arm/Architecture-arm.h | 1 + js/src/jit/arm/Assembler-arm.h | 3 +++ js/src/jit/arm64/Assembler-arm64.h | 1 + js/src/jit/x86-shared/Assembler-x86-shared.h | 1 + js/src/js.msg | 1 + js/src/jscntxt.h | 1 + js/src/vm/Runtime.cpp | 2 ++ js/src/vm/Runtime.h | 5 +++-- 19 files changed, 43 insertions(+), 5 deletions(-) diff --git a/js/src/asmjs/WasmCode.cpp b/js/src/asmjs/WasmCode.cpp index cae6f52b6270..85b8edc12e9f 100644 --- a/js/src/asmjs/WasmCode.cpp +++ b/js/src/asmjs/WasmCode.cpp @@ -213,6 +213,7 @@ CodeSegment::create(JSContext* cx, cs->globalDataLength_ = linkData.globalDataLength; cs->interruptCode_ = cs->code() + linkData.interruptOffset; cs->outOfBoundsCode_ = cs->code() + linkData.outOfBoundsOffset; + cs->unalignedAccessCode_ = cs->code() + linkData.unalignedAccessOffset; { JitContext jcx(CompileRuntime::get(cx->compartment()->runtimeFromAnyThread())); diff --git a/js/src/asmjs/WasmCode.h b/js/src/asmjs/WasmCode.h index 938afea50466..b4f09105b770 100644 --- a/js/src/asmjs/WasmCode.h +++ b/js/src/asmjs/WasmCode.h @@ -47,10 +47,11 @@ class CodeSegment uint32_t codeLength_; uint32_t globalDataLength_; - // These are pointers into code for two stubs used for asynchronous + // These are pointers into code for stubs used for asynchronous // signal-handler control-flow transfer. uint8_t* interruptCode_; uint8_t* outOfBoundsCode_; + uint8_t* unalignedAccessCode_; // The profiling mode may be changed dynamically. bool profilingEnabled_; @@ -80,6 +81,7 @@ class CodeSegment uint8_t* interruptCode() const { return interruptCode_; } uint8_t* outOfBoundsCode() const { return outOfBoundsCode_; } + uint8_t* unalignedAccessCode() const { return unalignedAccessCode_; } // The range [0, functionBytes) is a subrange of [0, codeBytes) that // contains only function body code, not the stub code. This distinction is diff --git a/js/src/asmjs/WasmGenerator.cpp b/js/src/asmjs/WasmGenerator.cpp index c288b0271154..434a65723eaf 100644 --- a/js/src/asmjs/WasmGenerator.cpp +++ b/js/src/asmjs/WasmGenerator.cpp @@ -419,6 +419,7 @@ ModuleGenerator::finishCodegen() // Fill in LinkData with the offsets of these stubs. linkData_.outOfBoundsOffset = jumpTargets[JumpTarget::OutOfBounds].begin; + linkData_.unalignedAccessOffset = jumpTargets[JumpTarget::UnalignedAccess].begin; linkData_.interruptOffset = interruptExit.begin; // Only call convertOutOfRangeBranchesToThunks after all other codegen that may diff --git a/js/src/asmjs/WasmJS.cpp b/js/src/asmjs/WasmJS.cpp index 96c476e6b985..31a752ec7afa 100644 --- a/js/src/asmjs/WasmJS.cpp +++ b/js/src/asmjs/WasmJS.cpp @@ -35,6 +35,9 @@ wasm::HasCompilerSupport(ExclusiveContext* cx) if (!cx->jitSupportsFloatingPoint()) return false; + if (!cx->jitSupportsUnalignedAccesses()) + return false; + #if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64) return false; #else diff --git a/js/src/asmjs/WasmModule.h b/js/src/asmjs/WasmModule.h index b29369b659d1..a3788ed8ab9e 100644 --- a/js/src/asmjs/WasmModule.h +++ b/js/src/asmjs/WasmModule.h @@ -41,6 +41,7 @@ struct LinkDataCacheablePod uint32_t globalDataLength; uint32_t interruptOffset; uint32_t outOfBoundsOffset; + uint32_t unalignedAccessOffset; LinkDataCacheablePod() { mozilla::PodZero(this); } }; diff --git a/js/src/asmjs/WasmStubs.cpp b/js/src/asmjs/WasmStubs.cpp index 5d5e634b7692..1cb296be3de6 100644 --- a/js/src/asmjs/WasmStubs.cpp +++ b/js/src/asmjs/WasmStubs.cpp @@ -934,6 +934,7 @@ wasm::GenerateJumpTarget(MacroAssembler& masm, JumpTarget target) return GenerateThrow(masm); case JumpTarget::BadIndirectCall: case JumpTarget::OutOfBounds: + case JumpTarget::UnalignedAccess: case JumpTarget::Unreachable: case JumpTarget::IntegerOverflow: case JumpTarget::InvalidConversionToInteger: diff --git a/js/src/asmjs/WasmTypes.cpp b/js/src/asmjs/WasmTypes.cpp index 869c97ad850e..bf72cf6e74f9 100644 --- a/js/src/asmjs/WasmTypes.cpp +++ b/js/src/asmjs/WasmTypes.cpp @@ -124,6 +124,9 @@ HandleTrap(int32_t trapIndex) case Trap::OutOfBounds: errorNumber = JSMSG_BAD_INDEX; break; + case Trap::UnalignedAccess: + errorNumber = JSMSG_WASM_UNALIGNED_ACCESS; + break; default: MOZ_CRASH("unexpected trap"); } diff --git a/js/src/asmjs/WasmTypes.h b/js/src/asmjs/WasmTypes.h index 95380d35b1d3..0aa1dbb7464d 100644 --- a/js/src/asmjs/WasmTypes.h +++ b/js/src/asmjs/WasmTypes.h @@ -732,6 +732,8 @@ enum class Trap IntegerDivideByZero, // Out of bounds on wasm memory accesses and asm.js SIMD/atomic accesses. OutOfBounds, + // Unaligned memory access. + UnalignedAccess, // Bad signature for an indirect call. BadIndirectCall, @@ -755,6 +757,7 @@ enum class JumpTarget InvalidConversionToInteger = unsigned(Trap::InvalidConversionToInteger), IntegerDivideByZero = unsigned(Trap::IntegerDivideByZero), OutOfBounds = unsigned(Trap::OutOfBounds), + UnalignedAccess = unsigned(Trap::UnalignedAccess), BadIndirectCall = unsigned(Trap::BadIndirectCall), ImpreciseSimdConversion = unsigned(Trap::ImpreciseSimdConversion), // Non-traps diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 86bfe5717fb5..7a69974f063c 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -3477,6 +3477,12 @@ jit::JitSupportsFloatingPoint() return js::jit::MacroAssembler::SupportsFloatingPoint(); } +bool +jit::JitSupportsUnalignedAccesses() +{ + return js::jit::MacroAssembler::SupportsUnalignedAccesses(); +} + bool jit::JitSupportsSimd() { diff --git a/js/src/jit/Ion.h b/js/src/jit/Ion.h index c2a6062549fb..304e3f429b0d 100644 --- a/js/src/jit/Ion.h +++ b/js/src/jit/Ion.h @@ -203,6 +203,7 @@ void DestroyJitScripts(FreeOp* fop, JSScript* script); void TraceJitScripts(JSTracer* trc, JSScript* script); bool JitSupportsFloatingPoint(); +bool JitSupportsUnalignedAccesses(); bool JitSupportsSimd(); bool JitSupportsAtomics(); diff --git a/js/src/jit/arm/Architecture-arm.cpp b/js/src/jit/arm/Architecture-arm.cpp index 28913e068184..afbf628159d8 100644 --- a/js/src/jit/arm/Architecture-arm.cpp +++ b/js/src/jit/arm/Architecture-arm.cpp @@ -6,7 +6,7 @@ #include "jit/arm/Architecture-arm.h" -#if !defined(JS_ARM_SIMULATOR) && !defined(__APPLE__) +#if !defined(JS_SIMULATOR_ARM) && !defined(__APPLE__) #include #endif @@ -41,7 +41,6 @@ namespace js { namespace jit { - // Parse the Linux kernel cpuinfo features. This is also used to parse the // override features which has some extensions: 'armv7', 'align' and 'hardfp'. static uint32_t @@ -269,6 +268,12 @@ GetARMFlags() return armHwCapFlags; } +bool HasARMv7() +{ + MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED); + return armHwCapFlags & HWCAP_ARMv7; +} + bool HasMOVWT() { MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED); diff --git a/js/src/jit/arm/Architecture-arm.h b/js/src/jit/arm/Architecture-arm.h index d88921095564..dc38db732fe3 100644 --- a/js/src/jit/arm/Architecture-arm.h +++ b/js/src/jit/arm/Architecture-arm.h @@ -576,6 +576,7 @@ class VFPRegister typedef VFPRegister FloatRegister; uint32_t GetARMFlags(); +bool HasARMv7(); bool HasMOVWT(); bool HasLDSTREXBHD(); // {LD,ST}REX{B,H,D} bool HasDMBDSBISB(); // DMB, DSB, and ISB diff --git a/js/src/jit/arm/Assembler-arm.h b/js/src/jit/arm/Assembler-arm.h index 2fb94faf2815..7b47f50d4b23 100644 --- a/js/src/jit/arm/Assembler-arm.h +++ b/js/src/jit/arm/Assembler-arm.h @@ -1752,6 +1752,9 @@ class Assembler : public AssemblerShared static bool SupportsFloatingPoint() { return HasVFP(); } + static bool SupportsUnalignedAccesses() { + return HasARMv7(); + } static bool SupportsSimd() { return js::jit::SupportsSimd; } diff --git a/js/src/jit/arm64/Assembler-arm64.h b/js/src/jit/arm64/Assembler-arm64.h index 0218973682a6..dfb78371ce70 100644 --- a/js/src/jit/arm64/Assembler-arm64.h +++ b/js/src/jit/arm64/Assembler-arm64.h @@ -287,6 +287,7 @@ class Assembler : public vixl::Assembler } static bool SupportsFloatingPoint() { return true; } + static bool SupportsUnalignedAccesses() { return true; } static bool SupportsSimd() { return js::jit::SupportsSimd; } // Tracks a jump that is patchable after finalization. diff --git a/js/src/jit/x86-shared/Assembler-x86-shared.h b/js/src/jit/x86-shared/Assembler-x86-shared.h index 93b9883dcb0f..c22a1b7494db 100644 --- a/js/src/jit/x86-shared/Assembler-x86-shared.h +++ b/js/src/jit/x86-shared/Assembler-x86-shared.h @@ -1101,6 +1101,7 @@ class AssemblerX86Shared : public AssemblerShared static bool HasSSE41() { return CPUInfo::IsSSE41Present(); } static bool HasPOPCNT() { return CPUInfo::IsPOPCNTPresent(); } static bool SupportsFloatingPoint() { return CPUInfo::IsSSE2Present(); } + static bool SupportsUnalignedAccesses() { return true; } static bool SupportsSimd() { return CPUInfo::IsSSE2Present(); } static bool HasAVX() { return CPUInfo::IsAVXPresent(); } diff --git a/js/src/js.msg b/js/src/js.msg index d0a76870ca4d..8c108109fddd 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -352,6 +352,7 @@ MSG_DEF(JSMSG_WASM_UNREACHABLE, 0, JSEXN_ERR, "unreachable execut MSG_DEF(JSMSG_WASM_INTEGER_OVERFLOW, 0, JSEXN_ERR, "integer overflow") MSG_DEF(JSMSG_WASM_INVALID_CONVERSION, 0, JSEXN_ERR, "invalid conversion to integer") MSG_DEF(JSMSG_WASM_INT_DIVIDE_BY_ZERO, 0, JSEXN_ERR, "integer divide by zero") +MSG_DEF(JSMSG_WASM_UNALIGNED_ACCESS, 0, JSEXN_ERR, "unaligned memory access") MSG_DEF(JSMSG_WASM_OVERRECURSED, 0, JSEXN_INTERNALERR, "call stack exhausted") // Proxy diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 80b2dd67214b..9249f48f7073 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -210,6 +210,7 @@ class ExclusiveContext : public ContextFriendFields, size_t gcSystemPageSize() { return gc::SystemPageSize(); } bool canUseSignalHandlers() const { return runtime_->canUseSignalHandlers(); } bool jitSupportsFloatingPoint() const { return runtime_->jitSupportsFloatingPoint; } + bool jitSupportsUnalignedAccesses() const { return runtime_->jitSupportsUnalignedAccesses; } bool jitSupportsSimd() const { return runtime_->jitSupportsSimd; } bool lcovEnabled() const { return runtime_->lcovOutput.isEnabled(); } diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 0dde7d0666a1..6ef14df5fac7 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -238,6 +238,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime) wrapObjectCallbacks(&DefaultWrapObjectCallbacks), preserveWrapperCallback(nullptr), jitSupportsFloatingPoint(false), + jitSupportsUnalignedAccesses(false), jitSupportsSimd(false), ionPcScriptCache(nullptr), scriptEnvironmentPreparer(nullptr), @@ -350,6 +351,7 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes) #endif jitSupportsFloatingPoint = js::jit::JitSupportsFloatingPoint(); + jitSupportsUnalignedAccesses = js::jit::JitSupportsUnalignedAccesses(); jitSupportsSimd = js::jit::JitSupportsSimd(); signalHandlersInstalled_ = wasm::EnsureSignalHandlersInstalled(this); diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index c6b079275491..4332e0b393a2 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1186,8 +1186,9 @@ struct JSRuntime : public JS::shadow::Runtime, return scriptDataTable_; } - bool jitSupportsFloatingPoint; - bool jitSupportsSimd; + bool jitSupportsFloatingPoint; + bool jitSupportsUnalignedAccesses; + bool jitSupportsSimd; // Cache for jit::GetPcScript(). js::jit::PcScriptCache* ionPcScriptCache;