mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
Merge m-c to fx-team.
This commit is contained in:
commit
0b9003439b
@ -79,6 +79,9 @@ TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
|
||||
if (mOffsetAcc) {
|
||||
offsetNode = mOffsetAcc->GetContent();
|
||||
offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
|
||||
NS_ASSERTION(offsetElm, "No element for offset accessible!");
|
||||
if (!offsetElm)
|
||||
return;
|
||||
frame = offsetElm->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,16 @@
|
||||
#include "mozilla/layers/PCompositorChild.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
#define TARGET_SANDBOX_EXPORTS
|
||||
#include "mozilla/sandboxTarget.h"
|
||||
#elif defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
#include "mozilla/Sandbox.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "nsIConsoleListener.h"
|
||||
@ -593,12 +600,17 @@ ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
|
||||
aPrivs;
|
||||
// If this fails, we die.
|
||||
SetCurrentProcessPrivileges(privs);
|
||||
#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#else if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
// SetCurrentProcessSandbox should be moved close to process initialization
|
||||
// time if/when possible. SetCurrentProcessPrivileges should probably be
|
||||
// moved as well. Right now this is set ONLY if we receive the
|
||||
// RecvSetProcessPrivileges message. See bug 880808.
|
||||
SetCurrentProcessSandbox();
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sandbox/chromium/base/basictypes.h"
|
||||
#include "sandbox/win/src/sandbox.h"
|
||||
#include "sandbox/win/src/sandbox_factory.h"
|
||||
#include "mozilla/sandboxTarget.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -67,14 +68,27 @@ InitializeBinder(void *aDummy) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static bool gIsSandboxEnabled = false;
|
||||
void StartSandboxCallback()
|
||||
{
|
||||
if (gIsSandboxEnabled) {
|
||||
sandbox::TargetServices* target_service =
|
||||
sandbox::SandboxFactory::GetTargetServices();
|
||||
target_service->LowerToken();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
bool isNuwa = false;
|
||||
bool isSandboxEnabled = false;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
isNuwa |= strcmp(argv[i], "-nuwa") == 0;
|
||||
isSandboxEnabled |= strcmp(argv[i], "-sandbox") == 0;
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
gIsSandboxEnabled |= strcmp(argv[i], "-sandbox") == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
@ -100,24 +114,6 @@ main(int argc, char* argv[])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
if (isSandboxEnabled) {
|
||||
sandbox::TargetServices* target_service =
|
||||
sandbox::SandboxFactory::GetTargetServices();
|
||||
if (!target_service) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sandbox::ResultCode result = target_service->Init();
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Initialization is finished, switch to the lowered token
|
||||
target_service->LowerToken();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check for the absolute minimum number of args we need to move
|
||||
// forward here. We expect the last arg to be the child process type.
|
||||
if (argc < 1)
|
||||
@ -132,6 +128,22 @@ main(int argc, char* argv[])
|
||||
mozilla::SanitizeEnvironmentVariables();
|
||||
SetDllDirectory(L"");
|
||||
}
|
||||
|
||||
#ifdef MOZ_CONTENT_SANDBOX
|
||||
if (gIsSandboxEnabled) {
|
||||
sandbox::TargetServices* target_service =
|
||||
sandbox::SandboxFactory::GetTargetServices();
|
||||
if (!target_service) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sandbox::ResultCode result = target_service->Init();
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return 2;
|
||||
}
|
||||
mozilla::SandboxTarget::Instance()->SetStartSandboxCallback(StartSandboxCallback);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
nsresult rv = XRE_InitChildProcess(argc, argv, proctype);
|
||||
|
@ -21,3 +21,11 @@ LOCAL_INCLUDES += [
|
||||
'/toolkit/xre',
|
||||
'/xpcom/base',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_CONTENT_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
||||
# For sandbox includes and the include dependencies those have
|
||||
LOCAL_INCLUDES += [
|
||||
'/security',
|
||||
'/security/sandbox',
|
||||
'/security/sandbox/chromium',
|
||||
]
|
||||
|
@ -826,7 +826,6 @@ StructTypeRepresentation::fieldNamed(jsid id) const
|
||||
|
||||
uint32_t unused;
|
||||
JSAtom *atom = JSID_TO_ATOM(id);
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
|
||||
if (atom->isIndex(&unused))
|
||||
return nullptr;
|
||||
|
@ -2865,12 +2865,10 @@ frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNo
|
||||
RootedFunction fun(cx, bce->script->functionNonDelazifying());
|
||||
JS_ASSERT(fun->isInterpreted());
|
||||
|
||||
if (fun->isInterpretedLazy()) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
if (fun->isInterpretedLazy())
|
||||
fun->setUnlazifiedScript(bce->script);
|
||||
} else {
|
||||
else
|
||||
fun->setScript(bce->script);
|
||||
}
|
||||
|
||||
bce->tellDebuggerAboutCompiledScript(cx);
|
||||
|
||||
|
@ -191,9 +191,6 @@ class BarrieredCell : public gc::Cell
|
||||
|
||||
static MOZ_ALWAYS_INLINE void readBarrier(T *thing) {
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
// Off thread Ion compilation never occurs when barriers are active.
|
||||
js::AutoThreadSafeAccess ts(thing);
|
||||
|
||||
JS::shadow::Zone *shadowZone = thing->shadowZoneFromAnyThread();
|
||||
if (shadowZone->needsBarrier()) {
|
||||
MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone));
|
||||
|
@ -1109,37 +1109,9 @@ InFreeList(ArenaHeader *aheader, void *thing)
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
// Ion compilation mainly occurs off the main thread, and may run while the
|
||||
// main thread is performing arbitrary VM operations, excepting GC activity.
|
||||
// The below class is used to mark functions and other operations which can
|
||||
// safely be performed off thread without racing. When running with thread
|
||||
// safety checking on, any access to a GC thing outside of AutoThreadSafeAccess
|
||||
// will cause an access violation.
|
||||
class MOZ_STACK_CLASS AutoThreadSafeAccess
|
||||
{
|
||||
public:
|
||||
#if defined(DEBUG) && defined(JS_CPU_X64) && !defined(XP_WIN)
|
||||
#define JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
|
||||
JSRuntime *runtime;
|
||||
gc::ArenaHeader *arena;
|
||||
|
||||
AutoThreadSafeAccess(const gc::Cell *cell MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
~AutoThreadSafeAccess();
|
||||
#else
|
||||
AutoThreadSafeAccess(const gc::Cell *cell MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~AutoThreadSafeAccess() {}
|
||||
#endif
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
gc::AllocKind
|
||||
gc::Cell::tenuredGetAllocKind() const
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return arenaHeader()->getAllocKind();
|
||||
}
|
||||
|
||||
|
@ -136,10 +136,7 @@ ICStubIterator::unlink(JSContext *cx)
|
||||
JS_ASSERT(currentStub_ != fallbackStub_);
|
||||
JS_ASSERT(!unlinked_);
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
|
||||
}
|
||||
fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
|
||||
|
||||
// Mark the current iterator position as unlinked, so operator++ works properly.
|
||||
unlinked_ = true;
|
||||
@ -1066,7 +1063,7 @@ DoProfilerFallback(JSContext *cx, BaselineFrame *frame, ICProfiler_Fallback *stu
|
||||
ICStub *optStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!optStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1797,7 +1794,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1815,7 +1812,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1830,7 +1827,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1841,7 +1838,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!booleanStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, booleanStub);
|
||||
stub->addNewStub(booleanStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1854,7 +1851,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!optStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1866,7 +1863,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, stringStub);
|
||||
stub->addNewStub(stringStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1878,7 +1875,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!objectStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, objectStub);
|
||||
stub->addNewStub(objectStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1896,7 +1893,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!objectStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, objectStub);
|
||||
stub->addNewStub(objectStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2207,7 +2204,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2218,7 +2215,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2229,7 +2226,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, stringStub);
|
||||
stub->addNewStub(stringStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2239,7 +2236,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!nilStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, nilStub);
|
||||
stub->addNewStub(nilStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2250,7 +2247,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!objStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, objStub);
|
||||
stub->addNewStub(objStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2542,11 +2539,11 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
}
|
||||
|
||||
if (ret.isDouble())
|
||||
stub->setSawDoubleResult(cx);
|
||||
stub->setSawDoubleResult();
|
||||
|
||||
// Check to see if a new stub should be generated.
|
||||
if (stub->numOptimizedStubs() >= ICBinaryArith_Fallback::MAX_OPTIMIZED_STUBS) {
|
||||
stub->noteUnoptimizableOperands(cx);
|
||||
stub->noteUnoptimizableOperands();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2559,7 +2556,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!strcatStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, strcatStub);
|
||||
stub->addNewStub(strcatStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2572,7 +2569,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!strcatStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, strcatStub);
|
||||
stub->addNewStub(strcatStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2588,13 +2585,13 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *arithStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!arithStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, arithStub);
|
||||
stub->addNewStub(arithStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle only int32 or double.
|
||||
if (!lhs.isNumber() || !rhs.isNumber()) {
|
||||
stub->noteUnoptimizableOperands(cx);
|
||||
stub->noteUnoptimizableOperands();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2618,7 +2615,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@ -2636,7 +2633,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *int32Stub = compilerInt32.getStub(compilerInt32.getStubSpace(script));
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2655,7 +2652,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *optStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!optStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@ -2663,7 +2660,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
}
|
||||
}
|
||||
|
||||
stub->noteUnoptimizableOperands(cx);
|
||||
stub->noteUnoptimizableOperands();
|
||||
return true;
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
@ -3058,7 +3055,7 @@ DoUnaryArithFallback(JSContext *cx, BaselineFrame *frame, ICUnaryArith_Fallback
|
||||
ICStub *int32Stub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3072,7 +3069,7 @@ DoUnaryArithFallback(JSContext *cx, BaselineFrame *frame, ICUnaryArith_Fallback
|
||||
ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3757,7 +3754,7 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3809,7 +3806,7 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3843,7 +3840,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, stringStub);
|
||||
stub->addNewStub(stringStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3861,7 +3858,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!argsStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, argsStub);
|
||||
stub->addNewStub(argsStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3883,7 +3880,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!argsStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, argsStub);
|
||||
stub->addNewStub(argsStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3898,7 +3895,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!denseStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, denseStub);
|
||||
stub->addNewStub(denseStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3934,7 +3931,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!typedArrayStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, typedArrayStub);
|
||||
stub->addNewStub(typedArrayStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3942,13 +3939,13 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
// be cached by either Baseline or Ion. Indicate this in the cache so that
|
||||
// Ion does not generate a cache for this op.
|
||||
if (!obj->isNative() && !obj->is<TypedArrayObject>())
|
||||
stub->noteNonNativeAccess(cx);
|
||||
stub->noteNonNativeAccess();
|
||||
|
||||
// GetElem operations which could access negative indexes generally can't
|
||||
// be optimized without the potential for bailouts, as we can't statically
|
||||
// determine that an object has no properties on such indexes.
|
||||
if (rhs.isNumber() && rhs.toNumber() < 0)
|
||||
stub->noteNegativeIndex(cx);
|
||||
stub->noteNegativeIndex();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -5014,7 +5011,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
|
||||
if (!denseStub->addUpdateStubForValue(cx, script, obj, JSID_VOIDHANDLE, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, denseStub);
|
||||
stub->addNewStub(denseStub);
|
||||
} else if (!addingCase &&
|
||||
!DenseSetElemStubExists(cx, ICStub::SetElem_Dense, stub, obj))
|
||||
{
|
||||
@ -5028,7 +5025,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
|
||||
if (!denseStub->addUpdateStubForValue(cx, script, obj, JSID_VOIDHANDLE, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, denseStub);
|
||||
stub->addNewStub(denseStub);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5061,7 +5058,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
|
||||
if (!typedArrayStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, typedArrayStub);
|
||||
stub->addNewStub(typedArrayStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -5111,13 +5108,13 @@ ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::noteArrayWriteHole(JSContext *cx, uint32_t pcOffset)
|
||||
BaselineScript::noteArrayWriteHole(uint32_t pcOffset)
|
||||
{
|
||||
ICEntry &entry = icEntryFromPCOffset(pcOffset);
|
||||
ICFallbackStub *stub = entry.fallbackStub();
|
||||
|
||||
if (stub->isSetElem_Fallback())
|
||||
stub->toSetElem_Fallback()->noteArrayWriteHole(cx);
|
||||
stub->toSetElem_Fallback()->noteArrayWriteHole();
|
||||
}
|
||||
|
||||
//
|
||||
@ -5639,7 +5636,7 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5729,7 +5726,7 @@ TryAttachScopeNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *s
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5936,7 +5933,7 @@ DoGetIntrinsicFallback(JSContext *cx, BaselineFrame *frame, ICGetIntrinsic_Fallb
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5984,7 +5981,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5996,7 +5993,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6013,7 +6010,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
if (obj->is<TypedArrayObject>()) {
|
||||
@ -6025,7 +6022,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6041,7 +6038,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6124,7 +6121,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6155,7 +6152,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6202,7 +6199,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
}
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6222,7 +6219,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6277,7 +6274,7 @@ TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6364,7 +6361,7 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
|
||||
}
|
||||
|
||||
JS_ASSERT(!attached);
|
||||
stub->noteUnoptimizableAccess(cx);
|
||||
stub->noteUnoptimizableAccess();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -7109,13 +7106,13 @@ ICGetProp_ArgumentsLength::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::noteAccessedGetter(JSContext *cx, uint32_t pcOffset)
|
||||
BaselineScript::noteAccessedGetter(uint32_t pcOffset)
|
||||
{
|
||||
ICEntry &entry = icEntryFromPCOffset(pcOffset);
|
||||
ICFallbackStub *stub = entry.fallbackStub();
|
||||
|
||||
if (stub->isGetProp_Fallback())
|
||||
stub->toGetProp_Fallback()->noteAccessedGetter(cx);
|
||||
stub->toGetProp_Fallback()->noteAccessedGetter();
|
||||
}
|
||||
|
||||
//
|
||||
@ -7156,7 +7153,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7174,7 +7171,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7196,7 +7193,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7215,7 +7212,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7290,7 +7287,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub,
|
||||
return true;
|
||||
|
||||
JS_ASSERT(!attached);
|
||||
stub->noteUnoptimizableAccess(cx);
|
||||
stub->noteUnoptimizableAccess();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -7796,7 +7793,7 @@ TryAttachFunApplyStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7813,7 +7810,7 @@ TryAttachFunApplyStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -7957,7 +7954,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
stub->unlinkStubsWithKind(cx, ICStub::Call_Scripted);
|
||||
|
||||
// Add new generalized stub.
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7986,7 +7983,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8023,7 +8020,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9155,7 +9152,7 @@ DoIteratorMoreFallback(JSContext *cx, BaselineFrame *frame, ICIteratorMore_Fallb
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script()));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -9229,7 +9226,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb
|
||||
return false;
|
||||
|
||||
if (!res.isString() && !stub->hasNonStringResult())
|
||||
stub->setHasNonStringResult(cx);
|
||||
stub->setHasNonStringResult();
|
||||
|
||||
if (iteratorObject->is<PropertyIteratorObject>() &&
|
||||
!stub->hasStub(ICStub::IteratorNext_Native))
|
||||
@ -9238,7 +9235,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script()));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -9402,7 +9399,7 @@ DoTypeOfFallback(JSContext *cx, BaselineFrame *frame, ICTypeOf_Fallback *stub, H
|
||||
ICStub *typeOfStub = compiler.getStub(compiler.getStubSpace(frame->script()));
|
||||
if (!typeOfStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, typeOfStub);
|
||||
stub->addNewStub(typeOfStub);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -9489,7 +9486,7 @@ DoRetSubFallback(JSContext *cx, BaselineFrame *frame, ICRetSub_Fallback *stub,
|
||||
if (!optStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -835,8 +835,7 @@ class ICFallbackStub : public ICStub
|
||||
}
|
||||
|
||||
// Add a new stub to the IC chain terminated by this fallback stub.
|
||||
void addNewStub(JSContext *cx, ICStub *stub) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void addNewStub(ICStub *stub) {
|
||||
JS_ASSERT(*lastStubPtrAddr_ == this);
|
||||
JS_ASSERT(stub->next() == nullptr);
|
||||
stub->setNext(this);
|
||||
@ -2442,15 +2441,13 @@ class ICBinaryArith_Fallback : public ICFallbackStub
|
||||
bool sawDoubleResult() const {
|
||||
return extra_ & SAW_DOUBLE_RESULT_BIT;
|
||||
}
|
||||
void setSawDoubleResult(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void setSawDoubleResult() {
|
||||
extra_ |= SAW_DOUBLE_RESULT_BIT;
|
||||
}
|
||||
bool hadUnoptimizableOperands() const {
|
||||
return extra_ & UNOPTIMIZABLE_OPERANDS_BIT;
|
||||
}
|
||||
void noteUnoptimizableOperands(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteUnoptimizableOperands() {
|
||||
extra_ |= UNOPTIMIZABLE_OPERANDS_BIT;
|
||||
}
|
||||
|
||||
@ -2851,16 +2848,14 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub
|
||||
return space->allocate<ICGetElem_Fallback>(code);
|
||||
}
|
||||
|
||||
void noteNonNativeAccess(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteNonNativeAccess() {
|
||||
extra_ |= EXTRA_NON_NATIVE;
|
||||
}
|
||||
bool hasNonNativeAccess() const {
|
||||
return extra_ & EXTRA_NON_NATIVE;
|
||||
}
|
||||
|
||||
void noteNegativeIndex(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteNegativeIndex() {
|
||||
extra_ |= EXTRA_NEGATIVE_INDEX;
|
||||
}
|
||||
bool hasNegativeIndex() const {
|
||||
@ -3448,8 +3443,7 @@ class ICSetElem_Fallback : public ICFallbackStub
|
||||
return space->allocate<ICSetElem_Fallback>(code);
|
||||
}
|
||||
|
||||
void noteArrayWriteHole(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteArrayWriteHole() {
|
||||
extra_ = 1;
|
||||
}
|
||||
bool hasArrayWriteHole() const {
|
||||
@ -4024,16 +4018,14 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub
|
||||
static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
|
||||
static const size_t ACCESSED_GETTER_BIT = 1;
|
||||
|
||||
void noteUnoptimizableAccess(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteUnoptimizableAccess() {
|
||||
extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
|
||||
}
|
||||
bool hadUnoptimizableAccess() const {
|
||||
return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
|
||||
}
|
||||
|
||||
void noteAccessedGetter(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteAccessedGetter() {
|
||||
extra_ |= (1u << ACCESSED_GETTER_BIT);
|
||||
}
|
||||
bool hasAccessedGetter() const {
|
||||
@ -4840,8 +4832,7 @@ class ICSetProp_Fallback : public ICFallbackStub
|
||||
}
|
||||
|
||||
static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
|
||||
void noteUnoptimizableAccess(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteUnoptimizableAccess() {
|
||||
extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
|
||||
}
|
||||
bool hadUnoptimizableAccess() const {
|
||||
@ -5742,8 +5733,7 @@ class ICIteratorNext_Fallback : public ICFallbackStub
|
||||
return space->allocate<ICIteratorNext_Fallback>(code);
|
||||
}
|
||||
|
||||
void setHasNonStringResult(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void setHasNonStringResult() {
|
||||
JS_ASSERT(extra_ == 0);
|
||||
extra_ = 1;
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ using mozilla::DebugOnly;
|
||||
bool
|
||||
SetElemICInspector::sawOOBDenseWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -40,8 +38,6 @@ SetElemICInspector::sawOOBDenseWrite() const
|
||||
bool
|
||||
SetElemICInspector::sawOOBTypedArrayWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -58,8 +54,6 @@ SetElemICInspector::sawOOBTypedArrayWrite() const
|
||||
bool
|
||||
SetElemICInspector::sawDenseWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -74,8 +68,6 @@ SetElemICInspector::sawDenseWrite() const
|
||||
bool
|
||||
SetElemICInspector::sawTypedArrayWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -90,8 +82,6 @@ SetElemICInspector::sawTypedArrayWrite() const
|
||||
bool
|
||||
BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
// Return a list of shapes seen by the baseline IC for the current op.
|
||||
// An empty list indicates no shapes are known, or there was an uncacheable
|
||||
// access.
|
||||
@ -149,8 +139,6 @@ BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes)
|
||||
ICStub *
|
||||
BaselineInspector::monomorphicStub(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return nullptr;
|
||||
|
||||
@ -168,8 +156,6 @@ BaselineInspector::monomorphicStub(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **psecond)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -190,8 +176,6 @@ BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **pseco
|
||||
MIRType
|
||||
BaselineInspector::expectedResultType(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
// Look at the IC entries for this op to guess what type it will produce,
|
||||
// returning MIRType_None otherwise.
|
||||
|
||||
@ -238,8 +222,6 @@ CanUseInt32Compare(ICStub::Kind kind)
|
||||
MCompare::CompareType
|
||||
BaselineInspector::expectedCompareType(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
ICStub *first = monomorphicStub(pc), *second = nullptr;
|
||||
if (!first && !dimorphicStub(pc, &first, &second))
|
||||
return MCompare::Compare_Unknown;
|
||||
@ -322,8 +304,6 @@ TryToSpecializeBinaryArithOp(ICStub **stubs,
|
||||
MIRType
|
||||
BaselineInspector::expectedBinaryArithSpecialization(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
MIRType result;
|
||||
ICStub *stubs[2];
|
||||
|
||||
@ -352,8 +332,6 @@ BaselineInspector::expectedBinaryArithSpecialization(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenNonNativeGetElement(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -368,8 +346,6 @@ BaselineInspector::hasSeenNonNativeGetElement(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -384,8 +360,6 @@ BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -400,8 +374,6 @@ BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
JS_ASSERT(JSOp(*pc) == JSOP_ITERNEXT);
|
||||
|
||||
if (!hasBaselineScript())
|
||||
@ -416,8 +388,6 @@ BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -437,8 +407,6 @@ BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
|
||||
JSObject *
|
||||
BaselineInspector::getTemplateObject(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return nullptr;
|
||||
|
||||
@ -466,8 +434,6 @@ BaselineInspector::getTemplateObject(jsbytecode *pc)
|
||||
JSObject *
|
||||
BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return nullptr;
|
||||
|
||||
@ -501,8 +467,6 @@ BaselineInspector::templateCallObject()
|
||||
JSObject *
|
||||
BaselineInspector::commonGetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonGetter)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
const ICEntry &entry = icEntryFromPC(pc);
|
||||
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
|
||||
if (stub->isGetProp_CallScripted() || stub->isGetProp_CallNative()) {
|
||||
@ -518,8 +482,6 @@ BaselineInspector::commonGetPropFunction(jsbytecode *pc, Shape **lastProperty, J
|
||||
JSObject *
|
||||
BaselineInspector::commonSetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonSetter)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
const ICEntry &entry = icEntryFromPC(pc);
|
||||
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
|
||||
if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
|
||||
|
@ -294,8 +294,8 @@ struct BaselineScript
|
||||
|
||||
void toggleSPS(bool enable);
|
||||
|
||||
void noteAccessedGetter(JSContext *cx, uint32_t pcOffset);
|
||||
void noteArrayWriteHole(JSContext *cx, uint32_t pcOffset);
|
||||
void noteAccessedGetter(uint32_t pcOffset);
|
||||
void noteArrayWriteHole(uint32_t pcOffset);
|
||||
|
||||
static size_t offsetOfFlags() {
|
||||
return offsetof(BaselineScript, flags_);
|
||||
|
@ -3568,7 +3568,6 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
|
||||
Register obj = ToRegister(lir->output());
|
||||
|
||||
JSObject *templateObj = lir->mir()->templateObject();
|
||||
AutoThreadSafeAccess ts(templateObj);
|
||||
|
||||
// If we have a template object, we can inline call object creation.
|
||||
OutOfLineCode *ool;
|
||||
|
@ -252,15 +252,6 @@ CompileCompartment::setSingletonsAsValues()
|
||||
return JS::CompartmentOptionsRef(compartment()).setSingletonsAsValues();
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
AutoLockForCompilation::AutoLockForCompilation(CompileCompartment *compartment
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
init(compartment->compartment()->runtimeFromAnyThread());
|
||||
}
|
||||
#endif
|
||||
|
||||
JitCompileOptions::JitCompileOptions()
|
||||
: cloneSingletons_(false),
|
||||
spsSlowAssertionsEnabled_(false)
|
||||
|
@ -102,8 +102,6 @@ class CompileCompartment
|
||||
{
|
||||
JSCompartment *compartment();
|
||||
|
||||
friend class js::AutoLockForCompilation;
|
||||
|
||||
public:
|
||||
static CompileCompartment *get(JSCompartment *comp);
|
||||
|
||||
|
@ -52,7 +52,6 @@
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::ThreadLocal;
|
||||
|
||||
// Assert that JitCode is gc::Cell aligned.
|
||||
@ -492,8 +491,6 @@ JitCompartment::ensureIonStubsExist(JSContext *cx)
|
||||
void
|
||||
jit::FinishOffThreadBuilder(IonBuilder *builder)
|
||||
{
|
||||
builder->script()->runtimeFromMainThread()->removeCompilationThread();
|
||||
|
||||
ExecutionMode executionMode = builder->info().executionMode();
|
||||
|
||||
// Clear the recompiling flag if it would have failed.
|
||||
@ -1565,9 +1562,6 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
// operation callback and can't propagate failures.
|
||||
cx->clearPendingException();
|
||||
}
|
||||
} else {
|
||||
if (builder->abortReason() == AbortReason_Disable)
|
||||
SetIonScript(builder->script(), builder->info().executionMode(), ION_DISABLED_SCRIPT);
|
||||
}
|
||||
|
||||
FinishOffThreadBuilder(builder);
|
||||
@ -1722,6 +1716,14 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
builderScript->ionScript()->setRecompiling();
|
||||
}
|
||||
|
||||
IonSpewNewFunction(graph, builderScript);
|
||||
|
||||
bool succeeded = builder->build();
|
||||
builder->clearForBackEnd();
|
||||
|
||||
if (!succeeded)
|
||||
return builder->abortReason();
|
||||
|
||||
// If possible, compile the script off thread.
|
||||
if (OffThreadCompilationAvailable(cx)) {
|
||||
if (!recompile)
|
||||
@ -1742,42 +1744,12 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
return AbortReason_NoAbort;
|
||||
}
|
||||
|
||||
Maybe<AutoEnterIonCompilation> ionCompiling;
|
||||
if (!cx->runtime()->profilingScripts && !IonSpewEnabled(IonSpew_Logs)) {
|
||||
// Compilation with script profiling is only done on the main thread,
|
||||
// and may modify scripts directly. Same for logging. It is only
|
||||
// enabled when offthread compilation is disabled. So don't watch for
|
||||
// proper use of the compilation lock.
|
||||
ionCompiling.construct();
|
||||
}
|
||||
|
||||
Maybe<AutoProtectHeapForIonCompilation> protect;
|
||||
if (js_JitOptions.checkThreadSafety &&
|
||||
cx->runtime()->gcIncrementalState == gc::NO_INCREMENTAL &&
|
||||
!cx->runtime()->profilingScripts)
|
||||
{
|
||||
protect.construct(cx->runtime());
|
||||
}
|
||||
|
||||
IonSpewNewFunction(graph, builderScript);
|
||||
|
||||
bool succeeded = builder->build();
|
||||
builder->clearForBackEnd();
|
||||
|
||||
if (!succeeded)
|
||||
return builder->abortReason();
|
||||
|
||||
ScopedJSDeletePtr<CodeGenerator> codegen(CompileBackEnd(builder));
|
||||
if (!codegen) {
|
||||
IonSpew(IonSpew_Abort, "Failed during back-end compilation.");
|
||||
return AbortReason_Disable;
|
||||
}
|
||||
|
||||
if (!protect.empty())
|
||||
protect.destroy();
|
||||
if (!ionCompiling.empty())
|
||||
ionCompiling.destroy();
|
||||
|
||||
bool success = codegen->link(cx, builder->constraints());
|
||||
|
||||
IonSpewEndFunction();
|
||||
|
@ -140,21 +140,13 @@ IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
|
||||
script_ = info->script();
|
||||
pc = info->startPC();
|
||||
|
||||
#ifdef DEBUG
|
||||
lock();
|
||||
JS_ASSERT(script()->hasBaselineScript());
|
||||
unlock();
|
||||
#endif
|
||||
JS_ASSERT(!!analysisContext == (info->executionMode() == DefinitePropertiesAnalysis));
|
||||
}
|
||||
|
||||
void
|
||||
IonBuilder::clearForBackEnd()
|
||||
{
|
||||
// This case should only be hit if there was a failure while building.
|
||||
if (!lock_.empty())
|
||||
lock_.destroy();
|
||||
|
||||
JS_ASSERT(!analysisContext);
|
||||
baselineFrame_ = nullptr;
|
||||
|
||||
@ -292,8 +284,6 @@ IonBuilder::getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constr
|
||||
fun = &obj->as<JSFunction>();
|
||||
} else {
|
||||
types::TypeObject *typeObj = calleeTypes->getTypeObject(i);
|
||||
AutoThreadSafeAccess ts(typeObj);
|
||||
|
||||
JS_ASSERT(typeObj);
|
||||
if (!typeObj->interpretedFunction) {
|
||||
targets.clear();
|
||||
@ -593,16 +583,12 @@ IonBuilder::pushLoop(CFGState::State initial, jsbytecode *stopAt, MBasicBlock *e
|
||||
bool
|
||||
IonBuilder::init()
|
||||
{
|
||||
lock();
|
||||
|
||||
if (!types::TypeScript::FreezeTypeSets(constraints(), script(),
|
||||
&thisTypes, &argTypes, &typeArray))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
if (!analysis().init(alloc(), gsn))
|
||||
return false;
|
||||
|
||||
@ -721,8 +707,6 @@ IonBuilder::build()
|
||||
if (!traverseBytecode())
|
||||
return false;
|
||||
|
||||
unlock();
|
||||
|
||||
if (!maybeAddOsrTypeBarriers())
|
||||
return false;
|
||||
|
||||
@ -882,7 +866,6 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
|
||||
if (!traverseBytecode())
|
||||
return false;
|
||||
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -937,9 +920,6 @@ IonBuilder::initParameters()
|
||||
// interpreter and didn't accumulate type information, try to use that OSR
|
||||
// frame to determine possible initial types for 'this' and parameters.
|
||||
|
||||
// For unknownProperties() tests under addType.
|
||||
lock();
|
||||
|
||||
if (thisTypes->empty() && baselineFrame_) {
|
||||
if (!thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc()))
|
||||
return false;
|
||||
@ -963,8 +943,6 @@ IonBuilder::initParameters()
|
||||
current->initSlot(info().argSlotUnchecked(i), param);
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -987,8 +965,6 @@ IonBuilder::initScopeChain(MDefinition *callee)
|
||||
if (!script()->compileAndGo())
|
||||
return abort("non-CNG global scripts are not supported");
|
||||
|
||||
lock();
|
||||
|
||||
if (JSFunction *fun = info().funMaybeLazy()) {
|
||||
if (!callee) {
|
||||
MCallee *calleeIns = MCallee::New(alloc());
|
||||
@ -1014,8 +990,6 @@ IonBuilder::initScopeChain(MDefinition *callee)
|
||||
scope = constant(ObjectValue(script()->global()));
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
current->setScopeChain(scope);
|
||||
return true;
|
||||
}
|
||||
@ -1209,14 +1183,6 @@ IonBuilder::maybeAddOsrTypeBarriers()
|
||||
bool
|
||||
IonBuilder::traverseBytecode()
|
||||
{
|
||||
// Always hold the compilation lock when traversing bytecode, though release
|
||||
// it before reacquiring it every few opcodes so that the main thread does not
|
||||
// block for long when updating compilation data.
|
||||
lock();
|
||||
|
||||
size_t lockOpcodeCount = 0;
|
||||
static const size_t LOCK_OPCODE_GRANULARITY = 5;
|
||||
|
||||
for (;;) {
|
||||
JS_ASSERT(pc < info().limitPC());
|
||||
|
||||
@ -1291,12 +1257,6 @@ IonBuilder::traverseBytecode()
|
||||
if (!inspectOpcode(op))
|
||||
return false;
|
||||
|
||||
if (++lockOpcodeCount == LOCK_OPCODE_GRANULARITY) {
|
||||
unlock();
|
||||
lock();
|
||||
lockOpcodeCount = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0; i < popped.length(); i++) {
|
||||
switch (op) {
|
||||
@ -3881,21 +3841,17 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
JSScript *calleeScript = target->nonLazyScript();
|
||||
BaselineInspector inspector(calleeScript);
|
||||
|
||||
// Improve type information of |this| when not set.
|
||||
if (callInfo.constructing() &&
|
||||
!callInfo.thisArg()->resultTypeSet() &&
|
||||
calleeScript->types)
|
||||
{
|
||||
AutoThreadSafeAccess ts(calleeScript);
|
||||
|
||||
// Improve type information of |this| when not set.
|
||||
if (callInfo.constructing() &&
|
||||
!callInfo.thisArg()->resultTypeSet() &&
|
||||
calleeScript->types)
|
||||
{
|
||||
types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
|
||||
if (!types->unknown()) {
|
||||
MTypeBarrier *barrier =
|
||||
MTypeBarrier::New(alloc(), callInfo.thisArg(), types->clone(alloc_->lifoAlloc()));
|
||||
current->add(barrier);
|
||||
callInfo.setThis(barrier);
|
||||
}
|
||||
types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
|
||||
if (!types->unknown()) {
|
||||
MTypeBarrier *barrier =
|
||||
MTypeBarrier::New(alloc(), callInfo.thisArg(), types->clone(alloc_->lifoAlloc()));
|
||||
current->add(barrier);
|
||||
callInfo.setThis(barrier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3911,8 +3867,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
MIRGraphReturns returns(alloc());
|
||||
AutoAccumulateReturns aar(graph(), returns);
|
||||
|
||||
unlock();
|
||||
|
||||
// Build the graph.
|
||||
IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
|
||||
&inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
|
||||
@ -3927,7 +3881,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
// Inlining the callee failed. Mark the callee as uninlineable only if
|
||||
// the inlining was aborted for a non-exception reason.
|
||||
if (inlineBuilder.abortReason_ == AbortReason_Disable) {
|
||||
AutoThreadSafeAccess ts(calleeScript);
|
||||
calleeScript->setUninlineable();
|
||||
abortReason_ = AbortReason_Inlining;
|
||||
} else if (inlineBuilder.abortReason_ == AbortReason_Inlining) {
|
||||
@ -3937,8 +3890,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
return false;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
// Create return block.
|
||||
jsbytecode *postCall = GetNextPc(pc);
|
||||
MBasicBlock *returnBlock = newBlock(nullptr, postCall);
|
||||
@ -3957,7 +3908,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
// Accumulate return values.
|
||||
if (returns.empty()) {
|
||||
// Inlining of functions that have no exit is not supported.
|
||||
AutoThreadSafeAccess ts(calleeScript);
|
||||
calleeScript->setUninlineable();
|
||||
abortReason_ = AbortReason_Inlining;
|
||||
return false;
|
||||
@ -4618,7 +4568,6 @@ IonBuilder::createDeclEnvObject(MDefinition *callee, MDefinition *scope)
|
||||
// Get a template CallObject that we'll use to generate inline object
|
||||
// creation.
|
||||
DeclEnvObject *templateObj = inspector->templateDeclEnvObject();
|
||||
AutoThreadSafeAccess ts(templateObj);
|
||||
|
||||
// One field is added to the function to handle its name. This cannot be a
|
||||
// dynamic slot because there is still plenty of room on the DeclEnv object.
|
||||
@ -4646,12 +4595,11 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
// Get a template CallObject that we'll use to generate inline object
|
||||
// creation.
|
||||
CallObject *templateObj = inspector->templateCallObject();
|
||||
AutoThreadSafeAccess ts(templateObj);
|
||||
|
||||
// If the CallObject needs dynamic slots, allocate those now.
|
||||
MInstruction *slots;
|
||||
if (templateObj->hasDynamicSlots()) {
|
||||
size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlotsForCompilation(),
|
||||
size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlots(),
|
||||
templateObj->lastProperty()->slotSpan(templateObj->getClass()),
|
||||
templateObj->getClass());
|
||||
slots = MNewSlots::New(alloc(), nslots);
|
||||
@ -4677,8 +4625,8 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
unsigned slot = i.scopeSlot();
|
||||
unsigned formal = i.frameIndex();
|
||||
MDefinition *param = current->getSlot(info().argSlotUnchecked(formal));
|
||||
if (slot >= templateObj->numFixedSlotsForCompilation())
|
||||
current->add(MStoreSlot::New(alloc(), slots, slot - templateObj->numFixedSlotsForCompilation(), param));
|
||||
if (slot >= templateObj->numFixedSlots())
|
||||
current->add(MStoreSlot::New(alloc(), slots, slot - templateObj->numFixedSlots(), param));
|
||||
else
|
||||
current->add(MStoreFixedSlot::New(alloc(), callObj, slot, param));
|
||||
}
|
||||
@ -4750,13 +4698,10 @@ IonBuilder::createThisScriptedSingleton(JSFunction *target, MDefinition *callee)
|
||||
if (!templateObject->hasTenuredProto() || templateObject->getProto() != proto)
|
||||
return nullptr;
|
||||
|
||||
{
|
||||
AutoThreadSafeAccess ts(target->nonLazyScript());
|
||||
if (!target->nonLazyScript()->types)
|
||||
return nullptr;
|
||||
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(templateObject)))
|
||||
return nullptr;
|
||||
}
|
||||
if (!target->nonLazyScript()->types)
|
||||
return nullptr;
|
||||
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(templateObject)))
|
||||
return nullptr;
|
||||
|
||||
// For template objects with NewScript info, the appropriate allocation
|
||||
// kind to use may change due to dynamic property adds. In these cases
|
||||
@ -5157,8 +5102,6 @@ IonBuilder::testNeedsArgumentCheck(JSFunction *target, CallInfo &callInfo)
|
||||
|
||||
JSScript *targetScript = target->nonLazyScript();
|
||||
|
||||
AutoThreadSafeAccess ts(targetScript);
|
||||
|
||||
if (!targetScript->types)
|
||||
return true;
|
||||
|
||||
@ -5357,7 +5300,6 @@ IonBuilder::jsop_eval(uint32_t argc)
|
||||
string->getOperand(1)->toConstant()->value().isString())
|
||||
{
|
||||
JSAtom *atom = &string->getOperand(1)->toConstant()->value().toString()->asAtom();
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
|
||||
if (StringEqualsAscii(atom, "()")) {
|
||||
MDefinition *name = string->getOperand(0);
|
||||
@ -5431,7 +5373,6 @@ IonBuilder::jsop_newarray(uint32_t count)
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
ins->resultTypeSet()->convertDoubleElements(constraints());
|
||||
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateObject->setShouldConvertDoubleElements();
|
||||
else
|
||||
@ -5514,7 +5455,6 @@ IonBuilder::jsop_initelem_array()
|
||||
current->add(elements);
|
||||
|
||||
JSObject *templateObject = obj->toNewArray()->templateObject();
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
|
||||
if (templateObject->shouldConvertDoubleElements()) {
|
||||
MInstruction *valueDouble = MToDouble::New(alloc(), value);
|
||||
@ -5556,7 +5496,6 @@ IonBuilder::jsop_initprop(PropertyName *name)
|
||||
MDefinition *obj = current->peek(-1);
|
||||
|
||||
JSObject *templateObject = obj->toNewObject()->templateObject();
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
|
||||
Shape *shape = templateObject->lastProperty()->searchLinear(NameToId(name));
|
||||
|
||||
@ -9179,9 +9118,6 @@ IonBuilder::jsop_regexp(RegExpObject *reobj)
|
||||
// then check if this regex object only flows into known natives and can
|
||||
// avoid cloning in this case.
|
||||
|
||||
// RegExpObjects embedded in scripts are immutable.
|
||||
AutoThreadSafeAccess ts(reobj);
|
||||
|
||||
bool mustClone = true;
|
||||
types::TypeObjectKey *typeObj = types::TypeObjectKey::get(&script()->global());
|
||||
if (!typeObj->hasFlags(constraints(), types::OBJECT_FLAG_REGEXP_FLAGS_SET)) {
|
||||
|
@ -787,17 +787,6 @@ class IonBuilder : public MIRGenerator
|
||||
// Constraints for recording dependencies on type information.
|
||||
types::CompilerConstraintList *constraints_;
|
||||
|
||||
mozilla::Maybe<AutoLockForCompilation> lock_;
|
||||
|
||||
void lock() {
|
||||
if (!analysisContext)
|
||||
lock_.construct(compartment);
|
||||
}
|
||||
void unlock() {
|
||||
if (!analysisContext)
|
||||
lock_.destroy();
|
||||
}
|
||||
|
||||
// Basic analysis information about the script.
|
||||
BytecodeAnalysis analysis_;
|
||||
BytecodeAnalysis &analysis() {
|
||||
|
@ -82,7 +82,6 @@ class JitCode : public gc::BarrieredCell<JitCode>
|
||||
|
||||
public:
|
||||
uint8_t *raw() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return code_;
|
||||
}
|
||||
size_t instructionsSize() const {
|
||||
|
@ -787,10 +787,6 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
|
||||
{
|
||||
// Fast initialization of an empty object returned by NewGCThing().
|
||||
|
||||
AutoThreadSafeAccess ts0(templateObject);
|
||||
AutoThreadSafeAccess ts1(templateObject->lastProperty());
|
||||
AutoThreadSafeAccess ts2(templateObject->lastProperty()->base()); // For isNative() assertions.
|
||||
|
||||
JS_ASSERT(!templateObject->hasDynamicElements());
|
||||
|
||||
storePtr(ImmGCPtr(templateObject->lastProperty()), Address(obj, JSObject::offsetOfShape()));
|
||||
@ -822,7 +818,7 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
|
||||
|
||||
// Fixed slots of non-array objects are required to be initialized.
|
||||
// Use the values currently in the template object.
|
||||
size_t nslots = Min(templateObject->numFixedSlotsForCompilation(),
|
||||
size_t nslots = Min(templateObject->numFixedSlots(),
|
||||
templateObject->lastProperty()->slotSpan(templateObject->getClass()));
|
||||
for (unsigned i = 0; i < nslots; i++) {
|
||||
storeValue(templateObject->getFixedSlot(i),
|
||||
|
@ -33,10 +33,6 @@ JitOptions::JitOptions()
|
||||
// RangeAnalysis results.
|
||||
checkRangeAnalysis = false;
|
||||
|
||||
// Whether to protect the GC heap during Ion compilation and ensure that
|
||||
// only threadsafe operations are performed on it.
|
||||
checkThreadSafety = false;
|
||||
|
||||
// Whether Ion should compile try-catch statements.
|
||||
compileTryCatch = true;
|
||||
|
||||
|
@ -45,7 +45,6 @@ struct JitOptions
|
||||
bool checkOsiPointRegisters;
|
||||
#endif
|
||||
bool checkRangeAnalysis;
|
||||
bool checkThreadSafety;
|
||||
bool compileTryCatch;
|
||||
bool disableGvn;
|
||||
bool disableLicm;
|
||||
|
@ -257,13 +257,10 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
getInlineReturnTypeSet()->convertDoubleElements(constraints());
|
||||
{
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateObject->setShouldConvertDoubleElements();
|
||||
else
|
||||
templateObject->clearShouldConvertDoubleElements();
|
||||
}
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateObject->setShouldConvertDoubleElements();
|
||||
else
|
||||
templateObject->clearShouldConvertDoubleElements();
|
||||
|
||||
MNewArray *ins = MNewArray::New(alloc(), constraints(), initLength, templateObject,
|
||||
templateObject->type()->initialHeap(constraints()),
|
||||
|
@ -788,8 +788,6 @@ MStringLength::foldsTo(TempAllocator &alloc, bool useValueNumbers)
|
||||
if ((type() == MIRType_Int32) && (string()->isConstant())) {
|
||||
Value value = string()->toConstant()->value();
|
||||
JSAtom *atom = &value.toString()->asAtom();
|
||||
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
return MConstant::New(alloc, Int32Value(atom->length()));
|
||||
}
|
||||
|
||||
@ -2607,7 +2605,6 @@ MBeta::printOpcode(FILE *fp) const
|
||||
bool
|
||||
MNewObject::shouldUseVM() const
|
||||
{
|
||||
AutoThreadSafeAccess ts(templateObject());
|
||||
return templateObject()->hasSingletonType() ||
|
||||
templateObject()->hasDynamicSlots();
|
||||
}
|
||||
|
@ -279,7 +279,6 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (GetIonContext()->cx) {
|
||||
AutoThreadSafeAccess ts(script);
|
||||
uint32_t stackDepth;
|
||||
bool reachablePC;
|
||||
if (!ReconstructStackDepth(GetIonContext()->cx, script, bailPC, &stackDepth, &reachablePC))
|
||||
|
@ -31,7 +31,6 @@ namespace js {
|
||||
inline jsid
|
||||
AtomToId(JSAtom *atom)
|
||||
{
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
JS_STATIC_ASSERT(JSID_INT_MIN == 0);
|
||||
|
||||
uint32_t index;
|
||||
|
@ -29,8 +29,6 @@ BooleanGetPrimitiveValue(HandleObject obj, JSContext *cx)
|
||||
inline bool
|
||||
EmulatesUndefined(JSObject *obj)
|
||||
{
|
||||
AutoThreadSafeAccess ts0(obj);
|
||||
AutoThreadSafeAccess ts1(obj->typeRaw());
|
||||
JSObject *actual = MOZ_LIKELY(!obj->is<WrapperObject>()) ? obj : UncheckedUnwrap(obj);
|
||||
return actual->getClass()->emulatesUndefined();
|
||||
}
|
||||
|
@ -116,7 +116,6 @@ js::ExistingCloneFunctionAtCallsite(const CallsiteCloneTable &table, JSFunction
|
||||
JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite());
|
||||
JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
|
||||
JS_ASSERT(types::UseNewTypeForClone(fun));
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
/*
|
||||
* If we start allocating function objects in the nursery, then the callsite
|
||||
@ -154,8 +153,6 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri
|
||||
typedef CallsiteCloneKey Key;
|
||||
typedef CallsiteCloneTable Table;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
|
||||
Table &table = cx->compartment()->callsiteClones;
|
||||
if (!table.initialized() && !table.init())
|
||||
return nullptr;
|
||||
|
@ -1087,69 +1087,6 @@ class AutoLockForExclusiveAccess
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
class AutoLockForCompilation
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
JSRuntime *runtime;
|
||||
|
||||
void init(JSRuntime *rt) {
|
||||
runtime = rt;
|
||||
if (runtime->numCompilationThreads) {
|
||||
runtime->assertCanLock(CompilationLock);
|
||||
PR_Lock(runtime->compilationLock);
|
||||
#ifdef DEBUG
|
||||
runtime->compilationLockOwner = PR_GetCurrentThread();
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(!runtime->mainThreadHasCompilationLock);
|
||||
runtime->mainThreadHasCompilationLock = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
AutoLockForCompilation(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
if (cx->isJSContext())
|
||||
init(cx->asJSContext()->runtime());
|
||||
else
|
||||
runtime = nullptr;
|
||||
}
|
||||
AutoLockForCompilation(jit::CompileCompartment *compartment MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
~AutoLockForCompilation() {
|
||||
if (runtime) {
|
||||
if (runtime->numCompilationThreads) {
|
||||
JS_ASSERT(runtime->compilationLockOwner == PR_GetCurrentThread());
|
||||
#ifdef DEBUG
|
||||
runtime->compilationLockOwner = nullptr;
|
||||
#endif
|
||||
PR_Unlock(runtime->compilationLock);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(runtime->mainThreadHasCompilationLock);
|
||||
runtime->mainThreadHasCompilationLock = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // JS_THREADSAFE
|
||||
public:
|
||||
AutoLockForCompilation(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
AutoLockForCompilation(jit::CompileCompartment *compartment MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~AutoLockForCompilation() {
|
||||
// An empty destructor is needed to avoid warnings from clang about
|
||||
// unused local variables of this type.
|
||||
}
|
||||
#endif // JS_THREADSAFE
|
||||
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -22,14 +22,7 @@ JSCompartment::initGlobal(js::GlobalObject &global)
|
||||
js::GlobalObject *
|
||||
JSCompartment::maybeGlobal() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (global_) {
|
||||
js::AutoThreadSafeAccess ts0(global_);
|
||||
js::AutoThreadSafeAccess ts1(global_->lastProperty());
|
||||
js::AutoThreadSafeAccess ts2(global_->lastProperty()->base());
|
||||
JS_ASSERT(global_->compartment() == this);
|
||||
}
|
||||
#endif
|
||||
JS_ASSERT_IF(global_, global_->compartment() == this);
|
||||
return global_;
|
||||
}
|
||||
|
||||
|
@ -1150,7 +1150,6 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
|
||||
RootedScript script(cx, lazy->maybeScript());
|
||||
|
||||
if (script) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
fun->setUnlazifiedScript(script);
|
||||
// Remember the lazy script on the compiled script, so it can be
|
||||
// stored on the function again in case of re-lazification.
|
||||
@ -1167,7 +1166,6 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
fun->setUnlazifiedScript(script);
|
||||
return true;
|
||||
}
|
||||
@ -1196,10 +1194,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
|
||||
fun->initAtom(script->functionNonDelazifying()->displayAtom());
|
||||
clonedScript->setFunction(fun);
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
fun->setUnlazifiedScript(clonedScript);
|
||||
}
|
||||
fun->setUnlazifiedScript(clonedScript);
|
||||
|
||||
CallNewScriptHook(cx, clonedScript, fun);
|
||||
|
||||
|
@ -105,12 +105,10 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
size_t nargs() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return nargs_;
|
||||
}
|
||||
|
||||
uint16_t flags() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return flags_;
|
||||
}
|
||||
|
||||
@ -134,14 +132,10 @@ class JSFunction : public JSObject
|
||||
return flags() & SH_WRAPPABLE;
|
||||
}
|
||||
|
||||
// Functions can change between being lazily interpreted and having scripts
|
||||
// when under the compilation lock.
|
||||
bool isInterpretedLazy() const {
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return flags() & INTERPRETED_LAZY;
|
||||
}
|
||||
bool hasScript() const {
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return flags() & INTERPRETED;
|
||||
}
|
||||
|
||||
@ -238,7 +232,6 @@ class JSFunction : public JSObject
|
||||
void initAtom(JSAtom *atom) { atom_.init(atom); }
|
||||
|
||||
JSAtom *displayAtom() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return atom_;
|
||||
}
|
||||
|
||||
@ -258,7 +251,6 @@ class JSFunction : public JSObject
|
||||
* activations (stack frames) of the function.
|
||||
*/
|
||||
JSObject *environment() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isInterpreted());
|
||||
return u.i.env_;
|
||||
}
|
||||
@ -332,8 +324,6 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
JSScript *nonLazyScript() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
JS_ASSERT(hasScript());
|
||||
JS_ASSERT(u.i.s.script_);
|
||||
return u.i.s.script_;
|
||||
@ -355,16 +345,12 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
js::LazyScript *lazyScript() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_);
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return u.i.s.lazy_;
|
||||
}
|
||||
|
||||
js::LazyScript *lazyScriptOrNull() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isInterpretedLazy());
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return u.i.s.lazy_;
|
||||
}
|
||||
|
||||
@ -398,7 +384,6 @@ class JSFunction : public JSObject
|
||||
void setUnlazifiedScript(JSScript *script) {
|
||||
// Note: createScriptForLazilyInterpretedFunction triggers a barrier on
|
||||
// lazy script before it is overwritten here.
|
||||
JS_ASSERT(js::CurrentThreadCanWriteCompilationData());
|
||||
JS_ASSERT(isInterpretedLazy());
|
||||
if (!lazyScript()->maybeScript())
|
||||
lazyScript()->initScript(script);
|
||||
@ -415,7 +400,6 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
JSNative native() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isNative());
|
||||
return u.n.native;
|
||||
}
|
||||
@ -440,7 +424,6 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
const JSJitInfo *jitInfo() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isNative());
|
||||
return u.n.jitinfo;
|
||||
}
|
||||
|
@ -688,9 +688,6 @@ TypeScript::FreezeTypeSets(CompilerConstraintList *constraints, JSScript *script
|
||||
TemporaryTypeSet **pArgTypes,
|
||||
TemporaryTypeSet **pBytecodeTypes)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(script);
|
||||
|
||||
LifoAlloc *alloc = constraints->alloc();
|
||||
StackTypeSet *existing = script->types->typeArray();
|
||||
|
||||
@ -810,7 +807,6 @@ TypeObjectKey::proto()
|
||||
bool
|
||||
ObjectImpl::hasTenuredProto() const
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->hasTenuredProto();
|
||||
}
|
||||
|
||||
@ -856,7 +852,6 @@ HeapTypeSetKey
|
||||
TypeObjectKey::property(jsid id)
|
||||
{
|
||||
JS_ASSERT(!unknownProperties());
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
HeapTypeSetKey property;
|
||||
property.object_ = this;
|
||||
@ -1513,10 +1508,8 @@ ObjectStateChange(ExclusiveContext *cxArg, TypeObject *object, bool markingUnkno
|
||||
HeapTypeSet *types = object->maybeGetProperty(JSID_EMPTY);
|
||||
|
||||
/* Mark as unknown after getting the types, to avoid assertion. */
|
||||
if (markingUnknown) {
|
||||
AutoLockForCompilation lock(cxArg);
|
||||
if (markingUnknown)
|
||||
object->addFlags(OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES);
|
||||
}
|
||||
|
||||
if (types) {
|
||||
if (JSContext *cx = cxArg->maybeJSContext()) {
|
||||
@ -2336,7 +2329,6 @@ TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target)
|
||||
}
|
||||
}
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
target->addFlags(OBJECT_FLAG_SETS_MARKED_UNKNOWN);
|
||||
}
|
||||
|
||||
@ -2756,28 +2748,9 @@ TypeCompartment::newTypedObject(JSContext *cx, IdValuePair *properties, size_t n
|
||||
// TypeObject
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
TypeObject::assertCanAccessProto() const
|
||||
{
|
||||
// The proto pointer for type objects representing singletons may move.
|
||||
JS_ASSERT_IF(singleton(), CurrentThreadCanReadCompilationData());
|
||||
|
||||
// Any proto pointer which is in the nursery may be moved, and may not be
|
||||
// accessed during off thread compilation.
|
||||
#if defined(JSGC_GENERATIONAL) && defined(JS_THREADSAFE)
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
TaggedProto proto(proto_);
|
||||
JS_ASSERT_IF(proto.isObject() && !proto.toObject()->isTenured(),
|
||||
!pt || !pt->ionCompiling);
|
||||
#endif
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void
|
||||
TypeObject::setProto(JSContext *cx, TaggedProto proto)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
JS_ASSERT(singleton());
|
||||
|
||||
if (proto.isObject() && IsInsideNursery(cx->runtime(), proto.toObject()))
|
||||
@ -3056,10 +3029,7 @@ TypeObject::setFlags(ExclusiveContext *cx, TypeObjectFlags flags)
|
||||
singleton()->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON));
|
||||
}
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
addFlags(flags);
|
||||
}
|
||||
addFlags(flags);
|
||||
|
||||
InferSpew(ISpewOps, "%s: setFlags 0x%x", TypeObjectString(this), flags);
|
||||
|
||||
@ -3104,10 +3074,8 @@ void
|
||||
TypeObject::clearAddendum(ExclusiveContext *cx)
|
||||
{
|
||||
JS_ASSERT(!(flags() & OBJECT_FLAG_ADDENDUM_CLEARED));
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
addFlags(OBJECT_FLAG_ADDENDUM_CLEARED);
|
||||
}
|
||||
|
||||
addFlags(OBJECT_FLAG_ADDENDUM_CLEARED);
|
||||
|
||||
/*
|
||||
* It is possible for the object to not have a new script or other
|
||||
@ -3521,10 +3489,7 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
|
||||
#endif
|
||||
new (newScript) TypeNewScript();
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
type->setAddendum(newScript);
|
||||
}
|
||||
type->setAddendum(newScript);
|
||||
|
||||
if (!newScript) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
@ -3692,10 +3657,7 @@ JSScript::makeTypes(JSContext *cx)
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
new (&typeArray[i]) StackTypeSet();
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
types = typeScript;
|
||||
}
|
||||
types = typeScript;
|
||||
|
||||
#ifdef DEBUG
|
||||
for (unsigned i = 0; i < nTypeSets(); i++) {
|
||||
@ -3825,12 +3787,8 @@ JSObject::splicePrototype(JSContext *cx, const Class *clasp, Handle<TaggedProto>
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
type->setClasp(clasp);
|
||||
type->setProto(cx, proto);
|
||||
}
|
||||
|
||||
type->setClasp(clasp);
|
||||
type->setProto(cx, proto);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3883,10 +3841,7 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
|
||||
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted())
|
||||
type->interpretedFunction = &obj->as<JSFunction>();
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
obj->type_ = type;
|
||||
}
|
||||
obj->type_ = type;
|
||||
|
||||
return type;
|
||||
}
|
||||
@ -4628,7 +4583,6 @@ TypeScript::printTypes(JSContext *cx, HandleScript script) const
|
||||
void
|
||||
TypeObject::setAddendum(TypeObjectAddendum *addendum)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
this->addendum = addendum;
|
||||
}
|
||||
|
||||
|
@ -27,11 +27,6 @@ namespace js {
|
||||
|
||||
class TypeDescr;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool CurrentThreadCanWriteCompilationData();
|
||||
bool CurrentThreadCanReadCompilationData();
|
||||
#endif
|
||||
|
||||
class TaggedProto
|
||||
{
|
||||
public:
|
||||
@ -890,12 +885,6 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
|
||||
/* Prototype shared by objects using this type. */
|
||||
HeapPtrObject proto_;
|
||||
|
||||
#ifdef DEBUG
|
||||
void assertCanAccessProto() const;
|
||||
#else
|
||||
void assertCanAccessProto() const {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whether there is a singleton JS object with this type. That JS object
|
||||
* must appear in type sets instead of this; we include the back reference
|
||||
@ -906,24 +895,19 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
|
||||
public:
|
||||
|
||||
const Class *clasp() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return clasp_;
|
||||
}
|
||||
|
||||
void setClasp(const Class *clasp) {
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
JS_ASSERT(singleton());
|
||||
clasp_ = clasp;
|
||||
}
|
||||
|
||||
TaggedProto proto() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
assertCanAccessProto();
|
||||
return TaggedProto(proto_);
|
||||
}
|
||||
|
||||
JSObject *singleton() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return singleton_;
|
||||
}
|
||||
|
||||
@ -965,42 +949,30 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
|
||||
public:
|
||||
|
||||
TypeObjectFlags flags() const {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return flags_;
|
||||
}
|
||||
|
||||
void addFlags(TypeObjectFlags flags) {
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
flags_ |= flags;
|
||||
}
|
||||
|
||||
void clearFlags(TypeObjectFlags flags) {
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
flags_ &= ~flags;
|
||||
}
|
||||
|
||||
bool hasNewScript() const {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum && addendum->isNewScript();
|
||||
}
|
||||
|
||||
TypeNewScript *newScript() {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum->asNewScript();
|
||||
}
|
||||
|
||||
bool hasTypedObject() {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum && addendum->isTypedObject();
|
||||
}
|
||||
|
||||
TypeTypedObject *typedObject() {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum->asTypedObject();
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,6 @@ Type::ObjectType(JSObject *obj)
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(TypeObject *obj)
|
||||
{
|
||||
AutoThreadSafeAccess ts(obj);
|
||||
if (obj->singleton())
|
||||
return Type(uintptr_t(obj->singleton()) | 1);
|
||||
return Type(uintptr_t(obj));
|
||||
@ -178,7 +177,6 @@ IdToTypeId(jsid id)
|
||||
*/
|
||||
if (JSID_IS_STRING(id)) {
|
||||
JSAtom *atom = JSID_TO_ATOM(id);
|
||||
js::AutoThreadSafeAccess ts(atom);
|
||||
JS::TwoByteChars cp = atom->range();
|
||||
if (cp.length() > 0 && (JS7_ISDEC(cp[0]) || cp[0] == '-')) {
|
||||
for (size_t i = 1; i < cp.length(); ++i) {
|
||||
@ -565,7 +563,6 @@ TypeScript::NumTypeSets(JSScript *script)
|
||||
/* static */ inline StackTypeSet *
|
||||
TypeScript::ThisTypes(JSScript *script)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
return script->types->typeArray() + script->nTypeSets() + analyze::ThisSlot();
|
||||
}
|
||||
|
||||
@ -579,7 +576,6 @@ TypeScript::ThisTypes(JSScript *script)
|
||||
TypeScript::ArgTypes(JSScript *script, unsigned i)
|
||||
{
|
||||
JS_ASSERT(i < script->functionNonDelazifying()->nargs());
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
return script->types->typeArray() + script->nTypeSets() + analyze::ArgSlot(i);
|
||||
}
|
||||
|
||||
@ -1128,12 +1124,9 @@ ConstraintTypeSet::addType(ExclusiveContext *cxArg, Type type)
|
||||
if (hasType(type))
|
||||
return;
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cxArg);
|
||||
if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) {
|
||||
cxArg->compartment()->types.setPendingNukeTypes(cxArg);
|
||||
return;
|
||||
}
|
||||
if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) {
|
||||
cxArg->compartment()->types.setPendingNukeTypes(cxArg);
|
||||
return;
|
||||
}
|
||||
|
||||
InferSpew(ISpewOps, "addType: %sT%p%s %s",
|
||||
@ -1277,7 +1270,6 @@ inline TypeObject::TypeObject(const Class *clasp, TaggedProto proto, TypeObjectF
|
||||
inline uint32_t
|
||||
TypeObject::basePropertyCount() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
return (flags() & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT;
|
||||
}
|
||||
|
||||
@ -1302,27 +1294,21 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id)
|
||||
if (HeapTypeSet *types = maybeGetProperty(id))
|
||||
return types;
|
||||
|
||||
uint32_t propertyCount;
|
||||
Property **pprop;
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
uint32_t propertyCount = basePropertyCount();
|
||||
Property **pprop = HashSetInsert<jsid,Property,Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
if (!pprop) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
propertyCount = basePropertyCount();
|
||||
pprop = HashSetInsert<jsid,Property,Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
if (!pprop) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return nullptr;
|
||||
}
|
||||
JS_ASSERT(!*pprop);
|
||||
|
||||
JS_ASSERT(!*pprop);
|
||||
|
||||
setBasePropertyCount(propertyCount);
|
||||
if (!addProperty(cx, id, pprop)) {
|
||||
setBasePropertyCount(0);
|
||||
propertySet = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
setBasePropertyCount(propertyCount);
|
||||
if (!addProperty(cx, id, pprop)) {
|
||||
setBasePropertyCount(0);
|
||||
propertySet = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
|
||||
@ -1350,9 +1336,6 @@ TypeObject::maybeGetProperty(jsid id)
|
||||
JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
|
||||
JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
|
||||
JS_ASSERT(!unknownProperties());
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
AutoThreadSafeAccess ts(this);
|
||||
|
||||
Property *prop = HashSetLookup<jsid,Property,Property>
|
||||
(propertySet, basePropertyCount(), id);
|
||||
|
@ -2048,7 +2048,6 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
|
||||
if (!LinkConstructorAndPrototype(cx, genFunction, genFunctionProto))
|
||||
return false;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
global->setSlot(STAR_GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto));
|
||||
global->setConstructor(JSProto_GeneratorFunction, ObjectValue(*genFunction));
|
||||
global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto));
|
||||
|
@ -2250,12 +2250,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
* Swap the object's types, to restore their initial type information.
|
||||
* The prototypes and classes of the objects were swapped in ReserveForTradeGuts.
|
||||
*/
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
TypeObject *tmp = a->type_;
|
||||
a->type_ = b->type_;
|
||||
b->type_ = tmp;
|
||||
}
|
||||
TypeObject *tmp = a->type_;
|
||||
a->type_ = b->type_;
|
||||
b->type_ = tmp;
|
||||
|
||||
/* Don't try to swap a JSFunction for a plain function JSObject. */
|
||||
JS_ASSERT_IF(a->is<JSFunction>(), a->tenuredSizeOfThis() == b->tenuredSizeOfThis());
|
||||
@ -2287,12 +2284,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
char tmp[mozilla::tl::Max<sizeof(JSFunction), sizeof(JSObject_Slots16)>::value];
|
||||
JS_ASSERT(size <= sizeof(tmp));
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
js_memcpy(tmp, a, size);
|
||||
js_memcpy(a, b, size);
|
||||
js_memcpy(b, tmp, size);
|
||||
}
|
||||
js_memcpy(tmp, a, size);
|
||||
js_memcpy(a, b, size);
|
||||
js_memcpy(b, tmp, size);
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
@ -2330,12 +2324,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
void *bpriv = b->hasPrivate() ? b->getPrivate() : nullptr;
|
||||
|
||||
char tmp[sizeof(JSObject)];
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
js_memcpy(&tmp, a, sizeof tmp);
|
||||
js_memcpy(a, b, sizeof tmp);
|
||||
js_memcpy(b, &tmp, sizeof tmp);
|
||||
}
|
||||
js_memcpy(&tmp, a, sizeof tmp);
|
||||
js_memcpy(a, b, sizeof tmp);
|
||||
js_memcpy(b, &tmp, sizeof tmp);
|
||||
|
||||
if (a->isNative())
|
||||
a->shape_->setNumFixedSlots(reserved.newafixed);
|
||||
@ -2785,12 +2776,6 @@ JSObject::growSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount,
|
||||
}
|
||||
}
|
||||
|
||||
// Global slots may be read during off thread compilation, and updates to
|
||||
// their slot pointers need to be synchronized.
|
||||
Maybe<AutoLockForCompilation> lock;
|
||||
if (obj->is<GlobalObject>())
|
||||
lock.construct(cx->asExclusiveContext());
|
||||
|
||||
if (!oldCount) {
|
||||
obj->slots = AllocateSlots(cx, obj, newCount);
|
||||
if (!obj->slots)
|
||||
@ -2835,12 +2820,6 @@ JSObject::shrinkSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount
|
||||
|
||||
JS_ASSERT_IF(!obj->is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
|
||||
|
||||
// Global slots may be read during off thread compilation, and updates to
|
||||
// their slot pointers need to be synchronized.
|
||||
Maybe<AutoLockForCompilation> lock;
|
||||
if (obj->is<GlobalObject>())
|
||||
lock.construct(cx->asExclusiveContext());
|
||||
|
||||
HeapSlot *newslots = ReallocateSlots(cx, obj, obj->slots, oldCount, newCount);
|
||||
if (!newslots)
|
||||
return; /* Leave slots at its old size. */
|
||||
@ -3227,10 +3206,7 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
|
||||
MarkTypeObjectUnknownProperties(cx, obj->type(), true);
|
||||
MarkTypeObjectUnknownProperties(cx, type, true);
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
obj->setType(type);
|
||||
}
|
||||
obj->setType(type);
|
||||
|
||||
*succeeded = true;
|
||||
return true;
|
||||
@ -4303,7 +4279,7 @@ NativeGetInline(JSContext *cx,
|
||||
case JSOP_GETPROP:
|
||||
case JSOP_CALLPROP:
|
||||
case JSOP_LENGTH:
|
||||
script->baselineScript()->noteAccessedGetter(cx, script->pcToOffset(pc));
|
||||
script->baselineScript()->noteAccessedGetter(script->pcToOffset(pc));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -5697,8 +5673,6 @@ DumpProperty(JSObject *obj, Shape &shape)
|
||||
bool
|
||||
JSObject::uninlinedIsProxy() const
|
||||
{
|
||||
AutoThreadSafeAccess ts0(this);
|
||||
AutoThreadSafeAccess ts1(type_);
|
||||
return is<ProxyObject>();
|
||||
}
|
||||
|
||||
|
@ -289,10 +289,6 @@ class JSObject : public js::ObjectImpl
|
||||
}
|
||||
|
||||
bool isBoundFunction() const {
|
||||
// Note: This function can race when it is called during off thread compilation.
|
||||
js::AutoThreadSafeAccess ts0(this);
|
||||
js::AutoThreadSafeAccess ts1(lastProperty());
|
||||
js::AutoThreadSafeAccess ts2(lastProperty()->base());
|
||||
return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION);
|
||||
}
|
||||
|
||||
@ -354,10 +350,6 @@ class JSObject : public js::ObjectImpl
|
||||
return lastProperty()->entryCount();
|
||||
}
|
||||
|
||||
uint32_t propertyCountForCompilation() const {
|
||||
return lastProperty()->entryCountForCompilation();
|
||||
}
|
||||
|
||||
bool hasShapeTable() const {
|
||||
return lastProperty()->hasTable();
|
||||
}
|
||||
@ -376,13 +368,13 @@ class JSObject : public js::ObjectImpl
|
||||
|
||||
/* Whether a slot is at a fixed offset from this object. */
|
||||
bool isFixedSlot(size_t slot) {
|
||||
return slot < numFixedSlotsForCompilation();
|
||||
return slot < numFixedSlots();
|
||||
}
|
||||
|
||||
/* Index into the dynamic slots array to use for a dynamic slot. */
|
||||
size_t dynamicSlotIndex(size_t slot) {
|
||||
JS_ASSERT(slot >= numFixedSlotsForCompilation());
|
||||
return slot - numFixedSlotsForCompilation();
|
||||
JS_ASSERT(slot >= numFixedSlots());
|
||||
return slot - numFixedSlots();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -400,9 +400,6 @@ JSObject::clearType(JSContext *cx, js::HandleObject obj)
|
||||
inline void
|
||||
JSObject::setType(js::types::TypeObject *newType)
|
||||
{
|
||||
// Note: This is usually called for newly created objects that haven't
|
||||
// escaped to script yet, so don't require that the compilation lock be
|
||||
// held here.
|
||||
JS_ASSERT(newType);
|
||||
JS_ASSERT(!hasSingletonType());
|
||||
type_ = newType;
|
||||
@ -999,11 +996,8 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
|
||||
JS_ASSERT(!global->nativeLookup(cx, id));
|
||||
|
||||
/* Set these first in case AddTypePropertyId looks for this class. */
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
global->setConstructor(key, ObjectValue(*ctor));
|
||||
global->setPrototype(key, ObjectValue(*proto));
|
||||
}
|
||||
global->setConstructor(key, ObjectValue(*ctor));
|
||||
global->setPrototype(key, ObjectValue(*proto));
|
||||
global->setConstructorPropertySlot(key, ObjectValue(*ctor));
|
||||
|
||||
if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) {
|
||||
|
@ -3167,10 +3167,7 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
|
||||
|
||||
JS_ASSERT(!script->isGenerator());
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
script->needsArgsObj_ = true;
|
||||
}
|
||||
script->needsArgsObj_ = true;
|
||||
|
||||
#ifdef JS_ION
|
||||
/*
|
||||
@ -3230,14 +3227,12 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
|
||||
bool
|
||||
JSScript::varIsAliased(uint32_t varSlot)
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return bindings.bindingIsAliased(bindings.numArgs() + varSlot);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::formalIsAliased(unsigned argSlot)
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return bindings.bindingIsAliased(argSlot);
|
||||
}
|
||||
|
||||
|
@ -249,8 +249,6 @@ class Bindings
|
||||
if (!callObjShape_)
|
||||
return false;
|
||||
|
||||
// Binding shapes are immutable once constructed.
|
||||
AutoThreadSafeAccess ts(callObjShape_);
|
||||
return !callObjShape_->isEmptyShape();
|
||||
}
|
||||
|
||||
@ -554,10 +552,6 @@ class ScriptSourceObject : public JSObject
|
||||
const ReadOnlyCompileOptions &options);
|
||||
|
||||
ScriptSource *source() {
|
||||
// Script source objects are immutable.
|
||||
AutoThreadSafeAccess ts0(this);
|
||||
AutoThreadSafeAccess ts1(lastProperty());
|
||||
AutoThreadSafeAccess ts2(lastProperty()->base());
|
||||
return static_cast<ScriptSource *>(getReservedSlot(SOURCE_SLOT).toPrivate());
|
||||
}
|
||||
|
||||
@ -638,22 +632,18 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
(and arguments if this is a function script) */
|
||||
|
||||
bool hasAnyAliasedBindings() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.hasAnyAliasedBindings();
|
||||
}
|
||||
|
||||
js::Binding *bindingArray() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.bindingArray();
|
||||
}
|
||||
|
||||
unsigned numArgs() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.numArgs();
|
||||
}
|
||||
|
||||
js::Shape *callObjShape() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.callObjShape();
|
||||
}
|
||||
|
||||
@ -889,11 +879,9 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
// Script bytecode is immutable after creation.
|
||||
jsbytecode *code() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return code_;
|
||||
}
|
||||
size_t length() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return length_;
|
||||
}
|
||||
|
||||
@ -917,94 +905,77 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
size_t mainOffset() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return mainOffset_;
|
||||
}
|
||||
|
||||
size_t lineno() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return lineno_;
|
||||
}
|
||||
|
||||
size_t column() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return column_;
|
||||
}
|
||||
|
||||
void setColumn(size_t column) { column_ = column; }
|
||||
|
||||
size_t nfixed() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return function_ ? bindings.numVars() : 0;
|
||||
}
|
||||
|
||||
size_t nslots() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return nslots_;
|
||||
}
|
||||
|
||||
size_t staticLevel() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return staticLevel_;
|
||||
}
|
||||
|
||||
size_t nTypeSets() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return nTypeSets_;
|
||||
}
|
||||
|
||||
size_t funLength() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funLength_;
|
||||
}
|
||||
|
||||
size_t sourceStart() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return sourceStart_;
|
||||
}
|
||||
|
||||
size_t sourceEnd() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return sourceEnd_;
|
||||
}
|
||||
|
||||
bool noScriptRval() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return noScriptRval_;
|
||||
}
|
||||
|
||||
bool savedCallerFun() const { return savedCallerFun_; }
|
||||
|
||||
bool strict() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return strict_;
|
||||
}
|
||||
|
||||
bool explicitUseStrict() const { return explicitUseStrict_; }
|
||||
|
||||
bool compileAndGo() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return compileAndGo_;
|
||||
}
|
||||
|
||||
bool selfHosted() const { return selfHosted_; }
|
||||
bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; }
|
||||
bool funHasExtensibleScope() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funHasExtensibleScope_;
|
||||
}
|
||||
bool funNeedsDeclEnvObject() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funNeedsDeclEnvObject_;
|
||||
}
|
||||
bool funHasAnyAliasedFormal() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funHasAnyAliasedFormal_;
|
||||
}
|
||||
|
||||
bool hasSingletons() const { return hasSingletons_; }
|
||||
bool treatAsRunOnce() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return treatAsRunOnce_;
|
||||
}
|
||||
bool hasRunOnce() const { return hasRunOnce_; }
|
||||
@ -1034,17 +1005,14 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
void setDirectlyInsideEval() { directlyInsideEval_ = true; }
|
||||
|
||||
bool usesArgumentsAndApply() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return usesArgumentsAndApply_;
|
||||
}
|
||||
void setUsesArgumentsAndApply() { usesArgumentsAndApply_ = true; }
|
||||
|
||||
bool shouldCloneAtCallsite() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return shouldCloneAtCallsite_;
|
||||
}
|
||||
bool shouldInline() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return shouldInline_;
|
||||
}
|
||||
|
||||
@ -1052,29 +1020,23 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
void setShouldInline() { shouldInline_ = true; }
|
||||
|
||||
bool isCallsiteClone() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return isCallsiteClone_;
|
||||
}
|
||||
bool isGeneratorExp() const { return isGeneratorExp_; }
|
||||
|
||||
bool failedBoundsCheck() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return failedBoundsCheck_;
|
||||
}
|
||||
bool failedShapeGuard() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return failedShapeGuard_;
|
||||
}
|
||||
bool hadFrequentBailouts() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return hadFrequentBailouts_;
|
||||
}
|
||||
bool uninlineable() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return uninlineable_;
|
||||
}
|
||||
bool invalidatedIdempotentCache() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return invalidatedIdempotentCache_;
|
||||
}
|
||||
|
||||
@ -1095,7 +1057,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
/* See ContextFlags::funArgumentsHasLocalBinding comment. */
|
||||
bool argumentsHasVarBinding() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return argsHasVarBinding_;
|
||||
}
|
||||
jsbytecode *argumentsBytecode() const { JS_ASSERT(code()[0] == JSOP_ARGUMENTS); return code(); }
|
||||
@ -1105,7 +1066,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
js::GeneratorKind generatorKind() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return js::GeneratorKindFromBits(generatorKindBits_);
|
||||
}
|
||||
bool isGenerator() const { return generatorKind() != js::NotGenerator; }
|
||||
@ -1130,8 +1090,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
*/
|
||||
bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
|
||||
bool needsArgsObj() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
JS_ASSERT(analyzedArgsUsage());
|
||||
return needsArgsObj_;
|
||||
}
|
||||
@ -1156,17 +1114,9 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
bool hasIonScript() const {
|
||||
// Note: While a script's baseline script is protected by the
|
||||
// compilation lock, writes to the ion script are not. This helps lock
|
||||
// ordering issues in CodeGenerator::link. Tests of script->ion during
|
||||
// off thread compilation can therefore race, though these are fairly
|
||||
// benign and the IonScript itself is never accessed.
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
|
||||
}
|
||||
bool canIonCompile() const {
|
||||
// Note: see above comment.
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return ion != ION_DISABLED_SCRIPT;
|
||||
}
|
||||
|
||||
@ -1192,8 +1142,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
bool hasBaselineScript() const {
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return baseline && baseline != BASELINE_DISABLED_SCRIPT;
|
||||
}
|
||||
bool canBaselineCompile() const {
|
||||
@ -1201,7 +1149,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
js::jit::BaselineScript *baselineScript() const {
|
||||
JS_ASSERT(hasBaselineScript());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return baseline;
|
||||
}
|
||||
inline void setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript);
|
||||
@ -1213,7 +1160,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
bool canParallelIonCompile() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return parallelIon != ION_DISABLED_SCRIPT;
|
||||
}
|
||||
|
||||
@ -1264,21 +1210,19 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
/*
|
||||
* Original compiled function for the script, if it has a function.
|
||||
* nullptr for global and eval scripts.
|
||||
* The delazifying variant ensures that the function isn't lazy, but can
|
||||
* only be used under a compilation lock. The non-delazifying variant
|
||||
* can be used off-thread and without the lock, but must only be used
|
||||
* after earlier code has called ensureNonLazyCanonicalFunction and
|
||||
* while the function can't have been relazified.
|
||||
* The delazifying variant ensures that the function isn't lazy. The
|
||||
* non-delazifying variant must only be used after earlier code has
|
||||
* called ensureNonLazyCanonicalFunction and while the function can't
|
||||
* have been relazified.
|
||||
*/
|
||||
inline JSFunction *functionDelazifying() const;
|
||||
JSFunction *functionNonDelazifying() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return function_;
|
||||
}
|
||||
inline void setFunction(JSFunction *fun);
|
||||
/*
|
||||
* Takes a compilation lock and de-lazifies the canonical function. Must
|
||||
* be called before entering code that expects the function to be non-lazy.
|
||||
* De-lazifies the canonical function. Must be called before entering code
|
||||
* that expects the function to be non-lazy.
|
||||
*/
|
||||
inline void ensureNonLazyCanonicalFunction(JSContext *cx);
|
||||
|
||||
@ -1294,7 +1238,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
void setSourceObject(JSObject *object);
|
||||
JSObject *sourceObject() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return sourceObject_;
|
||||
}
|
||||
js::ScriptSource *scriptSource() const;
|
||||
@ -1335,7 +1278,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
JSObject *enclosingStaticScope() const {
|
||||
if (isCallsiteClone())
|
||||
return nullptr;
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return enclosingScopeOrOriginalFunction_;
|
||||
}
|
||||
|
||||
@ -1345,8 +1287,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
public:
|
||||
uint32_t getUseCount() const {
|
||||
// Note: We ignore races when reading the use count of a script off thread.
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return useCount;
|
||||
}
|
||||
uint32_t incUseCount(uint32_t amount = 1) { return useCount += amount; }
|
||||
@ -1381,7 +1321,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
jssrcnote *notes() { return (jssrcnote *)(code() + length()); }
|
||||
|
||||
bool hasArray(ArrayKind kind) {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return (hasArrayBits & (1 << kind));
|
||||
}
|
||||
void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); }
|
||||
@ -1405,31 +1344,26 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
js::ConstArray *consts() {
|
||||
JS_ASSERT(hasConsts());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::ConstArray *>(data + constsOffset());
|
||||
}
|
||||
|
||||
js::ObjectArray *objects() {
|
||||
JS_ASSERT(hasObjects());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::ObjectArray *>(data + objectsOffset());
|
||||
}
|
||||
|
||||
js::ObjectArray *regexps() {
|
||||
JS_ASSERT(hasRegexps());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::ObjectArray *>(data + regexpsOffset());
|
||||
}
|
||||
|
||||
js::TryNoteArray *trynotes() {
|
||||
JS_ASSERT(hasTrynotes());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset());
|
||||
}
|
||||
|
||||
js::BlockScopeArray *blockScopes() {
|
||||
JS_ASSERT(hasBlockScopes());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::BlockScopeArray *>(data + blockScopesOffset());
|
||||
}
|
||||
|
||||
@ -1438,7 +1372,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
size_t natoms() const { return natoms_; }
|
||||
|
||||
js::HeapPtrAtom &getAtom(size_t index) const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(index < natoms());
|
||||
return atoms[index];
|
||||
}
|
||||
@ -1795,7 +1728,6 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
|
||||
}
|
||||
|
||||
bool usesArgumentsAndApply() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return usesArgumentsAndApply_;
|
||||
}
|
||||
void setUsesArgumentsAndApply() {
|
||||
@ -1820,11 +1752,9 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
|
||||
return sourceObject()->source();
|
||||
}
|
||||
uint32_t begin() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return begin_;
|
||||
}
|
||||
uint32_t end() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return end_;
|
||||
}
|
||||
uint32_t lineno() const {
|
||||
|
@ -58,8 +58,6 @@ LazyScript::functionDelazifying(JSContext *cx) const
|
||||
inline JSFunction *
|
||||
JSScript::functionDelazifying() const
|
||||
{
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(js::CurrentThreadCanWriteCompilationData());
|
||||
if (function_ && function_->isInterpretedLazy()) {
|
||||
function_->setUnlazifiedScript(const_cast<JSScript *>(this));
|
||||
// If this script has a LazyScript, make sure the LazyScript has a
|
||||
@ -81,19 +79,15 @@ inline void
|
||||
JSScript::ensureNonLazyCanonicalFunction(JSContext *cx)
|
||||
{
|
||||
// Infallibly delazify the canonical script.
|
||||
if (function_ && function_->isInterpretedLazy()) {
|
||||
js::AutoLockForCompilation lock(cx);
|
||||
if (function_ && function_->isInterpretedLazy())
|
||||
functionDelazifying();
|
||||
}
|
||||
}
|
||||
|
||||
inline JSFunction *
|
||||
JSScript::getFunction(size_t index)
|
||||
{
|
||||
JSFunction *fun = &getObject(index)->as<JSFunction>();
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT_IF(fun->isNative(), IsAsmJSModuleNative(fun->native()));
|
||||
#endif
|
||||
return fun;
|
||||
}
|
||||
|
||||
@ -138,7 +132,6 @@ JSScript::global() const
|
||||
* A JSScript always marks its compartment's global (via bindings) so we
|
||||
* can assert that maybeGlobal is non-null here.
|
||||
*/
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return *compartment()->maybeGlobal();
|
||||
}
|
||||
|
||||
@ -149,14 +142,16 @@ JSScript::principals()
|
||||
}
|
||||
|
||||
inline JSFunction *
|
||||
JSScript::donorFunction() const {
|
||||
JSScript::donorFunction() const
|
||||
{
|
||||
if (!isCallsiteClone())
|
||||
return nullptr;
|
||||
return &enclosingScopeOrOriginalFunction_->as<JSFunction>();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::setIsCallsiteClone(JSObject *fun) {
|
||||
JSScript::setIsCallsiteClone(JSObject *fun)
|
||||
{
|
||||
JS_ASSERT(shouldCloneAtCallsite());
|
||||
shouldCloneAtCallsite_ = false;
|
||||
isCallsiteClone_ = true;
|
||||
@ -166,14 +161,12 @@ JSScript::setIsCallsiteClone(JSObject *fun) {
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript) {
|
||||
JSScript::setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript)
|
||||
{
|
||||
#ifdef JS_ION
|
||||
if (hasBaselineScript())
|
||||
js::jit::BaselineScript::writeBarrierPre(tenuredZone(), baseline);
|
||||
#endif
|
||||
mozilla::Maybe<js::AutoLockForCompilation> lock;
|
||||
if (maybecx)
|
||||
lock.construct(maybecx);
|
||||
baseline = baselineScript;
|
||||
updateBaselineOrIonRaw();
|
||||
}
|
||||
|
@ -4254,8 +4254,6 @@ js::CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *resul
|
||||
int32_t
|
||||
js::CompareAtoms(JSAtom *atom1, JSAtom *atom2)
|
||||
{
|
||||
AutoThreadSafeAccess ts0(atom1);
|
||||
AutoThreadSafeAccess ts1(atom2);
|
||||
return CompareChars(atom1->chars(), atom1->length(), atom2->chars(), atom2->length());
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,6 @@ js::StartOffThreadIonCompile(JSContext *cx, jit::IonBuilder *builder)
|
||||
if (!WorkerThreadState().ionWorklist().append(builder))
|
||||
return false;
|
||||
|
||||
cx->runtime()->addCompilationThread();
|
||||
|
||||
WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER);
|
||||
return true;
|
||||
}
|
||||
@ -649,8 +647,6 @@ GlobalWorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void
|
||||
JSObject *newProto = GetClassPrototypePure(&parseTask->scopeChain->global(), key);
|
||||
JS_ASSERT(newProto);
|
||||
|
||||
// Note: this is safe to do without requiring the compilation lock, as
|
||||
// the new type is not yet available to compilation threads.
|
||||
object->setProtoUnchecked(newProto);
|
||||
}
|
||||
|
||||
@ -791,11 +787,7 @@ WorkerThread::handleIonWorkload()
|
||||
jit::IonContext ictx(jit::CompileRuntime::get(rt),
|
||||
jit::CompileCompartment::get(ionBuilder->script()->compartment()),
|
||||
&ionBuilder->alloc());
|
||||
AutoEnterIonCompilation ionCompiling;
|
||||
bool succeeded = ionBuilder->build();
|
||||
ionBuilder->clearForBackEnd();
|
||||
if (succeeded)
|
||||
ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
|
||||
ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
|
||||
}
|
||||
|
||||
FinishOffThreadIonCompile(ionBuilder);
|
||||
|
@ -83,9 +83,6 @@ js::UncheckedUnwrap(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
while (true) {
|
||||
AutoThreadSafeAccess ts0(wrapped);
|
||||
AutoThreadSafeAccess ts1(wrapped->typeRaw());
|
||||
AutoThreadSafeAccess ts2(wrapped->lastProperty());
|
||||
if (!wrapped->is<WrapperObject>() ||
|
||||
MOZ_UNLIKELY(stopAtOuter && wrapped->getClass()->ext.innerObject))
|
||||
{
|
||||
|
@ -5511,9 +5511,6 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
|
||||
if (op->getBoolOption("ion-check-range-analysis"))
|
||||
jit::js_JitOptions.checkRangeAnalysis = true;
|
||||
|
||||
if (op->getBoolOption("ion-check-thread-safety"))
|
||||
jit::js_JitOptions.checkThreadSafety = true;
|
||||
|
||||
if (const char *str = op->getStringOption("ion-inlining")) {
|
||||
if (strcmp(str, "on") == 0)
|
||||
jit::js_JitOptions.disableInlining = false;
|
||||
@ -5788,8 +5785,6 @@ main(int argc, char **argv, char **envp)
|
||||
"Range analysis (default: on, off to disable)")
|
||||
|| !op.addBoolOption('\0', "ion-check-range-analysis",
|
||||
"Range analysis checking")
|
||||
|| !op.addBoolOption('\0', "ion-check-thread-safety",
|
||||
"IonBuilder thread safety checking")
|
||||
|| !op.addStringOption('\0', "ion-inlining", "on/off",
|
||||
"Inline methods where possible (default: on, off to disable)")
|
||||
|| !op.addStringOption('\0', "ion-osr", "on/off",
|
||||
@ -5898,15 +5893,8 @@ main(int argc, char **argv, char **envp)
|
||||
if (!JS_Init())
|
||||
return 1;
|
||||
|
||||
// When doing thread safety checks for VM accesses made during Ion compilation,
|
||||
// we rely on protected memory and only the main thread should be active.
|
||||
JSUseHelperThreads useHelperThreads =
|
||||
op.getBoolOption("ion-check-thread-safety")
|
||||
? JS_NO_HELPER_THREADS
|
||||
: JS_USE_HELPER_THREADS;
|
||||
|
||||
/* Use the same parameters as the browser in xpcjsruntime.cpp. */
|
||||
rt = JS_NewRuntime(32L * 1024L * 1024L, useHelperThreads);
|
||||
rt = JS_NewRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS);
|
||||
if (!rt)
|
||||
return 1;
|
||||
gTimeoutFunc = NullValue();
|
||||
|
@ -554,14 +554,14 @@ GlobalObject::getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global,
|
||||
{
|
||||
if (!global->getOrCreateObjectPrototype(cx))
|
||||
return false;
|
||||
eval.set(&global->getSlotForCompilation(EVAL).toObject());
|
||||
eval.set(&global->getSlot(EVAL).toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalObject::valueIsEval(Value val)
|
||||
{
|
||||
Value eval = getSlotForCompilation(EVAL);
|
||||
Value eval = getSlot(EVAL);
|
||||
return eval.isObject() && eval == val;
|
||||
}
|
||||
|
||||
@ -788,10 +788,6 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
|
||||
{
|
||||
RootedObject holder(cx, intrinsicsHolder());
|
||||
|
||||
// Work directly with the shape machinery underlying the object, so that we
|
||||
// don't take the compilation lock until we are ready to update the object
|
||||
// without triggering a GC.
|
||||
|
||||
uint32_t slot = holder->slotSpan();
|
||||
RootedShape last(cx, holder->lastProperty());
|
||||
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
|
||||
@ -801,7 +797,6 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
if (!JSObject::setLastProperty(cx, holder, shape))
|
||||
return false;
|
||||
|
||||
|
@ -158,7 +158,7 @@ class GlobalObject : public JSObject
|
||||
public:
|
||||
Value getConstructor(JSProtoKey key) const {
|
||||
JS_ASSERT(key <= JSProto_LIMIT);
|
||||
return getSlotForCompilation(APPLICATION_SLOTS + key);
|
||||
return getSlot(APPLICATION_SLOTS + key);
|
||||
}
|
||||
static bool ensureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
|
||||
static bool initConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
|
||||
@ -170,7 +170,7 @@ class GlobalObject : public JSObject
|
||||
|
||||
Value getPrototype(JSProtoKey key) const {
|
||||
JS_ASSERT(key <= JSProto_LIMIT);
|
||||
return getSlotForCompilation(APPLICATION_SLOTS + JSProto_LIMIT + key);
|
||||
return getSlot(APPLICATION_SLOTS + JSProto_LIMIT + key);
|
||||
}
|
||||
|
||||
void setPrototype(JSProtoKey key, const Value &value) {
|
||||
@ -457,19 +457,6 @@ class GlobalObject : public JSObject
|
||||
return &self->getSlot(slot).toObject();
|
||||
}
|
||||
|
||||
Value getSlotForCompilation(uint32_t slot) const {
|
||||
// This method should only be used for slots that are either eagerly
|
||||
// initialized on creation of the global or only change under the
|
||||
// compilation lock. Note that the dynamic slots pointer for global
|
||||
// objects can only change under the compilation lock.
|
||||
JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(getClass()));
|
||||
uint32_t fixed = numFixedSlotsForCompilation();
|
||||
AutoThreadSafeAccess ts(this);
|
||||
if (slot < fixed)
|
||||
return fixedSlots()[slot];
|
||||
return slots[slot - fixed];
|
||||
}
|
||||
|
||||
public:
|
||||
static JSObject *getOrCreateIteratorPrototype(JSContext *cx,
|
||||
Handle<GlobalObject*> global)
|
||||
@ -547,18 +534,13 @@ class GlobalObject : public JSObject
|
||||
}
|
||||
|
||||
JSObject *intrinsicsHolder() {
|
||||
JS_ASSERT(!getSlotForCompilation(INTRINSICS).isUndefined());
|
||||
return &getSlotForCompilation(INTRINSICS).toObject();
|
||||
JS_ASSERT(!getSlot(INTRINSICS).isUndefined());
|
||||
return &getSlot(INTRINSICS).toObject();
|
||||
}
|
||||
|
||||
bool maybeGetIntrinsicValue(jsid id, Value *vp) {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
JSObject *holder = intrinsicsHolder();
|
||||
|
||||
AutoThreadSafeAccess ts0(holder);
|
||||
AutoThreadSafeAccess ts1(holder->lastProperty());
|
||||
AutoThreadSafeAccess ts2(holder->lastProperty()->base());
|
||||
|
||||
if (Shape *shape = holder->nativeLookupPure(id)) {
|
||||
*vp = holder->getSlot(shape->slot());
|
||||
return true;
|
||||
@ -596,8 +578,7 @@ class GlobalObject : public JSObject
|
||||
unsigned nargs, MutableHandleValue funVal);
|
||||
|
||||
RegExpStatics *getRegExpStatics() const {
|
||||
JSObject &resObj = getSlotForCompilation(REGEXP_STATICS).toObject();
|
||||
AutoThreadSafeAccess ts(&resObj);
|
||||
JSObject &resObj = getSlot(REGEXP_STATICS).toObject();
|
||||
return static_cast<RegExpStatics *>(resObj.getPrivate(/* nfixed = */ 1));
|
||||
}
|
||||
|
||||
|
@ -1320,7 +1320,7 @@ SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, con
|
||||
if ((uint32_t)i >= length) {
|
||||
// Annotate script if provided with information (e.g. baseline)
|
||||
if (script && script->hasBaselineScript() && *pc == JSOP_SETELEM)
|
||||
script->baselineScript()->noteArrayWriteHole(cx, script->pcToOffset(pc));
|
||||
script->baselineScript()->noteArrayWriteHole(script->pcToOffset(pc));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -334,25 +334,6 @@ js::ObjectImpl::nativeLookupPure(jsid id)
|
||||
return Shape::searchNoHashify(lastProperty(), id);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
js::ObjectImpl::numFixedSlotsForCompilation() const
|
||||
{
|
||||
// This is an alternative method for getting the number of fixed slots
|
||||
// in an object. It requires more logic and memory accesses than
|
||||
// numFixedSlots() but is safe to be called from the compilation thread,
|
||||
// even if the main thread is actively mutating the VM.
|
||||
if (static_cast<const JSObject *>(this)->is<ArrayObject>())
|
||||
return 0;
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
// The compiler does not have access to nursery things, so if this object
|
||||
// is in the nursery we can fall back to numFixedSlots().
|
||||
if (IsInsideNursery(GetGCThingRuntime(this), this))
|
||||
return numFixedSlots();
|
||||
#endif
|
||||
gc::AllocKind kind = tenuredGetAllocKind();
|
||||
return gc::GetGCKindSlots(kind, getClass());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class *clasp)
|
||||
{
|
||||
|
@ -984,14 +984,12 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
|
||||
public:
|
||||
TaggedProto getTaggedProto() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->proto();
|
||||
}
|
||||
|
||||
bool hasTenuredProto() const;
|
||||
|
||||
const Class *getClass() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->clasp();
|
||||
}
|
||||
|
||||
@ -1206,8 +1204,6 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
}
|
||||
|
||||
types::TypeObject *typeRaw() const {
|
||||
AutoThreadSafeAccess ts0(this);
|
||||
AutoThreadSafeAccess ts1(type_);
|
||||
return type_;
|
||||
}
|
||||
|
||||
@ -1215,14 +1211,11 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
return reinterpret_cast<const shadow::Object *>(this)->numFixedSlots();
|
||||
}
|
||||
|
||||
uint32_t numFixedSlotsForCompilation() const;
|
||||
|
||||
/*
|
||||
* Whether this is the only object which has its specified type. This
|
||||
* object will have its type constructed lazily as needed by analysis.
|
||||
*/
|
||||
bool hasSingletonType() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return !!type_->singleton();
|
||||
}
|
||||
|
||||
@ -1231,7 +1224,6 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
* might have a lazy type, use getType() below, otherwise type().
|
||||
*/
|
||||
bool hasLazyType() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->lazy();
|
||||
}
|
||||
|
||||
@ -1391,7 +1383,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
}
|
||||
|
||||
const Value &getFixedSlot(uint32_t slot) const {
|
||||
MOZ_ASSERT(slot < numFixedSlotsForCompilation());
|
||||
MOZ_ASSERT(slot < numFixedSlots());
|
||||
return fixedSlots()[slot];
|
||||
}
|
||||
|
||||
@ -1478,7 +1470,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
* Private pointers are stored immediately after the last fixed slot of
|
||||
* the object.
|
||||
*/
|
||||
MOZ_ASSERT(nfixed == numFixedSlotsForCompilation());
|
||||
MOZ_ASSERT(nfixed == numFixedSlots());
|
||||
MOZ_ASSERT(hasPrivate());
|
||||
HeapSlot *end = &fixedSlots()[nfixed];
|
||||
return *reinterpret_cast<void**>(end);
|
||||
@ -1555,10 +1547,6 @@ MOZ_ALWAYS_INLINE Zone *
|
||||
BarrieredCell<ObjectImpl>::zoneFromAnyThread() const
|
||||
{
|
||||
const ObjectImpl* obj = static_cast<const ObjectImpl*>(this);
|
||||
|
||||
// Note: This read of obj->shape_ may race, though the zone fetched will be the same.
|
||||
AutoThreadSafeAccess ts(obj->shape_);
|
||||
|
||||
return obj->shape_->zoneFromAnyThread();
|
||||
}
|
||||
|
||||
|
@ -80,9 +80,6 @@ PerThreadData::PerThreadData(JSRuntime *runtime)
|
||||
#endif
|
||||
dtoaState(nullptr),
|
||||
suppressGC(0),
|
||||
#ifdef DEBUG
|
||||
ionCompiling(false),
|
||||
#endif
|
||||
activeCompilations(0)
|
||||
{}
|
||||
|
||||
@ -132,12 +129,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
exclusiveAccessOwner(nullptr),
|
||||
mainThreadHasExclusiveAccess(false),
|
||||
numExclusiveThreads(0),
|
||||
compilationLock(nullptr),
|
||||
#ifdef DEBUG
|
||||
compilationLockOwner(nullptr),
|
||||
mainThreadHasCompilationLock(false),
|
||||
#endif
|
||||
numCompilationThreads(0),
|
||||
#else
|
||||
operationCallbackLockTaken(false),
|
||||
#endif
|
||||
@ -280,7 +271,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
decimalSeparator(0),
|
||||
numGrouping(0),
|
||||
#endif
|
||||
heapProtected_(false),
|
||||
mathCache_(nullptr),
|
||||
activeCompilations_(0),
|
||||
keepAtoms_(0),
|
||||
@ -360,10 +350,6 @@ JSRuntime::init(uint32_t maxbytes)
|
||||
exclusiveAccessLock = PR_NewLock();
|
||||
if (!exclusiveAccessLock)
|
||||
return false;
|
||||
|
||||
compilationLock = PR_NewLock();
|
||||
if (!compilationLock)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!mainThread.init())
|
||||
@ -495,10 +481,6 @@ JSRuntime::~JSRuntime()
|
||||
JS_ASSERT(!numExclusiveThreads);
|
||||
mainThreadHasExclusiveAccess = true;
|
||||
|
||||
JS_ASSERT(!compilationLockOwner);
|
||||
if (compilationLock)
|
||||
PR_DestroyLock(compilationLock);
|
||||
|
||||
JS_ASSERT(!operationCallbackOwner);
|
||||
if (operationCallbackLock)
|
||||
PR_DestroyLock(operationCallbackLock);
|
||||
@ -859,76 +841,6 @@ JSRuntime::activeGCInAtomsZone()
|
||||
return zone->needsBarrier() || zone->isGCScheduled() || zone->wasGCStarted();
|
||||
}
|
||||
|
||||
#ifdef JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
|
||||
AutoProtectHeapForIonCompilation::AutoProtectHeapForIonCompilation(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
: runtime(rt)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
||||
JS_ASSERT(!runtime->heapProtected_);
|
||||
runtime->heapProtected_ = true;
|
||||
|
||||
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||
Chunk *chunk = r.front();
|
||||
// Note: Don't protect the last page in the chunk, which stores
|
||||
// immutable info and needs to be accessible for runtimeFromAnyThread()
|
||||
// in AutoThreadSafeAccess.
|
||||
if (mprotect(chunk, ChunkSize - sizeof(Arena), PROT_NONE))
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
AutoProtectHeapForIonCompilation::~AutoProtectHeapForIonCompilation()
|
||||
{
|
||||
JS_ASSERT(runtime->heapProtected_);
|
||||
JS_ASSERT(runtime->unprotectedArenas.empty());
|
||||
runtime->heapProtected_ = false;
|
||||
|
||||
for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||
Chunk *chunk = r.front();
|
||||
if (mprotect(chunk, ChunkSize - sizeof(Arena), PROT_READ | PROT_WRITE))
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
AutoThreadSafeAccess::AutoThreadSafeAccess(const Cell *cell MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
: runtime(cell->runtimeFromAnyThread()), arena(nullptr)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
||||
if (!runtime->heapProtected_)
|
||||
return;
|
||||
|
||||
ArenaHeader *base = cell->arenaHeader();
|
||||
for (size_t i = 0; i < runtime->unprotectedArenas.length(); i++) {
|
||||
if (base == runtime->unprotectedArenas[i])
|
||||
return;
|
||||
}
|
||||
|
||||
arena = base;
|
||||
|
||||
if (mprotect(arena, sizeof(Arena), PROT_READ | PROT_WRITE))
|
||||
MOZ_CRASH();
|
||||
|
||||
if (!runtime->unprotectedArenas.append(arena))
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
AutoThreadSafeAccess::~AutoThreadSafeAccess()
|
||||
{
|
||||
if (!arena)
|
||||
return;
|
||||
|
||||
if (mprotect(arena, sizeof(Arena), PROT_NONE))
|
||||
MOZ_CRASH();
|
||||
|
||||
JS_ASSERT(arena == runtime->unprotectedArenas.back());
|
||||
runtime->unprotectedArenas.popBack();
|
||||
}
|
||||
|
||||
#endif // JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
void
|
||||
@ -993,8 +905,6 @@ JSRuntime::assertCanLock(RuntimeLock which)
|
||||
JS_ASSERT(exclusiveAccessOwner != PR_GetCurrentThread());
|
||||
case WorkerThreadStateLock:
|
||||
JS_ASSERT(!WorkerThreadState().isLocked());
|
||||
case CompilationLock:
|
||||
JS_ASSERT(compilationLockOwner != PR_GetCurrentThread());
|
||||
case OperationCallbackLock:
|
||||
JS_ASSERT(!currentThreadOwnsOperationCallbackLock());
|
||||
case GCLock:
|
||||
@ -1006,64 +916,6 @@ JSRuntime::assertCanLock(RuntimeLock which)
|
||||
#endif // JS_THREADSAFE
|
||||
}
|
||||
|
||||
AutoEnterIonCompilation::AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = js::TlsPerThreadData.get();
|
||||
JS_ASSERT(!pt->ionCompiling);
|
||||
pt->ionCompiling = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
AutoEnterIonCompilation::~AutoEnterIonCompilation()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = js::TlsPerThreadData.get();
|
||||
JS_ASSERT(pt->ionCompiling);
|
||||
pt->ionCompiling = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
js::CurrentThreadCanWriteCompilationData()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
|
||||
// Data can only be read from during compilation.
|
||||
if (pt->ionCompiling)
|
||||
return false;
|
||||
|
||||
// Ignore what threads with exclusive contexts are doing; these never have
|
||||
// run scripts or have associated compilation threads.
|
||||
JSRuntime *rt = pt->runtimeIfOnOwnerThread();
|
||||
if (!rt)
|
||||
return true;
|
||||
|
||||
return rt->currentThreadHasCompilationLock();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
js::CurrentThreadCanReadCompilationData()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
|
||||
// Data can always be read from freely outside of compilation.
|
||||
if (!pt || !pt->ionCompiling)
|
||||
return true;
|
||||
|
||||
return pt->runtime_->currentThreadHasCompilationLock();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
js::AssertCurrentThreadCanLock(RuntimeLock which)
|
||||
{
|
||||
|
@ -483,7 +483,6 @@ AtomStateOffsetToName(const JSAtomState &atomState, size_t offset)
|
||||
enum RuntimeLock {
|
||||
ExclusiveAccessLock,
|
||||
WorkerThreadStateLock,
|
||||
CompilationLock,
|
||||
OperationCallbackLock,
|
||||
GCLock
|
||||
};
|
||||
@ -553,7 +552,6 @@ class PerThreadData : public PerThreadDataFriendFields
|
||||
friend class js::jit::JitActivation;
|
||||
friend class js::AsmJSActivation;
|
||||
#ifdef DEBUG
|
||||
friend bool js::CurrentThreadCanReadCompilationData();
|
||||
friend void js::AssertCurrentThreadCanLock(RuntimeLock which);
|
||||
#endif
|
||||
|
||||
@ -603,11 +601,6 @@ class PerThreadData : public PerThreadDataFriendFields
|
||||
*/
|
||||
int32_t suppressGC;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Whether this thread is actively Ion compiling.
|
||||
bool ionCompiling;
|
||||
#endif
|
||||
|
||||
// Number of active bytecode compilation on this thread.
|
||||
unsigned activeCompilations;
|
||||
|
||||
@ -658,8 +651,6 @@ class MarkingValidator;
|
||||
typedef Vector<JS::Zone *, 4, SystemAllocPolicy> ZoneVector;
|
||||
|
||||
class AutoLockForExclusiveAccess;
|
||||
class AutoLockForCompilation;
|
||||
class AutoProtectHeapForIonCompilation;
|
||||
|
||||
void RecomputeStackLimit(JSRuntime *rt, StackKind kind);
|
||||
|
||||
@ -774,28 +765,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
|
||||
friend class js::AutoLockForExclusiveAccess;
|
||||
|
||||
/*
|
||||
* Lock taken when using data that can be modified by the main thread but
|
||||
* read by Ion compilation threads. Any time either the main thread writes
|
||||
* such data or the compilation thread reads it, this lock must be taken.
|
||||
* Note that no externally visible data is modified by the compilation
|
||||
* thread, so the main thread never needs to take this lock when reading.
|
||||
*/
|
||||
PRLock *compilationLock;
|
||||
#ifdef DEBUG
|
||||
PRThread *compilationLockOwner;
|
||||
bool mainThreadHasCompilationLock;
|
||||
#endif
|
||||
|
||||
/* Number of in flight Ion compilations. */
|
||||
size_t numCompilationThreads;
|
||||
|
||||
friend class js::AutoLockForCompilation;
|
||||
#ifdef DEBUG
|
||||
friend bool js::CurrentThreadCanWriteCompilationData();
|
||||
friend bool js::CurrentThreadCanReadCompilationData();
|
||||
#endif
|
||||
|
||||
public:
|
||||
void setUsedByExclusiveThread(JS::Zone *zone);
|
||||
void clearUsedByExclusiveThread(JS::Zone *zone);
|
||||
@ -821,41 +790,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
#endif
|
||||
}
|
||||
|
||||
void addCompilationThread() {
|
||||
#ifdef JS_THREADSAFE
|
||||
numCompilationThreads++;
|
||||
#else
|
||||
MOZ_ASSUME_UNREACHABLE("No threads");
|
||||
#endif
|
||||
}
|
||||
void removeCompilationThread() {
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ASSERT(numCompilationThreads);
|
||||
numCompilationThreads--;
|
||||
#else
|
||||
MOZ_ASSUME_UNREACHABLE("No threads");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool compilationThreadsPresent() const {
|
||||
#ifdef JS_THREADSAFE
|
||||
return numCompilationThreads > 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool currentThreadHasCompilationLock() {
|
||||
#ifdef JS_THREADSAFE
|
||||
return (!numCompilationThreads && mainThreadHasCompilationLock) ||
|
||||
compilationLockOwner == PR_GetCurrentThread();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
/* Embedders can use this zone however they wish. */
|
||||
JS::Zone *systemZone;
|
||||
|
||||
@ -1474,18 +1408,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
const char *numGrouping;
|
||||
#endif
|
||||
|
||||
friend class js::AutoProtectHeapForIonCompilation;
|
||||
friend class js::AutoThreadSafeAccess;
|
||||
mozilla::DebugOnly<bool> heapProtected_;
|
||||
#ifdef DEBUG
|
||||
js::Vector<js::gc::ArenaHeader *, 0, js::SystemAllocPolicy> unprotectedArenas;
|
||||
|
||||
public:
|
||||
bool heapProtected() {
|
||||
return heapProtected_;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
js::MathCache *mathCache_;
|
||||
js::MathCache *createMathCache(JSContext *cx);
|
||||
@ -2083,43 +2005,6 @@ class RuntimeAllocPolicy
|
||||
|
||||
extern const JSSecurityCallbacks NullSecurityCallbacks;
|
||||
|
||||
// Debugging RAII class which marks the current thread as performing an Ion
|
||||
// compilation, for use by CurrentThreadCan{Read,Write}CompilationData
|
||||
class AutoEnterIonCompilation
|
||||
{
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
|
||||
~AutoEnterIonCompilation();
|
||||
#else
|
||||
AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
#endif
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
// Debugging RAII class which protects the entire GC heap for the duration of an
|
||||
// Ion compilation. When used only the main thread will be active and all
|
||||
// accesses to GC things must be wrapped by an AutoThreadSafeAccess instance.
|
||||
class AutoProtectHeapForIonCompilation
|
||||
{
|
||||
public:
|
||||
#ifdef JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
JSRuntime *runtime;
|
||||
|
||||
AutoProtectHeapForIonCompilation(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
~AutoProtectHeapForIonCompilation();
|
||||
#else
|
||||
AutoProtectHeapForIonCompilation(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
#endif
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -76,10 +76,8 @@ StaticScopeIter<allowGC>::scopeShape() const
|
||||
{
|
||||
JS_ASSERT(hasDynamicScopeObject());
|
||||
JS_ASSERT(type() != NAMED_LAMBDA);
|
||||
if (type() == BLOCK) {
|
||||
AutoThreadSafeAccess ts(&block());
|
||||
if (type() == BLOCK)
|
||||
return block().lastProperty();
|
||||
}
|
||||
return funScript()->callObjShape();
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,6 @@ class ScopeObject : public JSObject
|
||||
* enclosing scope of a ScopeObject is necessarily non-null.
|
||||
*/
|
||||
inline JSObject &enclosingScope() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return getFixedSlot(SCOPE_CHAIN_SLOT).toObject();
|
||||
}
|
||||
|
||||
@ -252,7 +251,6 @@ class CallObject : public ScopeObject
|
||||
|
||||
/* True if this is for a strict mode eval frame. */
|
||||
bool isForEval() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull());
|
||||
JS_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(),
|
||||
getFixedSlot(CALLEE_SLOT).toObject().is<JSFunction>());
|
||||
@ -264,7 +262,6 @@ class CallObject : public ScopeObject
|
||||
* only be called if !isForEval.)
|
||||
*/
|
||||
JSFunction &callee() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return getFixedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
|
||||
}
|
||||
|
||||
@ -410,7 +407,7 @@ class BlockObject : public NestedScopeObject
|
||||
|
||||
/* Return the number of variables associated with this block. */
|
||||
uint32_t slotCount() const {
|
||||
return propertyCountForCompilation();
|
||||
return propertyCount();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -464,9 +461,6 @@ class StaticBlockObject : public BlockObject
|
||||
* variable of the block isAliased.
|
||||
*/
|
||||
bool needsClone() {
|
||||
// The first variable slot will always indicate whether the object has
|
||||
// any aliased vars. Bypass slotValue() to allow testing this off thread.
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return !getFixedSlot(RESERVED_SLOTS).isFalse();
|
||||
}
|
||||
|
||||
|
@ -1026,13 +1026,11 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
|
||||
void popFront() {
|
||||
JS_ASSERT(!empty());
|
||||
AutoThreadSafeAccess ts(cursor);
|
||||
cursor = cursor->parent;
|
||||
}
|
||||
};
|
||||
|
||||
const Class *getObjectClass() const {
|
||||
AutoThreadSafeAccess ts(base());
|
||||
return base()->clasp;
|
||||
}
|
||||
JSObject *getObjectParent() const { return base()->parent; }
|
||||
@ -1092,7 +1090,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
};
|
||||
|
||||
bool inDictionary() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (flags & IN_DICTIONARY) != 0;
|
||||
}
|
||||
unsigned getFlags() const { return flags & PUBLIC_FLAGS; }
|
||||
@ -1158,20 +1155,14 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
BaseShape *base() const { return base_.get(); }
|
||||
|
||||
bool hasSlot() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (attrs & JSPROP_SHARED) == 0;
|
||||
}
|
||||
uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); }
|
||||
uint32_t maybeSlot() const {
|
||||
// Note: Reading a shape's slot off thread can race against main thread
|
||||
// updates to the number of linear searches on the shape, which is
|
||||
// stored in the same slotInfo field. We tolerate this.
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return slotInfo & SLOT_MASK;
|
||||
}
|
||||
|
||||
bool isEmptyShape() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT_IF(JSID_IS_EMPTY(propid_), hasMissingSlot());
|
||||
return JSID_IS_EMPTY(propid_);
|
||||
}
|
||||
@ -1193,8 +1184,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
}
|
||||
|
||||
uint32_t numFixedSlots() const {
|
||||
// Note: The same race applies here as in maybeSlot().
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (slotInfo >> FIXED_SLOTS_SHIFT);
|
||||
}
|
||||
|
||||
@ -1216,7 +1205,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
}
|
||||
|
||||
const EncapsulatedId &propid() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(!isEmptyShape());
|
||||
JS_ASSERT(!JSID_IS_VOID(propid_));
|
||||
return propid_;
|
||||
@ -1224,7 +1212,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
EncapsulatedId &propidRef() { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
|
||||
jsid propidRaw() const {
|
||||
// Return the actual jsid, not an internal reference.
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return propid();
|
||||
}
|
||||
|
||||
@ -1241,8 +1228,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
bool configurable() const { return (attrs & JSPROP_PERMANENT) == 0; }
|
||||
bool enumerable() const { return (attrs & JSPROP_ENUMERATE) != 0; }
|
||||
bool writable() const {
|
||||
// JS_ASSERT(isDataDescriptor());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (attrs & JSPROP_READONLY) == 0;
|
||||
}
|
||||
bool hasGetterValue() const { return attrs & JSPROP_GETTER; }
|
||||
@ -1279,10 +1264,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
uint32_t entryCount() {
|
||||
if (hasTable())
|
||||
return table().entryCount;
|
||||
return entryCountForCompilation();
|
||||
}
|
||||
|
||||
uint32_t entryCountForCompilation() {
|
||||
uint32_t count = 0;
|
||||
for (Shape::Range<NoGC> r(this); !r.empty(); r.popFront())
|
||||
++count;
|
||||
@ -1649,7 +1630,6 @@ Shape::searchLinear(jsid id)
|
||||
JS_ASSERT(!inDictionary());
|
||||
|
||||
for (Shape *shape = this; shape; ) {
|
||||
AutoThreadSafeAccess ts(shape);
|
||||
if (shape->propidRef() == id)
|
||||
return shape;
|
||||
shape = shape->parent;
|
||||
|
@ -382,7 +382,6 @@ class JSString : public js::gc::BarrieredCell<JSString>
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
JSAtom &asAtom() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isAtom());
|
||||
return *(JSAtom *)this;
|
||||
}
|
||||
@ -1015,7 +1014,6 @@ JSString::base() const
|
||||
inline js::PropertyName *
|
||||
JSAtom::asPropertyName()
|
||||
{
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
#ifdef DEBUG
|
||||
uint32_t dummy;
|
||||
JS_ASSERT(!isIndex(&dummy));
|
||||
|
@ -1195,8 +1195,6 @@ TypedArrayObject::isArrayIndex(jsid id, uint32_t *ip)
|
||||
void
|
||||
TypedArrayObject::neuter(JSContext *cx)
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
|
||||
setSlot(LENGTH_SLOT, Int32Value(0));
|
||||
setSlot(BYTELENGTH_SLOT, Int32Value(0));
|
||||
setSlot(BYTEOFFSET_SLOT, Int32Value(0));
|
||||
|
@ -311,11 +311,9 @@ class TypedArrayObject : public ArrayBufferViewObject
|
||||
return tarr->getFixedSlot(BYTEOFFSET_SLOT);
|
||||
}
|
||||
static Value byteLengthValue(TypedArrayObject *tarr) {
|
||||
AutoThreadSafeAccess ts(tarr);
|
||||
return tarr->getFixedSlot(BYTELENGTH_SLOT);
|
||||
}
|
||||
static Value lengthValue(TypedArrayObject *tarr) {
|
||||
AutoThreadSafeAccess ts(tarr);
|
||||
return tarr->getFixedSlot(LENGTH_SLOT);
|
||||
}
|
||||
|
||||
@ -333,11 +331,9 @@ class TypedArrayObject : public ArrayBufferViewObject
|
||||
}
|
||||
|
||||
uint32_t type() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return getFixedSlot(TYPE_SLOT).toInt32();
|
||||
}
|
||||
void *viewData() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return static_cast<void*>(getPrivate(DATA_SLOT));
|
||||
}
|
||||
|
||||
|
@ -177,8 +177,10 @@ CacheFile::~CacheFile()
|
||||
LOG(("CacheFile::~CacheFile() [this=%p]", this));
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
if (!mMemoryOnly)
|
||||
if (!mMemoryOnly && mReady) {
|
||||
// mReady flag indicates we have metadata plus in a valid state.
|
||||
WriteMetadataIfNeededLocked(true);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1335,6 +1337,11 @@ CacheFile::WriteMetadataIfNeededLocked(bool aFireAndForget)
|
||||
AssertOwnsLock();
|
||||
MOZ_ASSERT(!mMemoryOnly);
|
||||
|
||||
if (!mMetadata) {
|
||||
MOZ_CRASH("Must have metadata here");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aFireAndForget) {
|
||||
// if aFireAndForget is set, we are called from dtor. Write
|
||||
// scheduler hard-refers CacheFile otherwise, so we cannot be here.
|
||||
|
@ -916,7 +916,12 @@ CacheFileIOManager::OnProfile()
|
||||
{
|
||||
LOG(("CacheFileIOManager::OnProfile() [gInstance=%p]", gInstance));
|
||||
|
||||
MOZ_ASSERT(gInstance);
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
if (!ioMan) {
|
||||
// CacheFileIOManager::Init() failed, probably could not create the IO
|
||||
// thread, just go with it...
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
@ -941,10 +946,10 @@ CacheFileIOManager::OnProfile()
|
||||
}
|
||||
|
||||
if (directory) {
|
||||
rv = directory->Clone(getter_AddRefs(gInstance->mCacheDirectory));
|
||||
rv = directory->Clone(getter_AddRefs(ioMan->mCacheDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = gInstance->mCacheDirectory->Append(NS_LITERAL_STRING("cache2"));
|
||||
rv = ioMan->mCacheDirectory->Append(NS_LITERAL_STRING("cache2"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,10 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
|
||||
EXPORT_LIBRARY = True
|
||||
FORCE_STATIC_LIB = True
|
||||
|
||||
DIRS += ['win/src/sandboxbroker']
|
||||
DIRS += [
|
||||
'win/src/sandboxbroker',
|
||||
'win/src/sandboxtarget',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'chromium/base/at_exit.cc',
|
||||
|
@ -23,16 +23,26 @@ SandboxBroker::SandboxBroker()
|
||||
sBrokerService = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// We'll start to increase the restrictions over time.
|
||||
mPolicy = sBrokerService->CreatePolicy();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SandboxBroker::AllowPipe(const wchar_t *aPath)
|
||||
{
|
||||
return mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
|
||||
sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, aPath);
|
||||
}
|
||||
|
||||
bool
|
||||
SandboxBroker::LaunchApp(const wchar_t *aPath,
|
||||
const wchar_t *aArguments,
|
||||
void **aProcessHandle)
|
||||
{
|
||||
// If the broker service isn't already initialized, do it now
|
||||
if (!sBrokerService) {
|
||||
if (!sBrokerService || !mPolicy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -40,16 +50,15 @@ SandboxBroker::LaunchApp(const wchar_t *aPath,
|
||||
// Medium integrity, unrestricted, in the same window station, within the
|
||||
// same desktop, and has no job object.
|
||||
// We'll start to increase the restrictions over time.
|
||||
sandbox::TargetPolicy *policy = sBrokerService->CreatePolicy();
|
||||
policy->SetJobLevel(sandbox::JOB_NONE, 0);
|
||||
policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
||||
sandbox::USER_RESTRICTED_SAME_ACCESS);
|
||||
policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_MEDIUM);
|
||||
mPolicy->SetJobLevel(sandbox::JOB_NONE, 0);
|
||||
mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
||||
sandbox::USER_RESTRICTED_SAME_ACCESS);
|
||||
mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
|
||||
|
||||
// Ceate the sandboxed process
|
||||
PROCESS_INFORMATION targetInfo;
|
||||
sandbox::ResultCode result;
|
||||
result = sBrokerService->SpawnTarget(aPath, aArguments, policy, &targetInfo);
|
||||
result = sBrokerService->SpawnTarget(aPath, aArguments, mPolicy, &targetInfo);
|
||||
|
||||
// The sandboxed process is started in a suspended state, resumeit now that
|
||||
// we'eve set things up.
|
||||
@ -59,13 +68,15 @@ SandboxBroker::LaunchApp(const wchar_t *aPath,
|
||||
// Return the process handle to the caller
|
||||
*aProcessHandle = targetInfo.hProcess;
|
||||
|
||||
policy->Release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SandboxBroker::~SandboxBroker()
|
||||
{
|
||||
if (mPolicy) {
|
||||
mPolicy->Release();
|
||||
mPolicy = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
namespace sandbox {
|
||||
class BrokerServices;
|
||||
class TargetPolicy;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
@ -23,12 +24,14 @@ class SANDBOX_EXPORT SandboxBroker
|
||||
{
|
||||
public:
|
||||
SandboxBroker();
|
||||
bool AllowPipe(const wchar_t *aPath);
|
||||
bool LaunchApp(const wchar_t *aPath, const wchar_t *aArguments,
|
||||
void **aProcessHandle);
|
||||
virtual ~SandboxBroker();
|
||||
|
||||
private:
|
||||
static sandbox::BrokerServices *sBrokerService;
|
||||
sandbox::TargetPolicy *mPolicy;
|
||||
};
|
||||
|
||||
} // mozilla
|
||||
|
9
security/sandbox/win/src/sandboxtarget/moz.build
Normal file
9
security/sandbox/win/src/sandboxtarget/moz.build
Normal file
@ -0,0 +1,9 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'sandboxTarget.h',
|
||||
]
|
65
security/sandbox/win/src/sandboxtarget/sandboxTarget.h
Normal file
65
security/sandbox/win/src/sandboxtarget/sandboxTarget.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __SECURITY_SANDBOX_SANDBOXTARGET_H__
|
||||
#define __SECURITY_SANDBOX_SANDBOXTARGET_H__
|
||||
|
||||
#ifdef TARGET_SANDBOX_EXPORTS
|
||||
#define TARGET_SANDBOX_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define TARGET_SANDBOX_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
namespace mozilla {
|
||||
|
||||
|
||||
class TARGET_SANDBOX_EXPORT SandboxTarget
|
||||
{
|
||||
public:
|
||||
typedef void (*StartSandboxPtr)();
|
||||
|
||||
/**
|
||||
* Obtains a pointer to the singleton instance
|
||||
*/
|
||||
static SandboxTarget* Instance()
|
||||
{
|
||||
static SandboxTarget sb;
|
||||
return &sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the application that will lower the sandbox token
|
||||
*
|
||||
* @param aStartSandboxCallback A callback function which will lower privs
|
||||
*/
|
||||
void SetStartSandboxCallback(StartSandboxPtr aStartSandboxCallback)
|
||||
{
|
||||
mStartSandboxCallback = aStartSandboxCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the library that wants to start the sandbox, which in turn
|
||||
* calls into the previously set StartSandboxCallback.
|
||||
*/
|
||||
void StartSandbox()
|
||||
{
|
||||
if (mStartSandboxCallback) {
|
||||
mStartSandboxCallback();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
SandboxTarget() :
|
||||
mStartSandboxCallback(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
StartSandboxPtr mStartSandboxCallback;
|
||||
};
|
||||
|
||||
|
||||
} // mozilla
|
||||
|
||||
#endif
|
@ -99,10 +99,11 @@ this.BookmarkJSONUtils = Object.freeze({
|
||||
Components.utils.reportError("Unable to report telemetry.");
|
||||
}
|
||||
|
||||
// Write to the temp folder first, to avoid leaving back partial files.
|
||||
let tmpPath = OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
OS.Path.basename(aFilePath) + ".tmp");
|
||||
yield OS.File.writeAtomic(aFilePath, jsonString, { tmpPath: tmpPath });
|
||||
// Do not write to the tmp folder, otherwise if it has a different
|
||||
// filesystem writeAtomic will fail. Eventual dangling .tmp files should
|
||||
// be cleaned up by the caller.
|
||||
yield OS.File.writeAtomic(aFilePath, jsonString,
|
||||
{ tmpPath: OS.Path.join(aFilePath + ".tmp") });
|
||||
return count;
|
||||
});
|
||||
},
|
||||
|
@ -132,6 +132,13 @@ this.PlacesBackups = {
|
||||
let backupFolderPath = yield this.getBackupFolder();
|
||||
let iterator = new OS.File.DirectoryIterator(backupFolderPath);
|
||||
yield iterator.forEach(function(aEntry) {
|
||||
// Since this is a lazy getter and OS.File I/O is serialized, we can
|
||||
// safely remove .tmp files without risking to remove ongoing backups.
|
||||
if (aEntry.name.endsWith(".tmp")) {
|
||||
OS.File.remove(aEntry.path);
|
||||
return;
|
||||
}
|
||||
|
||||
let matches = aEntry.name.match(this._filenamesRegex);
|
||||
if (matches) {
|
||||
// Remove bogus backups in future dates.
|
||||
|
Loading…
Reference in New Issue
Block a user