зеркало из https://github.com/mozilla/gecko-dev.git
Bug 864468: IonMonkey: Skip argument type checks when type is known to match, r=jandem
This commit is contained in:
Родитель
3e22fefe23
Коммит
3fca9cbc83
|
@ -1568,7 +1568,10 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
|
||||||
masm.loadPtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
|
masm.loadPtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
|
||||||
|
|
||||||
// Load script jitcode.
|
// Load script jitcode.
|
||||||
masm.loadBaselineOrIonRaw(objreg, objreg, executionMode, &uncompiled);
|
if (call->mir()->needsArgCheck())
|
||||||
|
masm.loadBaselineOrIonRaw(objreg, objreg, executionMode, &uncompiled);
|
||||||
|
else
|
||||||
|
masm.loadBaselineOrIonNoArgCheck(objreg, objreg, executionMode, &uncompiled);
|
||||||
|
|
||||||
// Nestle the StackPointer up to the argument vector.
|
// Nestle the StackPointer up to the argument vector.
|
||||||
masm.freeStack(unusedStack);
|
masm.freeStack(unusedStack);
|
||||||
|
@ -2252,7 +2255,7 @@ CodeGenerator::maybeCreateScriptCounts()
|
||||||
MResumePoint *resume = block->entryResumePoint();
|
MResumePoint *resume = block->entryResumePoint();
|
||||||
while (resume->caller())
|
while (resume->caller())
|
||||||
resume = resume->caller();
|
resume = resume->caller();
|
||||||
uint32_t offset = resume->pc() - script->code;
|
DebugOnly<uint32_t> offset = resume->pc() - script->code;
|
||||||
JS_ASSERT(offset < script->length);
|
JS_ASSERT(offset < script->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4902,6 +4905,10 @@ CodeGenerator::generate()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remember the entry offset to skip the argument check.
|
||||||
|
masm.flushBuffer();
|
||||||
|
setSkipArgCheckEntryOffset(masm.size());
|
||||||
|
|
||||||
if (!generatePrologue())
|
if (!generatePrologue())
|
||||||
return false;
|
return false;
|
||||||
if (!generateBody())
|
if (!generateBody())
|
||||||
|
@ -4951,6 +4958,7 @@ CodeGenerator::link()
|
||||||
graph.mir().numCallTargets());
|
graph.mir().numCallTargets());
|
||||||
|
|
||||||
ionScript->setMethod(code);
|
ionScript->setMethod(code);
|
||||||
|
ionScript->setSkipArgCheckEntryOffset(getSkipArgCheckEntryOffset());
|
||||||
|
|
||||||
SetIonScript(script, executionMode, ionScript);
|
SetIonScript(script, executionMode, ionScript);
|
||||||
|
|
||||||
|
|
|
@ -556,6 +556,7 @@ IonScript::IonScript()
|
||||||
deoptTable_(NULL),
|
deoptTable_(NULL),
|
||||||
osrPc_(NULL),
|
osrPc_(NULL),
|
||||||
osrEntryOffset_(0),
|
osrEntryOffset_(0),
|
||||||
|
skipArgCheckEntryOffset_(0),
|
||||||
invalidateEpilogueOffset_(0),
|
invalidateEpilogueOffset_(0),
|
||||||
invalidateEpilogueDataOffset_(0),
|
invalidateEpilogueDataOffset_(0),
|
||||||
numBailouts_(0),
|
numBailouts_(0),
|
||||||
|
|
|
@ -434,9 +434,8 @@ IonBuilder::build()
|
||||||
if (!current)
|
if (!current)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IonSpew(IonSpew_Scripts, "Analyzing script %s:%d (%p) (usecount=%d) (maxloopcount=%d)",
|
IonSpew(IonSpew_Scripts, "Analyzing script %s:%d (%p) (usecount=%d)",
|
||||||
script()->filename(), script()->lineno, (void *)script(), (int)script()->getUseCount(),
|
script()->filename(), script()->lineno, (void *)script(), (int)script()->getUseCount());
|
||||||
(int)script()->getMaxLoopCount());
|
|
||||||
|
|
||||||
if (!graph().addScript(script()))
|
if (!graph().addScript(script()))
|
||||||
return false;
|
return false;
|
||||||
|
@ -4750,6 +4749,49 @@ TestAreKnownDOMTypes(JSContext *cx, types::TypeSet *inTypes)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ArgumentTypesMatch(MDefinition *def, types::StackTypeSet *calleeTypes)
|
||||||
|
{
|
||||||
|
if (def->resultTypeSet()) {
|
||||||
|
JS_ASSERT(def->type() == MIRType_Value || def->mightBeType(def->type()));
|
||||||
|
return def->resultTypeSet()->isSubset(calleeTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def->type() == MIRType_Value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return calleeTypes->mightBeType(ValueTypeFromMIRType(def->type()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
TestNeedsArgumentCheck(JSContext *cx, HandleFunction target, CallInfo &callInfo)
|
||||||
|
{
|
||||||
|
// If we have a known target, check if the caller arg types are a subset of callee.
|
||||||
|
// Since typeset accumulates and can't decrease that means we don't need to check
|
||||||
|
// the arguments anymore.
|
||||||
|
if (!target->isInterpreted())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
RootedScript targetScript(cx, target->nonLazyScript());
|
||||||
|
if (!targetScript->hasAnalysis())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!ArgumentTypesMatch(callInfo.thisArg(), types::TypeScript::ThisTypes(targetScript)))
|
||||||
|
return true;
|
||||||
|
uint32_t expected_args = Min<uint32_t>(callInfo.argc(), target->nargs);
|
||||||
|
for (size_t i = 0; i < expected_args; i++) {
|
||||||
|
if (!ArgumentTypesMatch(callInfo.getArg(i), types::TypeScript::ArgTypes(targetScript, i)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (size_t i = callInfo.argc(); i < target->nargs; i++) {
|
||||||
|
if (!types::TypeScript::ArgTypes(targetScript, i)->mightBeType(JSVAL_TYPE_UNDEFINED))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MCall *
|
MCall *
|
||||||
IonBuilder::makeCallHelper(HandleFunction target, CallInfo &callInfo, bool cloneAtCallsite)
|
IonBuilder::makeCallHelper(HandleFunction target, CallInfo &callInfo, bool cloneAtCallsite)
|
||||||
{
|
{
|
||||||
|
@ -4819,6 +4861,7 @@ IonBuilder::makeCallHelper(HandleFunction target, CallInfo &callInfo, bool clone
|
||||||
current->add(newThis);
|
current->add(newThis);
|
||||||
|
|
||||||
thisArg = newThis;
|
thisArg = newThis;
|
||||||
|
callInfo.setThis(newThis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass |this| and function.
|
// Pass |this| and function.
|
||||||
|
@ -4844,6 +4887,9 @@ IonBuilder::makeCallHelper(HandleFunction target, CallInfo &callInfo, bool clone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target && !TestNeedsArgumentCheck(cx, target, callInfo))
|
||||||
|
call->disableArgCheck();
|
||||||
|
|
||||||
call->initFunction(callInfo.fun());
|
call->initFunction(callInfo.fun());
|
||||||
|
|
||||||
current->add(call);
|
current->add(call);
|
||||||
|
|
|
@ -46,8 +46,8 @@ class IonCode : public gc::Cell
|
||||||
uint32_t jumpRelocTableBytes_; // Size of the jump relocation table.
|
uint32_t jumpRelocTableBytes_; // Size of the jump relocation table.
|
||||||
uint32_t dataRelocTableBytes_; // Size of the data relocation table.
|
uint32_t dataRelocTableBytes_; // Size of the data relocation table.
|
||||||
uint32_t preBarrierTableBytes_; // Size of the prebarrier table.
|
uint32_t preBarrierTableBytes_; // Size of the prebarrier table.
|
||||||
JSBool invalidated_; // Whether the code object has been invalidated.
|
JSBool invalidated_; // Whether the code object has been invalidated.
|
||||||
// This is necessary to prevent GC tracing.
|
// This is necessary to prevent GC tracing.
|
||||||
|
|
||||||
#if JS_BITS_PER_WORD == 32
|
#if JS_BITS_PER_WORD == 32
|
||||||
// Ensure IonCode is gc::Cell aligned.
|
// Ensure IonCode is gc::Cell aligned.
|
||||||
|
@ -160,6 +160,9 @@ struct IonScript
|
||||||
// Offset to OSR entrypoint from method_->raw(), or 0.
|
// Offset to OSR entrypoint from method_->raw(), or 0.
|
||||||
uint32_t osrEntryOffset_;
|
uint32_t osrEntryOffset_;
|
||||||
|
|
||||||
|
// Offset to entrypoint skipping type arg check from method_->raw().
|
||||||
|
uint32_t skipArgCheckEntryOffset_;
|
||||||
|
|
||||||
// Offset of the invalidation epilogue (which pushes this IonScript
|
// Offset of the invalidation epilogue (which pushes this IonScript
|
||||||
// and calls the invalidation thunk).
|
// and calls the invalidation thunk).
|
||||||
uint32_t invalidateEpilogueOffset_;
|
uint32_t invalidateEpilogueOffset_;
|
||||||
|
@ -302,6 +305,9 @@ struct IonScript
|
||||||
static inline size_t offsetOfOsrEntryOffset() {
|
static inline size_t offsetOfOsrEntryOffset() {
|
||||||
return offsetof(IonScript, osrEntryOffset_);
|
return offsetof(IonScript, osrEntryOffset_);
|
||||||
}
|
}
|
||||||
|
static inline size_t offsetOfSkipArgCheckEntryOffset() {
|
||||||
|
return offsetof(IonScript, skipArgCheckEntryOffset_);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IonCode *method() const {
|
IonCode *method() const {
|
||||||
|
@ -327,6 +333,13 @@ struct IonScript
|
||||||
uint32_t osrEntryOffset() const {
|
uint32_t osrEntryOffset() const {
|
||||||
return osrEntryOffset_;
|
return osrEntryOffset_;
|
||||||
}
|
}
|
||||||
|
void setSkipArgCheckEntryOffset(uint32_t offset) {
|
||||||
|
JS_ASSERT(!skipArgCheckEntryOffset_);
|
||||||
|
skipArgCheckEntryOffset_ = offset;
|
||||||
|
}
|
||||||
|
uint32_t getSkipArgCheckEntryOffset() const {
|
||||||
|
return skipArgCheckEntryOffset_;
|
||||||
|
}
|
||||||
bool containsCodeAddress(uint8_t *addr) const {
|
bool containsCodeAddress(uint8_t *addr) const {
|
||||||
return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
|
return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -963,6 +963,38 @@ MacroAssembler::loadBaselineOrIonRaw(Register script, Register dest, ExecutionMo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MacroAssembler::loadBaselineOrIonNoArgCheck(Register script, Register dest, ExecutionMode mode,
|
||||||
|
Label *failure)
|
||||||
|
{
|
||||||
|
if (mode == SequentialExecution) {
|
||||||
|
loadPtr(Address(script, JSScript::offsetOfBaselineOrIonSkipArgCheck()), dest);
|
||||||
|
if (failure)
|
||||||
|
branchTestPtr(Assembler::Zero, dest, dest, failure);
|
||||||
|
} else {
|
||||||
|
// Find second register to get the offset to skip argument check
|
||||||
|
Register offset = script;
|
||||||
|
if (script == dest) {
|
||||||
|
GeneralRegisterSet regs(GeneralRegisterSet::All());
|
||||||
|
regs.take(dest);
|
||||||
|
offset = regs.takeAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPtr(Address(script, JSScript::offsetOfParallelIonScript()), dest);
|
||||||
|
if (failure)
|
||||||
|
branchPtr(Assembler::BelowOrEqual, dest, ImmWord(ION_COMPILING_SCRIPT), failure);
|
||||||
|
|
||||||
|
Push(offset);
|
||||||
|
load32(Address(script, IonScript::offsetOfSkipArgCheckEntryOffset()), offset);
|
||||||
|
|
||||||
|
loadPtr(Address(dest, IonScript::offsetOfMethod()), dest);
|
||||||
|
loadPtr(Address(dest, IonCode::offsetOfCode()), dest);
|
||||||
|
addPtr(offset, dest);
|
||||||
|
|
||||||
|
Pop(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MacroAssembler::loadBaselineFramePtr(Register framePtr, Register dest)
|
MacroAssembler::loadBaselineFramePtr(Register framePtr, Register dest)
|
||||||
{
|
{
|
||||||
|
|
|
@ -874,6 +874,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadBaselineOrIonRaw(Register script, Register dest, ExecutionMode mode, Label *failure);
|
void loadBaselineOrIonRaw(Register script, Register dest, ExecutionMode mode, Label *failure);
|
||||||
|
void loadBaselineOrIonNoArgCheck(Register callee, Register dest, ExecutionMode mode, Label *failure);
|
||||||
|
|
||||||
void loadBaselineFramePtr(Register framePtr, Register dest);
|
void loadBaselineFramePtr(Register framePtr, Register dest);
|
||||||
|
|
||||||
|
|
|
@ -1365,11 +1365,14 @@ class MCall
|
||||||
// Original value of argc from the bytecode.
|
// Original value of argc from the bytecode.
|
||||||
uint32_t numActualArgs_;
|
uint32_t numActualArgs_;
|
||||||
|
|
||||||
|
bool needsArgCheck_;
|
||||||
|
|
||||||
MCall(JSFunction *target, uint32_t numActualArgs, bool construct)
|
MCall(JSFunction *target, uint32_t numActualArgs, bool construct)
|
||||||
: construct_(construct),
|
: construct_(construct),
|
||||||
target_(target),
|
target_(target),
|
||||||
targetScript_(NULL),
|
targetScript_(NULL),
|
||||||
numActualArgs_(numActualArgs)
|
numActualArgs_(numActualArgs),
|
||||||
|
needsArgCheck_(true)
|
||||||
{
|
{
|
||||||
setResultType(MIRType_Value);
|
setResultType(MIRType_Value);
|
||||||
}
|
}
|
||||||
|
@ -1387,6 +1390,14 @@ class MCall
|
||||||
return setOperand(FunctionOperandIndex, func);
|
return setOperand(FunctionOperandIndex, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool needsArgCheck() const {
|
||||||
|
return needsArgCheck_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disableArgCheck() {
|
||||||
|
needsArgCheck_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
MPrepareCall *getPrepareCall() {
|
MPrepareCall *getPrepareCall() {
|
||||||
return getOperand(PrepareCallOperandIndex)->toPrepareCall();
|
return getOperand(PrepareCallOperandIndex)->toPrepareCall();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, Mac
|
||||||
lastOsiPointOffset_(0),
|
lastOsiPointOffset_(0),
|
||||||
sps_(&gen->compartment->rt->spsProfiler, &lastPC_),
|
sps_(&gen->compartment->rt->spsProfiler, &lastPC_),
|
||||||
osrEntryOffset_(0),
|
osrEntryOffset_(0),
|
||||||
|
skipArgCheckEntryOffset_(0),
|
||||||
frameDepth_(graph->localSlotCount() * sizeof(STACK_SLOT_SIZE) +
|
frameDepth_(graph->localSlotCount() * sizeof(STACK_SLOT_SIZE) +
|
||||||
graph->argumentSlotCount() * sizeof(Value))
|
graph->argumentSlotCount() * sizeof(Value))
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,6 +91,18 @@ class CodeGeneratorShared : public LInstructionVisitor
|
||||||
return osrEntryOffset_;
|
return osrEntryOffset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The offset of the first instruction of the body.
|
||||||
|
// This skips the arguments type checks.
|
||||||
|
size_t skipArgCheckEntryOffset_;
|
||||||
|
|
||||||
|
inline void setSkipArgCheckEntryOffset(size_t offset) {
|
||||||
|
JS_ASSERT(skipArgCheckEntryOffset_ == 0);
|
||||||
|
skipArgCheckEntryOffset_ = offset;
|
||||||
|
}
|
||||||
|
inline size_t getSkipArgCheckEntryOffset() const {
|
||||||
|
return skipArgCheckEntryOffset_;
|
||||||
|
}
|
||||||
|
|
||||||
typedef js::Vector<SafepointIndex, 8, SystemAllocPolicy> SafepointIndices;
|
typedef js::Vector<SafepointIndex, 8, SystemAllocPolicy> SafepointIndices;
|
||||||
|
|
||||||
bool markArgumentSlots(LSafepoint *safepoint);
|
bool markArgumentSlots(LSafepoint *safepoint);
|
||||||
|
|
|
@ -1146,11 +1146,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool
|
||||||
RootedScript script(cx);
|
RootedScript script(cx);
|
||||||
SET_SCRIPT(regs.fp()->script());
|
SET_SCRIPT(regs.fp()->script());
|
||||||
|
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
/* Reset the loop count on the script we're entering. */
|
|
||||||
script->resetLoopCount();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if JS_TRACE_LOGGING
|
#if JS_TRACE_LOGGING
|
||||||
AutoTraceLog logger(TraceLogging::defaultLogger(),
|
AutoTraceLog logger(TraceLogging::defaultLogger(),
|
||||||
TraceLogging::INTERPRETER_START,
|
TraceLogging::INTERPRETER_START,
|
||||||
|
@ -1383,10 +1378,6 @@ ADD_EMPTY_CASE(JSOP_TRY)
|
||||||
END_EMPTY_CASES
|
END_EMPTY_CASES
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_LOOPHEAD)
|
BEGIN_CASE(JSOP_LOOPHEAD)
|
||||||
|
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
script->incrLoopCount();
|
|
||||||
#endif
|
|
||||||
END_CASE(JSOP_LOOPHEAD)
|
END_CASE(JSOP_LOOPHEAD)
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_LABEL)
|
BEGIN_CASE(JSOP_LABEL)
|
||||||
|
@ -2424,9 +2415,6 @@ BEGIN_CASE(JSOP_FUNCALL)
|
||||||
regs.fp()->setUseNewType();
|
regs.fp()->setUseNewType();
|
||||||
|
|
||||||
SET_SCRIPT(regs.fp()->script());
|
SET_SCRIPT(regs.fp()->script());
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
script->resetLoopCount();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
if (!newType && ion::IsEnabled(cx)) {
|
if (!newType && ion::IsEnabled(cx)) {
|
||||||
|
|
|
@ -1916,11 +1916,7 @@ JSScript::isShortRunning()
|
||||||
{
|
{
|
||||||
return length < 100 &&
|
return length < 100 &&
|
||||||
hasAnalysis() &&
|
hasAnalysis() &&
|
||||||
!analysis()->hasFunctionCalls()
|
!analysis()->hasFunctionCalls();
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
&& getMaxLoopCount() < 40
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -2883,11 +2879,15 @@ void
|
||||||
JSScript::updateBaselineOrIonRaw()
|
JSScript::updateBaselineOrIonRaw()
|
||||||
{
|
{
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
if (hasIonScript())
|
if (hasIonScript()) {
|
||||||
baselineOrIonRaw = ion->method()->raw();
|
baselineOrIonRaw = ion->method()->raw();
|
||||||
else if (hasBaselineScript())
|
baselineOrIonSkipArgCheck = ion->method()->raw() + ion->getSkipArgCheckEntryOffset();
|
||||||
|
} else if (hasBaselineScript()) {
|
||||||
baselineOrIonRaw = baseline->method()->raw();
|
baselineOrIonRaw = baseline->method()->raw();
|
||||||
else
|
baselineOrIonSkipArgCheck = baseline->method()->raw();
|
||||||
|
} else {
|
||||||
baselineOrIonRaw = NULL;
|
baselineOrIonRaw = NULL;
|
||||||
|
baselineOrIonSkipArgCheck = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,10 +412,7 @@ class JSScript : public js::gc::Cell
|
||||||
uint32_t useCount; /* Number of times the script has been called
|
uint32_t useCount; /* Number of times the script has been called
|
||||||
* or has had backedges taken. Reset if the
|
* or has had backedges taken. Reset if the
|
||||||
* script's JIT code is forcibly discarded. */
|
* script's JIT code is forcibly discarded. */
|
||||||
|
uint32_t PADDING32;
|
||||||
uint32_t maxLoopCount; /* Maximum loop count that has been encountered. */
|
|
||||||
uint32_t loopCount; /* Number of times a LOOPHEAD has been encountered.
|
|
||||||
after a LOOPENTRY. Modified only by interpreter. */
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Unique identifier within the compartment for this script, used for
|
// Unique identifier within the compartment for this script, used for
|
||||||
|
@ -429,7 +426,6 @@ class JSScript : public js::gc::Cell
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t PADDING16;
|
uint16_t PADDING16;
|
||||||
|
|
||||||
uint16_t version; /* JS version under which script was compiled */
|
uint16_t version; /* JS version under which script was compiled */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -603,6 +599,7 @@ class JSScript : public js::gc::Cell
|
||||||
* if there's no Baseline or Ion script.
|
* if there's no Baseline or Ion script.
|
||||||
*/
|
*/
|
||||||
uint8_t *baselineOrIonRaw;
|
uint8_t *baselineOrIonRaw;
|
||||||
|
uint8_t *baselineOrIonSkipArgCheck;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool hasIonScript() const {
|
bool hasIonScript() const {
|
||||||
|
@ -683,6 +680,9 @@ class JSScript : public js::gc::Cell
|
||||||
static size_t offsetOfBaselineOrIonRaw() {
|
static size_t offsetOfBaselineOrIonRaw() {
|
||||||
return offsetof(JSScript, baselineOrIonRaw);
|
return offsetof(JSScript, baselineOrIonRaw);
|
||||||
}
|
}
|
||||||
|
static size_t offsetOfBaselineOrIonSkipArgCheck() {
|
||||||
|
return offsetof(JSScript, baselineOrIonSkipArgCheck);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Original compiled function for the script, if it has a function.
|
* Original compiled function for the script, if it has a function.
|
||||||
|
@ -809,22 +809,6 @@ class JSScript : public js::gc::Cell
|
||||||
static size_t offsetOfUseCount() { return offsetof(JSScript, useCount); }
|
static size_t offsetOfUseCount() { return offsetof(JSScript, useCount); }
|
||||||
void resetUseCount() { useCount = 0; }
|
void resetUseCount() { useCount = 0; }
|
||||||
|
|
||||||
void resetLoopCount() {
|
|
||||||
if (loopCount > maxLoopCount)
|
|
||||||
maxLoopCount = loopCount;
|
|
||||||
loopCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void incrLoopCount() {
|
|
||||||
++loopCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getMaxLoopCount() {
|
|
||||||
if (loopCount > maxLoopCount)
|
|
||||||
maxLoopCount = loopCount;
|
|
||||||
return maxLoopCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Size of the JITScript and all sections. If |mallocSizeOf| is NULL, the
|
* Size of the JITScript and all sections. If |mallocSizeOf| is NULL, the
|
||||||
* size is computed analytically. (This method is implemented in
|
* size is computed analytically. (This method is implemented in
|
||||||
|
|
Загрузка…
Ссылка в новой задаче