Bug 1284056 - Baldr: rename MachineId to Assumptions (r=bbouvier)

MozReview-Commit-ID: Fo7QeGYo8sI

--HG--
extra : rebase_source : d189e1e5108ed6e49010919395a5df7180d01a1f
This commit is contained in:
Luke Wagner 2016-07-06 08:36:23 -05:00
Родитель 0c68d72e21
Коммит 187268b192
13 изменённых файлов: 164 добавлений и 124 удалений

Просмотреть файл

@ -1754,7 +1754,11 @@ class MOZ_STACK_CLASS ModuleValidator
if (!dummyFunction_)
return false;
UniqueModuleGeneratorData genData = MakeUnique<ModuleGeneratorData>(cx_, ModuleKind::AsmJS);
Assumptions assumptions;
if (!assumptions.init(SignalUsage(cx_), cx_->buildIdOp()))
return false;
auto genData = MakeUnique<ModuleGeneratorData>(assumptions.usesSignal, ModuleKind::AsmJS);
if (!genData ||
!genData->sigs.resize(MaxSigs) ||
!genData->funcSigs.resize(MaxFuncs) ||
@ -1771,7 +1775,7 @@ class MOZ_STACK_CLASS ModuleValidator
return false;
}
if (!mg_.init(Move(genData), Move(filename), asmJSMetadata_.get()))
if (!mg_.init(Move(genData), Move(filename), Move(assumptions), asmJSMetadata_.get()))
return false;
mg_.bumpMinHeapLength(asmJSMetadata_->minHeapLength);
@ -7797,7 +7801,7 @@ CheckBuffer(JSContext* cx, const AsmJSMetadata& metadata, HandleValue bufferVal,
if (buffer->is<ArrayBufferObject>()) {
Rooted<ArrayBufferObject*> abheap(cx, &buffer->as<ArrayBufferObject>());
bool useSignalHandlers = metadata.usesSignal.forOOB;
bool useSignalHandlers = metadata.assumptions.usesSignal.forOOB;
if (!ArrayBufferObject::prepareForAsmJS(cx, abheap, useSignalHandlers))
return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
}
@ -8167,7 +8171,7 @@ class ModuleCharsForStore : ModuleChars
// An unnamed function expression captures the same thing, sans 'f'.
// Since asm.js modules do not contain any free variables, equality of
// [beginOffset, endOffset) is sufficient to guarantee identical code
// generation, modulo MachineId.
// generation, modulo Assumptions.
//
// For functions created with 'new Function', function arguments are
// not present in the source so we must manually explicitly serialize
@ -8307,16 +8311,11 @@ struct ScopedCacheEntryOpenedForRead
static JS::AsmJSCacheResult
StoreAsmJSModuleInCache(AsmJSParser& parser, Module& module, ExclusiveContext* cx)
{
MachineId machineId;
if (!machineId.extractCurrentState(cx))
return JS::AsmJSCache_InternalError;
ModuleCharsForStore moduleChars;
if (!moduleChars.init(parser))
return JS::AsmJSCache_InternalError;
size_t serializedSize = machineId.serializedSize() +
moduleChars.serializedSize() +
size_t serializedSize = moduleChars.serializedSize() +
module.serializedSize();
JS::OpenAsmJSCacheEntryForWriteOp open = cx->asmJSCacheOps().openEntryForWrite;
@ -8334,7 +8333,6 @@ StoreAsmJSModuleInCache(AsmJSParser& parser, Module& module, ExclusiveContext* c
return openResult;
uint8_t* cursor = entry.memory;
cursor = machineId.serialize(cursor);
cursor = moduleChars.serialize(cursor);
cursor = module.serialize(cursor);
@ -8350,10 +8348,6 @@ LookupAsmJSModuleInCache(ExclusiveContext* cx, AsmJSParser& parser, bool* loaded
*loadedFromCache = false;
MachineId machineId;
if (!machineId.extractCurrentState(cx))
return true;
JS::OpenAsmJSCacheEntryForReadOp open = cx->asmJSCacheOps().openEntryForRead;
if (!open)
return true;
@ -8367,13 +8361,6 @@ LookupAsmJSModuleInCache(ExclusiveContext* cx, AsmJSParser& parser, bool* loaded
const uint8_t* cursor = entry.memory;
MachineId cachedMachineId;
cursor = cachedMachineId.deserialize(cursor);
if (!cursor)
return false;
if (machineId != cachedMachineId)
return true;
ModuleCharsForLookup moduleChars;
cursor = moduleChars.deserialize(cursor);
if (!moduleChars.match(parser))
@ -8400,7 +8387,11 @@ LookupAsmJSModuleInCache(ExclusiveContext* cx, AsmJSParser& parser, bool* loaded
if (!atEnd)
return true;
if (asmJSMetadata->usesSignal != SignalUsage(cx))
Assumptions assumptions;
if (!assumptions.init(SignalUsage(cx), cx->buildIdOp()))
return true;
if (assumptions != (*module)->metadata().assumptions)
return true;
if (!parser.tokenStream.advance(asmJSMetadata->srcEndBeforeCurly()))

Просмотреть файл

@ -26,6 +26,7 @@
#include "asmjs/WasmModule.h"
#include "asmjs/WasmSerialize.h"
#include "jit/ExecutableAllocator.h"
#include "jit/MacroAssembler.h"
#ifdef JS_ION_PERF
# include "jit/PerfSpewer.h"
#endif
@ -457,7 +458,8 @@ Metadata::serializedSize() const
SerializedPodVectorSize(callSites) +
SerializedPodVectorSize(callThunks) +
SerializedPodVectorSize(funcNames) +
filename.serializedSize();
filename.serializedSize() +
assumptions.serializedSize();
}
uint8_t*
@ -473,6 +475,7 @@ Metadata::serialize(uint8_t* cursor) const
cursor = SerializePodVector(cursor, callThunks);
cursor = SerializePodVector(cursor, funcNames);
cursor = filename.serialize(cursor);
cursor = assumptions.serialize(cursor);
return cursor;
}
@ -488,7 +491,8 @@ Metadata::deserialize(const uint8_t* cursor)
(cursor = DeserializePodVector(cursor, &callSites)) &&
(cursor = DeserializePodVector(cursor, &callThunks)) &&
(cursor = DeserializePodVector(cursor, &funcNames)) &&
(cursor = filename.deserialize(cursor));
(cursor = filename.deserialize(cursor)) &&
(cursor = assumptions.deserialize(cursor));
return cursor;
}
@ -503,7 +507,8 @@ Metadata::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
callSites.sizeOfExcludingThis(mallocSizeOf) +
callThunks.sizeOfExcludingThis(mallocSizeOf) +
funcNames.sizeOfExcludingThis(mallocSizeOf) +
filename.sizeOfExcludingThis(mallocSizeOf);
filename.sizeOfExcludingThis(mallocSizeOf) +
assumptions.sizeOfExcludingThis(mallocSizeOf);
}
bool

Просмотреть файл

@ -412,7 +412,6 @@ typedef Vector<char16_t, 64> TwoByteName;
struct MetadataCacheablePod
{
ModuleKind kind;
SignalUsage usesSignal;
HeapUsage heapUsage;
uint32_t initialHeapLength;
@ -435,6 +434,7 @@ struct Metadata : ShareableBase<Metadata>, MetadataCacheablePod
CallThunkVector callThunks;
NameInBytecodeVector funcNames;
CacheableChars filename;
Assumptions assumptions;
bool usesHeap() const { return UsesHeap(heapUsage); }
bool hasSharedHeap() const { return heapUsage == HeapUsage::Shared; }

Просмотреть файл

@ -1083,9 +1083,9 @@ DecodeUnknownSections(JSContext* cx, Decoder& d)
}
static UniqueModule
DecodeModule(JSContext* cx, UniqueChars file, const ShareableBytes& bytecode)
DecodeModule(JSContext* cx, UniqueChars file, Assumptions&& assumptions, const ShareableBytes& bytecode)
{
UniqueModuleGeneratorData init = js::MakeUnique<ModuleGeneratorData>(cx);
auto init = js::MakeUnique<ModuleGeneratorData>(assumptions.usesSignal);
if (!init)
return nullptr;
@ -1108,7 +1108,7 @@ DecodeModule(JSContext* cx, UniqueChars file, const ShareableBytes& bytecode)
return nullptr;
ModuleGenerator mg(cx);
if (!mg.init(Move(init), Move(file)))
if (!mg.init(Move(init), Move(file), Move(assumptions)))
return nullptr;
if (!DecodeMemorySection(cx, d, mg))
@ -1133,7 +1133,7 @@ DecodeModule(JSContext* cx, UniqueChars file, const ShareableBytes& bytecode)
}
UniqueModule
wasm::Compile(JSContext* cx, UniqueChars file, Bytes&& bytecode)
wasm::Compile(JSContext* cx, UniqueChars file, Assumptions&& assumptions, Bytes&& bytecode)
{
MOZ_ASSERT(HasCompilerSupport(cx));
@ -1141,7 +1141,7 @@ wasm::Compile(JSContext* cx, UniqueChars file, Bytes&& bytecode)
if (!sharedBytes)
return nullptr;
UniqueModule module = DecodeModule(cx, Move(file), *sharedBytes);
UniqueModule module = DecodeModule(cx, Move(file), Move(assumptions), *sharedBytes);
if (!module) {
if (!cx->isExceptionPending())
ReportOutOfMemory(cx);

Просмотреть файл

@ -21,6 +21,7 @@
#include "asmjs/WasmBinary.h"
#include "asmjs/WasmJS.h"
#include "asmjs/WasmTypes.h"
namespace js {
namespace wasm {
@ -29,7 +30,7 @@ namespace wasm {
// wasm::Module.
UniqueModule
Compile(JSContext* cx, UniqueChars filename, Bytes&& code);
Compile(JSContext* cx, UniqueChars filename, Assumptions&& assumptions, Bytes&& code);
} // namespace wasm
} // namespace js

Просмотреть файл

@ -112,7 +112,8 @@ ParallelCompilationEnabled(ExclusiveContext* cx)
}
bool
ModuleGenerator::init(UniqueModuleGeneratorData shared, UniqueChars file, Metadata* maybeMetadata)
ModuleGenerator::init(UniqueModuleGeneratorData shared, UniqueChars file, Assumptions&& assumptions,
Metadata* maybeMetadata)
{
if (!funcIndexToExport_.init())
return false;
@ -129,9 +130,9 @@ ModuleGenerator::init(UniqueModuleGeneratorData shared, UniqueChars file, Metada
}
metadata_->kind = shared->kind;
metadata_->usesSignal = shared->usesSignal;
metadata_->heapUsage = HeapUsage::None;
metadata_->filename = Move(file);
metadata_->assumptions = Move(assumptions);
shared_ = Move(shared);

Просмотреть файл

@ -77,8 +77,8 @@ struct ModuleGeneratorData
return funcSigs[funcIndex] - sigs.begin();
}
explicit ModuleGeneratorData(ExclusiveContext* cx, ModuleKind kind = ModuleKind::Wasm)
: kind(kind), usesSignal(cx), minHeapLength(0)
explicit ModuleGeneratorData(SignalUsage usesSignal, ModuleKind kind = ModuleKind::Wasm)
: kind(kind), usesSignal(usesSignal), minHeapLength(0)
{}
};
@ -142,10 +142,11 @@ class MOZ_STACK_CLASS ModuleGenerator
MOZ_MUST_USE bool init(UniqueModuleGeneratorData shared,
UniqueChars filename,
Assumptions&& assumptions,
Metadata* maybeMetadata = nullptr);
bool isAsmJS() const { return metadata_->kind == ModuleKind::AsmJS; }
SignalUsage usesSignal() const { return metadata_->usesSignal; }
SignalUsage usesSignal() const { return metadata_->assumptions.usesSignal; }
jit::MacroAssembler& masm() { return masm_; }
// Heap usage:

Просмотреть файл

@ -130,7 +130,11 @@ wasm::Eval(JSContext* cx, Handle<TypedArrayObject*> code, HandleObject importObj
return false;
}
UniqueModule module = Compile(cx, Move(filename), Move(bytecode));
Assumptions assumptions;
if (!assumptions.init(SignalUsage(cx), cx->buildIdOp()))
return true;
UniqueModule module = Compile(cx, Move(filename), Move(assumptions), Move(bytecode));
if (!module)
return false;
@ -319,10 +323,14 @@ ModuleConstructor(JSContext* cx, unsigned argc, Value* vp)
return false;
}
Assumptions assumptions;
if (!assumptions.init(SignalUsage(cx), cx->buildIdOp()))
return true;
if (!CheckCompilerSupport(cx))
return false;
UniqueModule module = Compile(cx, Move(filename), Move(bytecode));
UniqueModule module = Compile(cx, Move(filename), Move(assumptions), Move(bytecode));
if (!module)
return false;

Просмотреть файл

@ -339,7 +339,7 @@ Module::instantiate(JSContext* cx,
if (metadata_->usesHeap() && !heap) {
MOZ_ASSERT(!metadata_->isAsmJS());
heap = ArrayBufferObject::createForWasm(cx, metadata_->initialHeapLength,
metadata_->usesSignal.forOOB);
metadata_->assumptions.usesSignal.forOOB);
if (!heap)
return false;
}

Просмотреть файл

@ -19,7 +19,7 @@
#ifndef wasm_serialize_h
#define wasm_serialize_h
#include "jit/MacroAssembler.h"
#include "js/Vector.h"
namespace js {
namespace wasm {
@ -132,86 +132,6 @@ DeserializePodVector(const uint8_t* cursor, mozilla::Vector<T, N, SystemAllocPol
return cursor;
}
static inline MOZ_MUST_USE bool
GetCPUID(uint32_t* cpuId)
{
enum Arch {
X86 = 0x1,
X64 = 0x2,
ARM = 0x3,
MIPS = 0x4,
MIPS64 = 0x5,
ARCH_BITS = 3
};
#if defined(JS_CODEGEN_X86)
MOZ_ASSERT(uint32_t(jit::CPUInfo::GetSSEVersion()) <= (UINT32_MAX >> ARCH_BITS));
*cpuId = X86 | (uint32_t(jit::CPUInfo::GetSSEVersion()) << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_X64)
MOZ_ASSERT(uint32_t(jit::CPUInfo::GetSSEVersion()) <= (UINT32_MAX >> ARCH_BITS));
*cpuId = X64 | (uint32_t(jit::CPUInfo::GetSSEVersion()) << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_ARM)
MOZ_ASSERT(jit::GetARMFlags() <= (UINT32_MAX >> ARCH_BITS));
*cpuId = ARM | (jit::GetARMFlags() << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_MIPS32)
MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS));
*cpuId = MIPS | (jit::GetMIPSFlags() << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_MIPS64)
MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS));
*cpuId = MIPS64 | (jit::GetMIPSFlags() << ARCH_BITS);
return true;
#else
return false;
#endif
}
class MachineId
{
uint32_t cpuId_;
JS::BuildIdCharVector buildId_;
public:
MOZ_MUST_USE bool extractCurrentState(ExclusiveContext* cx) {
if (!cx->buildIdOp())
return false;
if (!cx->buildIdOp()(&buildId_))
return false;
if (!GetCPUID(&cpuId_))
return false;
return true;
}
size_t serializedSize() const {
return sizeof(uint32_t) +
SerializedPodVectorSize(buildId_);
}
uint8_t* serialize(uint8_t* cursor) const {
cursor = WriteScalar<uint32_t>(cursor, cpuId_);
cursor = SerializePodVector(cursor, buildId_);
return cursor;
}
const uint8_t* deserialize(const uint8_t* cursor) {
(cursor = ReadScalar<uint32_t>(cursor, &cpuId_)) &&
(cursor = DeserializePodVector(cursor, &buildId_));
return cursor;
}
bool operator==(const MachineId& rhs) const {
return cpuId_ == rhs.cpuId_ &&
buildId_.length() == rhs.buildId_.length() &&
mozilla::PodEqual(buildId_.begin(), rhs.buildId_.begin(), buildId_.length());
}
bool operator!=(const MachineId& rhs) const {
return !(*this == rhs);
}
};
} // namespace wasm
} // namespace js

