mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 09:18:42 +09:00
Security fixes toward Firefox 58 level but might miss some. Check later.
Security fixes toward Firefox 58 level but might miss some. Check later.
This commit is contained in:
parent
1f0c1ad851
commit
98e863440f
20 changed files with 222 additions and 74 deletions
|
|
@ -132,6 +132,12 @@ function loadCallgraph(file)
|
|||
addGCFunction(func, "annotation");
|
||||
}
|
||||
|
||||
// mess up the id <-> name correspondence. Also, we need to know if the
|
||||
// functions even exist in the first place.)
|
||||
for (var func of extraGCFunctions()) {
|
||||
addGCFunction(func, "annotation");
|
||||
}
|
||||
|
||||
// Initialize suppressedFunctions to the set of all functions, and the
|
||||
// worklist to all toplevel callers.
|
||||
var worklist = [];
|
||||
|
|
|
|||
|
|
@ -1020,7 +1020,7 @@ class MOZ_STACK_CLASS TokenStream
|
|||
return true;
|
||||
}
|
||||
|
||||
void skipChars(uint8_t n) {
|
||||
void skipChars(uint32_t n) {
|
||||
while (n-- > 0) {
|
||||
MOZ_ASSERT(userbuf.hasRawChars());
|
||||
mozilla::DebugOnly<int32_t> c = getCharIgnoreEOL();
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "jit/MacroAssembler-inl.h"
|
||||
#include "vm/Interpreter-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
#include "vm/TypeInference-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
|
@ -97,7 +98,8 @@ BaselineCompiler::compile()
|
|||
AutoTraceLog logScript(logger, scriptEvent);
|
||||
AutoTraceLog logCompile(logger, TraceLogger_BaselineCompilation);
|
||||
|
||||
if (!script->ensureHasTypes(cx) || !script->ensureHasAnalyzedArgsUsage(cx))
|
||||
AutoKeepTypeScripts keepTypes(cx);
|
||||
if (!script->ensureHasTypes(cx, keepTypes) || !script->ensureHasAnalyzedArgsUsage(cx))
|
||||
return Method_Error;
|
||||
|
||||
// When code coverage is only enabled for optimizations, or when a Debugger
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "jit/JitFrames-inl.h"
|
||||
#include "jit/MacroAssembler-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/TypeInference-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
|
@ -670,6 +671,7 @@ RecompileBaselineScriptForDebugMode(JSContext* cx, JSScript* script,
|
|||
JitSpew(JitSpew_BaselineDebugModeOSR, "Recompiling (%s:%" PRIuSIZE ") for %s",
|
||||
script->filename(), script->lineno(), observing ? "DEBUGGING" : "NORMAL EXECUTION");
|
||||
|
||||
AutoKeepTypeScripts keepTypes(cx);
|
||||
script->setBaselineScript(cx->runtime(), nullptr);
|
||||
|
||||
MethodStatus status = BaselineCompile(cx, script, /* forceDebugMode = */ observing);
|
||||
|
|
|
|||
|
|
@ -4180,7 +4180,8 @@ jit::AnalyzeArgumentsUsage(JSContext* cx, JSScript* scriptArg)
|
|||
if (script->length() > MAX_SCRIPT_SIZE)
|
||||
return true;
|
||||
|
||||
if (!script->ensureHasTypes(cx))
|
||||
AutoKeepTypeScripts keepTypes(cx);
|
||||
if (!script->ensureHasTypes(cx, keepTypes))
|
||||
return false;
|
||||
|
||||
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
|
||||
|
|
|
|||
|
|
@ -1226,9 +1226,9 @@ IonCacheIRCompiler::emitCallStringSplitResult()
|
|||
static bool
|
||||
GroupHasPropertyTypes(ObjectGroup* group, jsid* id, Value* v)
|
||||
{
|
||||
if (group->unknownProperties())
|
||||
if (group->unknownPropertiesDontCheckGeneration())
|
||||
return true;
|
||||
HeapTypeSet* propTypes = group->maybeGetProperty(*id);
|
||||
HeapTypeSet* propTypes = group->maybeGetPropertyDontCheckGeneration(*id);
|
||||
if (!propTypes)
|
||||
return true;
|
||||
if (!propTypes->nonConstantProperty())
|
||||
|
|
|
|||
|
|
@ -544,7 +544,8 @@ CreateThis(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHa
|
|||
RootedFunction fun(cx, &callee->as<JSFunction>());
|
||||
if (fun->isInterpreted() && fun->isConstructor()) {
|
||||
JSScript* script = JSFunction::getOrCreateScript(cx, fun);
|
||||
if (!script || !script->ensureHasTypes(cx))
|
||||
AutoKeepTypeScripts keepTypes(cx);
|
||||
if (!script || !script->ensureHasTypes(cx, keepTypes))
|
||||
return false;
|
||||
if (fun->isBoundFunction() || script->isDerivedClassConstructor()) {
|
||||
rval.set(MagicValue(JS_UNINITIALIZED_LEXICAL));
|
||||
|
|
|
|||
|
|
@ -863,7 +863,7 @@ template <class Iter>
|
|||
static void
|
||||
TraceOneDataRelocation(JSTracer* trc, Iter* iter)
|
||||
{
|
||||
Instruction* ins = iter->cur();
|
||||
Iter iterCopy(*iter);
|
||||
Register dest;
|
||||
Assembler::RelocStyle rs;
|
||||
const void* prior = Assembler::GetPtr32Target(iter, &dest, &rs);
|
||||
|
|
@ -874,12 +874,12 @@ TraceOneDataRelocation(JSTracer* trc, Iter* iter)
|
|||
"ion-masm-ptr");
|
||||
|
||||
if (ptr != prior) {
|
||||
MacroAssemblerARM::ma_mov_patch(Imm32(int32_t(ptr)), dest, Assembler::Always, rs, ins);
|
||||
MacroAssemblerARM::ma_mov_patch(Imm32(int32_t(ptr)), dest, Assembler::Always, rs, iterCopy);
|
||||
|
||||
// L_LDR won't cause any instructions to be updated.
|
||||
if (rs != Assembler::L_LDR) {
|
||||
AutoFlushICache::flush(uintptr_t(ins), 4);
|
||||
AutoFlushICache::flush(uintptr_t(ins->next()), 4);
|
||||
AutoFlushICache::flush(uintptr_t(iter->cur()), 4);
|
||||
AutoFlushICache::flush(uintptr_t(iter->next()), 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -899,7 +899,7 @@ TraceDataRelocations(JSTracer* trc, ARMBuffer* buffer, CompactBufferReader& read
|
|||
{
|
||||
while (reader.more()) {
|
||||
BufferOffset offset(reader.readUnsigned());
|
||||
ARMBuffer::AssemblerBufferInstIterator iter(offset, buffer);
|
||||
BufferInstructionIterator iter(offset, buffer);
|
||||
TraceOneDataRelocation(trc, &iter);
|
||||
}
|
||||
}
|
||||
|
|
@ -3161,14 +3161,15 @@ Assembler::PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newVal
|
|||
PatchedImmPtr expectedValue)
|
||||
{
|
||||
Instruction* ptr = reinterpret_cast<Instruction*>(label.raw());
|
||||
InstructionIterator iter(ptr);
|
||||
Register dest;
|
||||
Assembler::RelocStyle rs;
|
||||
|
||||
InstructionIterator iter(ptr);
|
||||
DebugOnly<const uint32_t*> val = GetPtr32Target(&iter, &dest, &rs);
|
||||
MOZ_ASSERT(uint32_t((const uint32_t*)val) == uint32_t(expectedValue.value));
|
||||
|
||||
MacroAssembler::ma_mov_patch(Imm32(int32_t(newValue.value)), dest, Always, rs, ptr);
|
||||
iter = InstructionIterator(ptr);
|
||||
MacroAssembler::ma_mov_patch(Imm32(int32_t(newValue.value)), dest, Always, rs, iter);
|
||||
|
||||
// L_LDR won't cause any instructions to be updated.
|
||||
if (rs != L_LDR) {
|
||||
|
|
@ -3221,6 +3222,20 @@ InstIsGuard(Instruction* inst, const PoolHeader** ph)
|
|||
return *ph != nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
InstIsGuard(BufferInstructionIterator& iter, const PoolHeader** ph)
|
||||
{
|
||||
Instruction* inst = iter.cur();
|
||||
Assembler::Condition c = inst->extractCond();
|
||||
if (c != Assembler::Always)
|
||||
return false;
|
||||
if (!(inst->is<InstBXReg>() || inst->is<InstBImm>()))
|
||||
return false;
|
||||
// See if the next instruction is a pool header.
|
||||
*ph = iter.peek()->as<const PoolHeader>();
|
||||
return *ph != nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
InstIsBNop(Instruction* inst)
|
||||
{
|
||||
|
|
@ -3266,6 +3281,28 @@ Instruction::skipPool()
|
|||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
BufferInstructionIterator::skipPool()
|
||||
{
|
||||
// If this is a guard, and the next instruction is a header, always work
|
||||
// around the pool. If it isn't a guard, then start looking ahead.
|
||||
|
||||
const PoolHeader* ph;
|
||||
if (InstIsGuard(*this, &ph)) {
|
||||
// Don't skip a natural guard.
|
||||
if (ph->isNatural())
|
||||
return;
|
||||
advance(sizeof(Instruction) * (1 + ph->size()));
|
||||
skipPool();
|
||||
return;
|
||||
}
|
||||
|
||||
if (InstIsBNop(cur())) {
|
||||
next();
|
||||
skipPool();
|
||||
}
|
||||
}
|
||||
|
||||
// Cases to be handled:
|
||||
// 1) no pools or branches in sight => return this+1
|
||||
// 2) branch to next instruction => return this+2, because a nop needed to be inserted into the stream.
|
||||
|
|
@ -3409,13 +3446,6 @@ Assembler::BailoutTableStart(uint8_t* code)
|
|||
return (uint8_t*) inst;
|
||||
}
|
||||
|
||||
InstructionIterator::InstructionIterator(Instruction* i_)
|
||||
: i(i_)
|
||||
{
|
||||
// Work around pools with an artificial pool guard and around nop-fill.
|
||||
i = i->skipPool();
|
||||
}
|
||||
|
||||
uint32_t Assembler::NopFill = 0;
|
||||
|
||||
uint32_t
|
||||
|
|
|
|||
|
|
@ -2246,20 +2246,35 @@ class InstMOV : public InstALU
|
|||
class InstructionIterator
|
||||
{
|
||||
private:
|
||||
Instruction* i;
|
||||
Instruction* inst_;
|
||||
|
||||
public:
|
||||
explicit InstructionIterator(Instruction* i_);
|
||||
explicit InstructionIterator(Instruction* inst) : inst_(inst) {
|
||||
skipPool();
|
||||
}
|
||||
void skipPool() {
|
||||
inst_ = inst_->skipPool();
|
||||
}
|
||||
|
||||
Instruction* next() {
|
||||
i = i->next();
|
||||
inst_ = inst_->next();
|
||||
return cur();
|
||||
}
|
||||
Instruction* cur() const {
|
||||
return i;
|
||||
return inst_;
|
||||
}
|
||||
};
|
||||
|
||||
class BufferInstructionIterator : public ARMBuffer::AssemblerBufferInstIterator
|
||||
{
|
||||
public:
|
||||
BufferInstructionIterator(BufferOffset bo, ARMBuffer* buffer)
|
||||
: ARMBuffer::AssemblerBufferInstIterator(bo, buffer)
|
||||
{}
|
||||
void skipPool();
|
||||
};
|
||||
|
||||
|
||||
static const uint32_t NumIntArgRegs = 4;
|
||||
|
||||
// There are 16 *float* registers available for arguments
|
||||
|
|
|
|||
|
|
@ -308,6 +308,25 @@ MacroAssembler::add64(Imm64 imm, Register64 dest)
|
|||
ma_adc(imm.hi(), dest.high, scratch, LeaveCC);
|
||||
}
|
||||
|
||||
CodeOffset
|
||||
MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
|
||||
{
|
||||
ScratchRegisterScope scratch(*this);
|
||||
CodeOffset offs = CodeOffset(currentOffset());
|
||||
ma_movPatchable(Imm32(0), scratch, Always);
|
||||
ma_add(src, scratch, dest);
|
||||
return offs;
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
|
||||
{
|
||||
ScratchRegisterScope scratch(*this);
|
||||
BufferInstructionIterator iter(BufferOffset(offset.offset()), &m_buffer);
|
||||
iter.maybeSkipAutomaticInstructions();
|
||||
ma_mov_patch(imm, scratch, Always, HasMOVWT() ? L_MOVWT : L_LDR, iter);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -345,35 +345,36 @@ MacroAssemblerARM::ma_movPatchable(ImmPtr imm, Register dest, Assembler::Conditi
|
|||
ma_movPatchable(Imm32(int32_t(imm.value)), dest, c);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
MacroAssemblerARM::ma_mov_patch(Imm32 imm_, Register dest, Assembler::Condition c,
|
||||
RelocStyle rs, Instruction* i)
|
||||
/* static */
|
||||
template<class Iter>
|
||||
void
|
||||
MacroAssemblerARM::ma_mov_patch(Imm32 imm32, Register dest, Assembler::Condition c,
|
||||
RelocStyle rs, Iter iter)
|
||||
{
|
||||
MOZ_ASSERT(i);
|
||||
int32_t imm = imm_.value;
|
||||
MOZ_ASSERT(iter.cur());
|
||||
|
||||
// Make sure the current instruction is not an artificial guard inserted
|
||||
// by the assembler buffer.
|
||||
i = i->skipPool();
|
||||
iter.skipPool();
|
||||
|
||||
int32_t imm = imm32.value;
|
||||
|
||||
switch(rs) {
|
||||
case L_MOVWT:
|
||||
Assembler::as_movw_patch(dest, Imm16(imm & 0xffff), c, i);
|
||||
i = i->next();
|
||||
Assembler::as_movt_patch(dest, Imm16(imm >> 16 & 0xffff), c, i);
|
||||
Assembler::as_movw_patch(dest, Imm16(imm & 0xffff), c, iter.cur());
|
||||
Assembler::as_movt_patch(dest, Imm16(imm >> 16 & 0xffff), c, iter.next());
|
||||
break;
|
||||
case L_LDR:
|
||||
Assembler::WritePoolEntry(i, c, imm);
|
||||
Assembler::WritePoolEntry(iter.cur(), c, imm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
MacroAssemblerARM::ma_mov_patch(ImmPtr imm, Register dest, Assembler::Condition c,
|
||||
RelocStyle rs, Instruction* i)
|
||||
{
|
||||
ma_mov_patch(Imm32(int32_t(imm.value)), dest, c, rs, i);
|
||||
}
|
||||
template void
|
||||
MacroAssemblerARM::ma_mov_patch(Imm32 imm32, Register dest, Assembler::Condition c,
|
||||
RelocStyle rs, InstructionIterator iter);
|
||||
template void
|
||||
MacroAssemblerARM::ma_mov_patch(Imm32 imm32, Register dest, Assembler::Condition c,
|
||||
RelocStyle rs, BufferInstructionIterator iter);
|
||||
|
||||
void
|
||||
MacroAssemblerARM::ma_mov(Register src, Register dest, SBit s, Assembler::Condition c)
|
||||
|
|
|
|||
|
|
@ -124,10 +124,10 @@ class MacroAssemblerARM : public Assembler
|
|||
void ma_movPatchable(Imm32 imm, Register dest, Assembler::Condition c);
|
||||
void ma_movPatchable(ImmPtr imm, Register dest, Assembler::Condition c);
|
||||
|
||||
// To be used with Iter := InstructionIterator or BufferInstructionIterator.
|
||||
template<class Iter>
|
||||
static void ma_mov_patch(Imm32 imm, Register dest, Assembler::Condition c,
|
||||
RelocStyle rs, Instruction* i);
|
||||
static void ma_mov_patch(ImmPtr imm, Register dest, Assembler::Condition c,
|
||||
RelocStyle rs, Instruction* i);
|
||||
RelocStyle rs, Iter iter);
|
||||
|
||||
// ALU based ops
|
||||
// mov
|
||||
|
|
|
|||
|
|
@ -141,7 +141,6 @@ class AssemblerBuffer
|
|||
{
|
||||
protected:
|
||||
typedef BufferSlice<SliceSize> Slice;
|
||||
typedef AssemblerBuffer<SliceSize, Inst> AssemblerBuffer_;
|
||||
|
||||
// Doubly-linked list of BufferSlices, with the most recent in tail position.
|
||||
Slice* head;
|
||||
|
|
@ -388,24 +387,32 @@ class AssemblerBuffer
|
|||
return BufferOffset(bufferSize);
|
||||
}
|
||||
|
||||
typedef AssemblerBuffer<SliceSize, Inst> ThisClass;
|
||||
|
||||
class AssemblerBufferInstIterator
|
||||
{
|
||||
BufferOffset bo;
|
||||
AssemblerBuffer_* m_buffer;
|
||||
BufferOffset bo_;
|
||||
ThisClass* buffer_;
|
||||
|
||||
public:
|
||||
explicit AssemblerBufferInstIterator(BufferOffset off, AssemblerBuffer_* buffer)
|
||||
: bo(off), m_buffer(buffer)
|
||||
explicit AssemblerBufferInstIterator(BufferOffset bo, ThisClass* buffer)
|
||||
: bo_(bo), buffer_(buffer)
|
||||
{ }
|
||||
|
||||
void advance(int offset) {
|
||||
bo_ = BufferOffset(bo_.getOffset() + offset);
|
||||
}
|
||||
|
||||
Inst* next() {
|
||||
Inst* i = m_buffer->getInst(bo);
|
||||
bo = BufferOffset(bo.getOffset() + i->size());
|
||||
advance(cur()->size());
|
||||
return cur();
|
||||
}
|
||||
|
||||
Inst* cur() {
|
||||
return m_buffer->getInst(bo);
|
||||
Inst* peek() {
|
||||
return buffer_->getInst(BufferOffset(bo_.getOffset() + cur()->size()));
|
||||
}
|
||||
Inst* cur() const {
|
||||
return buffer_->getInst(bo_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1689,7 +1689,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
bool isTopLevel() { return code() && !functionNonDelazifying(); }
|
||||
|
||||
/* Ensure the script has a TypeScript. */
|
||||
inline bool ensureHasTypes(JSContext* cx);
|
||||
inline bool ensureHasTypes(JSContext* cx, js::AutoKeepTypeScripts&);
|
||||
|
||||
inline js::TypeScript* types();
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "jsscriptinlines.h"
|
||||
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/TypeInference-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
|
@ -1466,7 +1467,8 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler
|
|||
CallObject& callobj = env->as<CallObject>();
|
||||
RootedFunction fun(cx, &callobj.callee());
|
||||
RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
|
||||
if (!script->ensureHasTypes(cx) || !script->ensureHasAnalyzedArgsUsage(cx))
|
||||
AutoKeepTypeScripts keepTypes(cx);
|
||||
if (!script->ensureHasTypes(cx, keepTypes) || !script->ensureHasAnalyzedArgsUsage(cx))
|
||||
return false;
|
||||
|
||||
BindingIter bi(script);
|
||||
|
|
|
|||
|
|
@ -383,7 +383,8 @@ class ObjectGroup : public gc::TenuredCell
|
|||
inline HeapTypeSet* getProperty(ExclusiveContext* cx, JSObject* obj, jsid id);
|
||||
|
||||
/* Get a property only if it already exists. */
|
||||
inline HeapTypeSet* maybeGetProperty(jsid id);
|
||||
MOZ_ALWAYS_INLINE HeapTypeSet* maybeGetProperty(jsid id);
|
||||
MOZ_ALWAYS_INLINE HeapTypeSet* maybeGetPropertyDontCheckGeneration(jsid id);
|
||||
|
||||
/*
|
||||
* Iterate through the group's properties. getPropertyCount overapproximates
|
||||
|
|
@ -461,6 +462,7 @@ class ObjectGroup : public gc::TenuredCell
|
|||
}
|
||||
|
||||
inline uint32_t basePropertyCount();
|
||||
inline uint32_t basePropertyCountDontCheckGeneration();
|
||||
|
||||
private:
|
||||
inline void setBasePropertyCount(uint32_t count);
|
||||
|
|
|
|||
|
|
@ -367,10 +367,10 @@ TypeMonitorCall(JSContext* cx, const js::CallArgs& args, bool constructing)
|
|||
inline bool
|
||||
TrackPropertyTypes(ExclusiveContext* cx, JSObject* obj, jsid id)
|
||||
{
|
||||
if (obj->hasLazyGroup() || obj->group()->unknownProperties())
|
||||
if (obj->hasLazyGroup() || obj->group()->unknownPropertiesDontCheckGeneration())
|
||||
return false;
|
||||
|
||||
if (obj->isSingleton() && !obj->group()->maybeGetProperty(id))
|
||||
if (obj->isSingleton() && !obj->group()->maybeGetPropertyDontCheckGeneration(id))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -405,7 +405,15 @@ PropertyHasBeenMarkedNonConstant(JSObject* obj, jsid id)
|
|||
inline bool
|
||||
HasTypePropertyId(JSObject* obj, jsid id, TypeSet::Type type)
|
||||
{
|
||||
if (obj->hasLazyGroup())
|
||||
MOZ_ASSERT(id == IdToTypeId(id));
|
||||
MOZ_ASSERT(TrackPropertyTypes(obj, id));
|
||||
|
||||
if (HeapTypeSet* types = obj->group()->maybeGetPropertyDontCheckGeneration(id)) {
|
||||
if (!types->hasType(type))
|
||||
return false;
|
||||
// Non-constant properties are only relevant for singleton objects.
|
||||
if (obj->isSingleton() && !types->nonConstantProperty())
|
||||
return false;
|
||||
return true;
|
||||
|
||||
if (obj->group()->unknownProperties())
|
||||
|
|
@ -657,6 +665,21 @@ TypeScript::SetArgument(JSContext* cx, JSScript* script, unsigned arg, const js:
|
|||
SetArgument(cx, script, arg, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
inline
|
||||
AutoKeepTypeScripts::AutoKeepTypeScripts(JSContext* cx)
|
||||
: zone_(cx->zone()->types),
|
||||
prev_(zone_.keepTypeScripts)
|
||||
{
|
||||
zone_.keepTypeScripts = true;
|
||||
}
|
||||
|
||||
inline
|
||||
AutoKeepTypeScripts::~AutoKeepTypeScripts()
|
||||
{
|
||||
MOZ_ASSERT(zone_.keepTypeScripts);
|
||||
zone_.keepTypeScripts = prev_;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeHashSet
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1024,10 +1047,18 @@ TypeSet::getObjectClass(unsigned i) const
|
|||
// ObjectGroup
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline uint32_t
|
||||
ObjectGroup::basePropertyCountDontCheckGeneration()
|
||||
{
|
||||
uint32_t flags = flagsDontCheckGeneration();
|
||||
return (flags & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT;
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
ObjectGroup::basePropertyCount()
|
||||
{
|
||||
return (flags() & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT;
|
||||
maybeSweep(nullptr);
|
||||
return basePropertyCountDontCheckGeneration();
|
||||
}
|
||||
|
||||
inline void
|
||||
|
|
@ -1083,18 +1114,25 @@ ObjectGroup::getProperty(ExclusiveContext* cx, JSObject* obj, jsid id)
|
|||
}
|
||||
|
||||
inline HeapTypeSet*
|
||||
ObjectGroup::maybeGetProperty(jsid id)
|
||||
ObjectGroup::maybeGetPropertyDontCheckGeneration(jsid id)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
MOZ_ASSERT(!unknownPropertiesDontCheckGeneration());
|
||||
|
||||
Property* prop = TypeHashSet::Lookup<jsid, Property, Property>
|
||||
(propertySet, basePropertyCount(), id);
|
||||
(propertySet, basePropertyCountDontCheckGeneration(), id);
|
||||
|
||||
return prop ? &prop->types : nullptr;
|
||||
}
|
||||
|
||||
inline HeapTypeSet*
|
||||
ObjectGroup::maybeGetProperty(jsid id)
|
||||
{
|
||||
maybeSweep(nullptr);
|
||||
return maybeGetPropertyDontCheckGeneration(id);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
ObjectGroup::getPropertyCount()
|
||||
{
|
||||
|
|
@ -1125,7 +1163,7 @@ JSScript::types()
|
|||
}
|
||||
|
||||
inline bool
|
||||
JSScript::ensureHasTypes(JSContext* cx)
|
||||
JSScript::ensureHasTypes(JSContext* cx, js::AutoKeepTypeScripts&)
|
||||
{
|
||||
return types() || makeTypes(cx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4436,6 +4436,7 @@ JSScript::maybeSweepTypes(AutoClearTypeInferenceStateOnOOM* oom)
|
|||
// only do this if nothing has been compiled for the script, which will be
|
||||
// the case unless the script has been compiled since we started sweeping.
|
||||
if (types.sweepReleaseTypes &&
|
||||
!types.keepTypeScripts &&
|
||||
!hasBaselineScript() &&
|
||||
!hasIonScript())
|
||||
{
|
||||
|
|
@ -4492,20 +4493,24 @@ Zone::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
|||
|
||||
TypeZone::TypeZone(Zone* zone)
|
||||
: zone_(zone),
|
||||
typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
generation(0),
|
||||
compilerOutputs(nullptr),
|
||||
sweepTypeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
sweepCompilerOutputs(nullptr),
|
||||
sweepReleaseTypes(false),
|
||||
activeAnalysis(nullptr)
|
||||
typeLifoAlloc(zone->group(), (size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
generation(zone->group(), 0),
|
||||
compilerOutputs(zone->group(), nullptr),
|
||||
sweepTypeLifoAlloc(zone->group(), (size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
sweepCompilerOutputs(zone->group(), nullptr),
|
||||
sweepReleaseTypes(zone->group(), false),
|
||||
sweepingTypes(zone->group(), false),
|
||||
keepTypeScripts(zone->group(), false),
|
||||
activeAnalysis(zone->group(), nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
TypeZone::~TypeZone()
|
||||
{
|
||||
js_delete(compilerOutputs);
|
||||
js_delete(sweepCompilerOutputs);
|
||||
js_delete(compilerOutputs.ref());
|
||||
js_delete(sweepCompilerOutputs.ref());
|
||||
MOZ_RELEASE_ASSERT(!sweepingTypes);
|
||||
MOZ_ASSERT(!keepTypeScripts);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1255,6 +1255,19 @@ class TypeScript
|
|||
#endif
|
||||
};
|
||||
|
||||
// Ensures no TypeScripts are purged in the current zone.
|
||||
class MOZ_RAII AutoKeepTypeScripts
|
||||
{
|
||||
TypeZone& zone_;
|
||||
bool prev_;
|
||||
|
||||
AutoKeepTypeScripts(const AutoKeepTypeScripts&) = delete;
|
||||
void operator=(const AutoKeepTypeScripts&) = delete;
|
||||
|
||||
public:
|
||||
explicit inline AutoKeepTypeScripts(JSContext* cx);
|
||||
inline ~AutoKeepTypeScripts();
|
||||
};
|
||||
void
|
||||
FillBytecodeTypeMap(JSScript* script, uint32_t* bytecodeMap);
|
||||
|
||||
|
|
@ -1325,6 +1338,9 @@ struct TypeZone
|
|||
static const size_t TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 8 * 1024;
|
||||
LifoAlloc typeLifoAlloc;
|
||||
|
||||
TypeZone(const TypeZone&) = delete;
|
||||
void operator=(const TypeZone&) = delete;
|
||||
|
||||
// Current generation for sweeping.
|
||||
uint32_t generation : 1;
|
||||
|
||||
|
|
@ -1348,6 +1364,7 @@ struct TypeZone
|
|||
// information attached to scripts.
|
||||
bool sweepReleaseTypes;
|
||||
|
||||
ZoneGroupData<bool> keepTypeScripts;
|
||||
// The topmost AutoEnterAnalysis on the stack, if there is one.
|
||||
AutoEnterAnalysis* activeAnalysis;
|
||||
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ UnboxedPlainObject::ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj
|
|||
bool
|
||||
UnboxedPlainObject::containsUnboxedOrExpandoProperty(ExclusiveContext* cx, jsid id) const
|
||||
{
|
||||
if (layout().lookup(id))
|
||||
if (layoutDontCheckGeneration().lookup(id))
|
||||
return true;
|
||||
|
||||
if (maybeExpando() && maybeExpando()->containsShapeOrElement(cx, id))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue