190 lines
7.1 KiB
Diff
190 lines
7.1 KiB
Diff
Copied from: https://hg.mozilla.org/releases/mozilla-esr38/rev/f31d643afd41
|
|
Security advisory: https://www.mozilla.org/en-US/security/advisories/mfsa2016-01/
|
|
Mozilla Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1233925
|
|
|
|
# HG changeset patch
|
|
# User Jan de Mooij <jdemooij@mozilla.com>
|
|
# Date 1452110721 -3600
|
|
# Node ID f31d643afd4159b5422ae5aebcbbea0a088e018e
|
|
# Parent 4444e94a99cb9b00c0351cc8bf5459739cc036a5
|
|
Bug 1233925 - Treat functions with rest more like functions with lazy arguments. r=nbp a=ritu
|
|
|
|
diff --git a/js/src/jit/BacktrackingAllocator.cpp b/js/src/jit/BacktrackingAllocator.cpp
|
|
--- a/js/src/jit/BacktrackingAllocator.cpp
|
|
+++ b/js/src/jit/BacktrackingAllocator.cpp
|
|
@@ -201,20 +201,19 @@ BacktrackingAllocator::tryGroupRegisters
|
|
// constructor calling convention.
|
|
if (IsThisSlotDefinition(reg0->def()) || IsThisSlotDefinition(reg1->def())) {
|
|
if (*reg0->def()->output() != *reg1->def()->output())
|
|
return true;
|
|
}
|
|
|
|
// Registers which might spill to the frame's argument slots can only be
|
|
// grouped with other such registers if the frame might access those
|
|
- // arguments through a lazy arguments object.
|
|
+ // arguments through a lazy arguments object or rest parameter.
|
|
if (IsArgumentSlotDefinition(reg0->def()) || IsArgumentSlotDefinition(reg1->def())) {
|
|
- JSScript* script = graph.mir().entryBlock()->info().script();
|
|
- if (script && script->argumentsAliasesFormals()) {
|
|
+ if (graph.mir().entryBlock()->info().mayReadFrameArgsDirectly()) {
|
|
if (*reg0->def()->output() != *reg1->def()->output())
|
|
return true;
|
|
}
|
|
}
|
|
|
|
VirtualRegisterGroup* group0 = reg0->group(), *group1 = reg1->group();
|
|
|
|
if (!group0 && group1)
|
|
diff --git a/js/src/jit/CompileInfo.h b/js/src/jit/CompileInfo.h
|
|
--- a/js/src/jit/CompileInfo.h
|
|
+++ b/js/src/jit/CompileInfo.h
|
|
@@ -194,16 +194,17 @@ enum AnalysisMode {
|
|
class CompileInfo
|
|
{
|
|
public:
|
|
CompileInfo(JSScript* script, JSFunction* fun, jsbytecode* osrPc, bool constructing,
|
|
AnalysisMode analysisMode, bool scriptNeedsArgsObj,
|
|
InlineScriptTree* inlineScriptTree)
|
|
: script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
|
|
analysisMode_(analysisMode), scriptNeedsArgsObj_(scriptNeedsArgsObj),
|
|
+ mayReadFrameArgsDirectly_(script->mayReadFrameArgsDirectly()),
|
|
inlineScriptTree_(inlineScriptTree)
|
|
{
|
|
MOZ_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
|
|
|
|
// The function here can flow in from anywhere so look up the canonical
|
|
// function to ensure that we do not try to embed a nursery pointer in
|
|
// jit-code. Precisely because it can flow in from anywhere, it's not
|
|
// guaranteed to be non-lazy. Hence, don't access its script!
|
|
@@ -222,17 +223,17 @@ class CompileInfo
|
|
fixedLexicalBegin_ = script->fixedLexicalBegin();
|
|
nstack_ = script->nslots() - script->nfixed();
|
|
nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
|
|
}
|
|
|
|
explicit CompileInfo(unsigned nlocals)
|
|
: script_(nullptr), fun_(nullptr), osrPc_(nullptr), osrStaticScope_(nullptr),
|
|
constructing_(false), analysisMode_(Analysis_None), scriptNeedsArgsObj_(false),
|
|
- inlineScriptTree_(nullptr)
|
|
+ mayReadFrameArgsDirectly_(false), inlineScriptTree_(nullptr)
|
|
{
|
|
nimplicit_ = 0;
|
|
nargs_ = 0;
|
|
nbodyfixed_ = 0;
|
|
nlocals_ = nlocals;
|
|
nstack_ = 1; /* For FunctionCompiler::pushPhiInput/popPhiOutput */
|
|
nslots_ = nlocals_ + nstack_;
|
|
fixedLexicalBegin_ = nlocals;
|
|
@@ -539,16 +540,20 @@ class CompileInfo
|
|
return false;
|
|
|
|
if (needsArgsObj() && isObservableArgumentSlot(slot))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
+ bool mayReadFrameArgsDirectly() const {
|
|
+ return mayReadFrameArgsDirectly_;
|
|
+ }
|
|
+
|
|
private:
|
|
unsigned nimplicit_;
|
|
unsigned nargs_;
|
|
unsigned nbodyfixed_;
|
|
unsigned nlocals_;
|
|
unsigned nstack_;
|
|
unsigned nslots_;
|
|
unsigned fixedLexicalBegin_;
|
|
@@ -559,15 +564,17 @@ class CompileInfo
|
|
bool constructing_;
|
|
AnalysisMode analysisMode_;
|
|
|
|
// Whether a script needs an arguments object is unstable over compilation
|
|
// since the arguments optimization could be marked as failed on the main
|
|
// thread, so cache a value here and use it throughout for consistency.
|
|
bool scriptNeedsArgsObj_;
|
|
|
|
+ bool mayReadFrameArgsDirectly_;
|
|
+
|
|
InlineScriptTree* inlineScriptTree_;
|
|
};
|
|
|
|
} // namespace jit
|
|
} // namespace js
|
|
|
|
#endif /* jit_CompileInfo_h */
|
|
diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp
|
|
--- a/js/src/jit/JitFrames.cpp
|
|
+++ b/js/src/jit/JitFrames.cpp
|
|
@@ -1002,17 +1002,17 @@ MarkThisAndArguments(JSTracer* trc, JitF
|
|
// formal arguments is taken care of by the frame's safepoint/snapshot,
|
|
// except when the script's lazy arguments object aliases those formals,
|
|
// in which case we mark them as well.
|
|
|
|
size_t nargs = layout->numActualArgs();
|
|
size_t nformals = 0;
|
|
if (CalleeTokenIsFunction(layout->calleeToken())) {
|
|
JSFunction* fun = CalleeTokenToFunction(layout->calleeToken());
|
|
- nformals = fun->nonLazyScript()->argumentsAliasesFormals() ? 0 : fun->nargs();
|
|
+ nformals = fun->nonLazyScript()->mayReadFrameArgsDirectly() ? 0 : fun->nargs();
|
|
}
|
|
|
|
Value* argv = layout->argv();
|
|
|
|
// Trace |this|.
|
|
gc::MarkValueRoot(trc, argv, "ion-thisv");
|
|
|
|
// Trace actual arguments beyond the formals. Note + 1 for thisv.
|
|
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
|
|
--- a/js/src/jsscript.cpp
|
|
+++ b/js/src/jsscript.cpp
|
|
@@ -3894,16 +3894,22 @@ JSScript::hasLoops()
|
|
JSTryNote* tnlimit = tn + trynotes()->length;
|
|
for (; tn < tnlimit; tn++) {
|
|
if (tn->kind == JSTRY_FOR_IN || tn->kind == JSTRY_LOOP)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
+bool
|
|
+JSScript::mayReadFrameArgsDirectly()
|
|
+{
|
|
+ return argumentsHasVarBinding() || (function_ && function_->hasRest());
|
|
+}
|
|
+
|
|
static inline void
|
|
LazyScriptHash(uint32_t lineno, uint32_t column, uint32_t begin, uint32_t end,
|
|
HashNumber hashes[3])
|
|
{
|
|
HashNumber hash = lineno;
|
|
hash = RotateLeft(hash, 4) ^ column;
|
|
hash = RotateLeft(hash, 4) ^ begin;
|
|
hash = RotateLeft(hash, 4) ^ end;
|
|
diff --git a/js/src/jsscript.h b/js/src/jsscript.h
|
|
--- a/js/src/jsscript.h
|
|
+++ b/js/src/jsscript.h
|
|
@@ -1397,16 +1397,20 @@ class JSScript : public js::gc::TenuredC
|
|
}
|
|
inline void setFunction(JSFunction* fun);
|
|
/*
|
|
* De-lazifies the canonical function. Must be called before entering code
|
|
* that expects the function to be non-lazy.
|
|
*/
|
|
inline void ensureNonLazyCanonicalFunction(JSContext* cx);
|
|
|
|
+ // Returns true if the script may read formal arguments on the stack
|
|
+ // directly, via lazy arguments or a rest parameter.
|
|
+ bool mayReadFrameArgsDirectly();
|
|
+
|
|
JSFlatString* sourceData(JSContext* cx);
|
|
|
|
static bool loadSource(JSContext* cx, js::ScriptSource* ss, bool* worked);
|
|
|
|
void setSourceObject(JSObject* object);
|
|
JSObject* sourceObject() const {
|
|
return sourceObject_;
|
|
}
|
|
|