Просмотреть файл

@ -604,7 +604,7 @@ EmulateHeapAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddre
const MemoryAccess* memoryAccess, const Instance& instance)
{
MOZ_RELEASE_ASSERT(instance.codeSegment().containsFunctionPC(pc));
MOZ_RELEASE_ASSERT(instance.metadata().usesSignal.forOOB);
MOZ_RELEASE_ASSERT(instance.metadata().assumptions.usesSignal.forOOB);
MOZ_RELEASE_ASSERT(memoryAccess->insnOffset() == (pc - instance.codeSegment().code()));
// Disassemble the instruction which caused the trap so that we can extract

Просмотреть файл

@ -24,7 +24,8 @@
#include "jsmath.h"
#include "asmjs/WasmInstance.h"
#include "jit/shared/Assembler-shared.h"
#include "asmjs/WasmSerialize.h"
#include "jit/MacroAssembler.h"
#include "js/Conversions.h"
#include "vm/Interpreter.h"
@ -290,3 +291,95 @@ SignalUsage::operator==(SignalUsage rhs) const
{
return forOOB == rhs.forOOB && forInterrupt == rhs.forInterrupt;
}
static inline MOZ_MUST_USE bool
GetCPUID(uint32_t* cpuId)
{
enum Arch {
X86 = 0x1,
X64 = 0x2,
ARM = 0x3,
MIPS = 0x4,
MIPS64 = 0x5,
ARCH_BITS = 3
};
#if defined(JS_CODEGEN_X86)
MOZ_ASSERT(uint32_t(jit::CPUInfo::GetSSEVersion()) <= (UINT32_MAX >> ARCH_BITS));
*cpuId = X86 | (uint32_t(jit::CPUInfo::GetSSEVersion()) << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_X64)
MOZ_ASSERT(uint32_t(jit::CPUInfo::GetSSEVersion()) <= (UINT32_MAX >> ARCH_BITS));
*cpuId = X64 | (uint32_t(jit::CPUInfo::GetSSEVersion()) << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_ARM)
MOZ_ASSERT(jit::GetARMFlags() <= (UINT32_MAX >> ARCH_BITS));
*cpuId = ARM | (jit::GetARMFlags() << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_MIPS32)
MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS));
*cpuId = MIPS | (jit::GetMIPSFlags() << ARCH_BITS);
return true;
#elif defined(JS_CODEGEN_MIPS64)
MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS));
*cpuId = MIPS64 | (jit::GetMIPSFlags() << ARCH_BITS);
return true;
#else
return false;
#endif
}
MOZ_MUST_USE bool
Assumptions::init(SignalUsage usesSignal, JS::BuildIdOp buildIdOp)
{
this->usesSignal = usesSignal;
if (!GetCPUID(&cpuId))
return false;
if (!buildIdOp || !buildIdOp(&buildId))
return false;
return true;
}
bool
Assumptions::operator==(const Assumptions& rhs) const
{
return usesSignal == rhs.usesSignal &&
cpuId == rhs.cpuId &&
buildId.length() == rhs.buildId.length() &&
PodEqual(buildId.begin(), rhs.buildId.begin(), buildId.length());
}
size_t
Assumptions::serializedSize() const
{
return sizeof(usesSignal) +
sizeof(uint32_t) +
SerializedPodVectorSize(buildId);
}
uint8_t*
Assumptions::serialize(uint8_t* cursor) const
{
cursor = WriteBytes(cursor, &usesSignal, sizeof(usesSignal));
cursor = WriteScalar<uint32_t>(cursor, cpuId);
cursor = SerializePodVector(cursor, buildId);
return cursor;
}
const uint8_t*
Assumptions::deserialize(const uint8_t* cursor)
{
(cursor = ReadBytes(cursor, &usesSignal, sizeof(usesSignal))) &&
(cursor = ReadScalar<uint32_t>(cursor, &cpuId)) &&
(cursor = DeserializePodVector(cursor, &buildId));
return cursor;
}
size_t
Assumptions::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
{
return buildId.sizeOfExcludingThis(mallocSizeOf);
}

Просмотреть файл

@ -49,6 +49,7 @@ using mozilla::Move;
using mozilla::MallocSizeOf;
using mozilla::PodZero;
using mozilla::PodCopy;
using mozilla::PodEqual;
using mozilla::RefCounted;
typedef Vector<uint32_t, 0, SystemAllocPolicy> Uint32Vector;
@ -774,6 +775,7 @@ typedef EnumeratedArray<JumpTarget, JumpTarget::Limit, Uint32Vector> JumpSiteArr
struct SignalUsage
{
// NB: these fields are serialized as a POD in Assumptions.
bool forOOB;
bool forInterrupt;
@ -783,6 +785,24 @@ struct SignalUsage
bool operator!=(SignalUsage rhs) const { return !(*this == rhs); }
};
// Assumptions captures ambient state that must be the same when compiling and
// deserializing a module for the compiled code to be valid. If it's not, then
// the module must be recompiled from scratch.
struct Assumptions
{
SignalUsage usesSignal;
uint32_t cpuId;
JS::BuildIdCharVector buildId;
MOZ_MUST_USE bool init(SignalUsage usesSignal, JS::BuildIdOp buildIdOp);
bool operator==(const Assumptions& rhs) const;
bool operator!=(const Assumptions& rhs) const { return !(*this == rhs); }
WASM_DECLARE_SERIALIZABLE(Assumptions)
};
// A Module can either be asm.js or wasm.
enum ModuleKind