Merge m-c to fx-team.

This commit is contained in:
Ryan VanderMeulen 2014-02-14 15:33:13 -05:00
commit 0b9003439b
68 changed files with 373 additions and 1135 deletions

View File

@ -79,6 +79,9 @@ TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
if (mOffsetAcc) { if (mOffsetAcc) {
offsetNode = mOffsetAcc->GetContent(); offsetNode = mOffsetAcc->GetContent();
offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode); offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
NS_ASSERTION(offsetElm, "No element for offset accessible!");
if (!offsetElm)
return;
frame = offsetElm->GetPrimaryFrame(); frame = offsetElm->GetPrimaryFrame();
} }

View File

@ -30,9 +30,16 @@
#include "mozilla/layers/PCompositorChild.h" #include "mozilla/layers/PCompositorChild.h"
#include "mozilla/net/NeckoChild.h" #include "mozilla/net/NeckoChild.h"
#include "mozilla/Preferences.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" #include "mozilla/Sandbox.h"
#endif #endif
#endif
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "nsIConsoleListener.h" #include "nsIConsoleListener.h"
@ -593,12 +600,17 @@ ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
aPrivs; aPrivs;
// If this fails, we die. // If this fails, we die.
SetCurrentProcessPrivileges(privs); 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 // SetCurrentProcessSandbox should be moved close to process initialization
// time if/when possible. SetCurrentProcessPrivileges should probably be // time if/when possible. SetCurrentProcessPrivileges should probably be
// moved as well. Right now this is set ONLY if we receive the // moved as well. Right now this is set ONLY if we receive the
// RecvSetProcessPrivileges message. See bug 880808. // RecvSetProcessPrivileges message. See bug 880808.
SetCurrentProcessSandbox(); SetCurrentProcessSandbox();
#endif
#endif #endif
return true; return true;
} }

View File

@ -25,6 +25,7 @@
#include "sandbox/chromium/base/basictypes.h" #include "sandbox/chromium/base/basictypes.h"
#include "sandbox/win/src/sandbox.h" #include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h" #include "sandbox/win/src/sandbox_factory.h"
#include "mozilla/sandboxTarget.h"
#endif #endif
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
@ -67,14 +68,27 @@ InitializeBinder(void *aDummy) {
} }
#endif #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 int
main(int argc, char* argv[]) main(int argc, char* argv[])
{ {
bool isNuwa = false; bool isNuwa = false;
bool isSandboxEnabled = false;
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
isNuwa |= strcmp(argv[i], "-nuwa") == 0; 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 #ifdef MOZ_NUWA_PROCESS
@ -100,24 +114,6 @@ main(int argc, char* argv[])
#endif #endif
#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 // 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. // forward here. We expect the last arg to be the child process type.
if (argc < 1) if (argc < 1)
@ -132,6 +128,22 @@ main(int argc, char* argv[])
mozilla::SanitizeEnvironmentVariables(); mozilla::SanitizeEnvironmentVariables();
SetDllDirectory(L""); 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 #endif
nsresult rv = XRE_InitChildProcess(argc, argv, proctype); nsresult rv = XRE_InitChildProcess(argc, argv, proctype);

View File

@ -21,3 +21,11 @@ LOCAL_INCLUDES += [
'/toolkit/xre', '/toolkit/xre',
'/xpcom/base', '/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',
]

View File

@ -826,7 +826,6 @@ StructTypeRepresentation::fieldNamed(jsid id) const
uint32_t unused; uint32_t unused;
JSAtom *atom = JSID_TO_ATOM(id); JSAtom *atom = JSID_TO_ATOM(id);
AutoThreadSafeAccess ts(atom);
if (atom->isIndex(&unused)) if (atom->isIndex(&unused))
return nullptr; return nullptr;

View File

@ -2865,12 +2865,10 @@ frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNo
RootedFunction fun(cx, bce->script->functionNonDelazifying()); RootedFunction fun(cx, bce->script->functionNonDelazifying());
JS_ASSERT(fun->isInterpreted()); JS_ASSERT(fun->isInterpreted());
if (fun->isInterpretedLazy()) { if (fun->isInterpretedLazy())
AutoLockForCompilation lock(cx);
fun->setUnlazifiedScript(bce->script); fun->setUnlazifiedScript(bce->script);
} else { else
fun->setScript(bce->script); fun->setScript(bce->script);
}
bce->tellDebuggerAboutCompiledScript(cx); bce->tellDebuggerAboutCompiledScript(cx);

View File

@ -191,9 +191,6 @@ class BarrieredCell : public gc::Cell
static MOZ_ALWAYS_INLINE void readBarrier(T *thing) { static MOZ_ALWAYS_INLINE void readBarrier(T *thing) {
#ifdef JSGC_INCREMENTAL #ifdef JSGC_INCREMENTAL
// Off thread Ion compilation never occurs when barriers are active.
js::AutoThreadSafeAccess ts(thing);
JS::shadow::Zone *shadowZone = thing->shadowZoneFromAnyThread(); JS::shadow::Zone *shadowZone = thing->shadowZoneFromAnyThread();
if (shadowZone->needsBarrier()) { if (shadowZone->needsBarrier()) {
MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone)); MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone));

View File

@ -1109,37 +1109,9 @@ InFreeList(ArenaHeader *aheader, void *thing)
} /* namespace gc */ } /* 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::AllocKind
gc::Cell::tenuredGetAllocKind() const gc::Cell::tenuredGetAllocKind() const
{ {
AutoThreadSafeAccess ts(this);
return arenaHeader()->getAllocKind(); return arenaHeader()->getAllocKind();
} }

View File

@ -136,10 +136,7 @@ ICStubIterator::unlink(JSContext *cx)
JS_ASSERT(currentStub_ != fallbackStub_); JS_ASSERT(currentStub_ != fallbackStub_);
JS_ASSERT(!unlinked_); JS_ASSERT(!unlinked_);
{ fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
AutoLockForCompilation lock(cx);
fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
}
// Mark the current iterator position as unlinked, so operator++ works properly. // Mark the current iterator position as unlinked, so operator++ works properly.
unlinked_ = true; unlinked_ = true;
@ -1066,7 +1063,7 @@ DoProfilerFallback(JSContext *cx, BaselineFrame *frame, ICProfiler_Fallback *stu
ICStub *optStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *optStub = compiler.getStub(compiler.getStubSpace(script));
if (!optStub) if (!optStub)
return false; return false;
stub->addNewStub(cx, optStub); stub->addNewStub(optStub);
return true; return true;
} }
@ -1797,7 +1794,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!int32Stub) if (!int32Stub)
return false; return false;
stub->addNewStub(cx, int32Stub); stub->addNewStub(int32Stub);
return true; return true;
} }
@ -1815,7 +1812,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!doubleStub) if (!doubleStub)
return false; return false;
stub->addNewStub(cx, doubleStub); stub->addNewStub(doubleStub);
return true; return true;
} }
@ -1830,7 +1827,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!doubleStub) if (!doubleStub)
return false; return false;
stub->addNewStub(cx, doubleStub); stub->addNewStub(doubleStub);
return true; return true;
} }
@ -1841,7 +1838,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!booleanStub) if (!booleanStub)
return false; return false;
stub->addNewStub(cx, booleanStub); stub->addNewStub(booleanStub);
return true; return true;
} }
@ -1854,7 +1851,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!optStub) if (!optStub)
return false; return false;
stub->addNewStub(cx, optStub); stub->addNewStub(optStub);
return true; return true;
} }
@ -1866,7 +1863,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!stringStub) if (!stringStub)
return false; return false;
stub->addNewStub(cx, stringStub); stub->addNewStub(stringStub);
return true; return true;
} }
@ -1878,7 +1875,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!objectStub) if (!objectStub)
return false; return false;
stub->addNewStub(cx, objectStub); stub->addNewStub(objectStub);
return true; return true;
} }
@ -1896,7 +1893,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
if (!objectStub) if (!objectStub)
return false; return false;
stub->addNewStub(cx, objectStub); stub->addNewStub(objectStub);
return true; return true;
} }
} }
@ -2207,7 +2204,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
if (!int32Stub) if (!int32Stub)
return false; return false;
stub->addNewStub(cx, int32Stub); stub->addNewStub(int32Stub);
return true; return true;
} }
@ -2218,7 +2215,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
if (!doubleStub) if (!doubleStub)
return false; return false;
stub->addNewStub(cx, doubleStub); stub->addNewStub(doubleStub);
return true; return true;
} }
@ -2229,7 +2226,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
if (!stringStub) if (!stringStub)
return false; return false;
stub->addNewStub(cx, stringStub); stub->addNewStub(stringStub);
return true; return true;
} }
@ -2239,7 +2236,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
if (!nilStub) if (!nilStub)
return false; return false;
stub->addNewStub(cx, nilStub); stub->addNewStub(nilStub);
return true; return true;
} }
@ -2250,7 +2247,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
if (!objStub) if (!objStub)
return false; return false;
stub->addNewStub(cx, objStub); stub->addNewStub(objStub);
return true; return true;
} }
@ -2542,11 +2539,11 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
} }
if (ret.isDouble()) if (ret.isDouble())
stub->setSawDoubleResult(cx); stub->setSawDoubleResult();
// Check to see if a new stub should be generated. // Check to see if a new stub should be generated.
if (stub->numOptimizedStubs() >= ICBinaryArith_Fallback::MAX_OPTIMIZED_STUBS) { if (stub->numOptimizedStubs() >= ICBinaryArith_Fallback::MAX_OPTIMIZED_STUBS) {
stub->noteUnoptimizableOperands(cx); stub->noteUnoptimizableOperands();
return true; return true;
} }
@ -2559,7 +2556,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script));
if (!strcatStub) if (!strcatStub)
return false; return false;
stub->addNewStub(cx, strcatStub); stub->addNewStub(strcatStub);
return true; return true;
} }
@ -2572,7 +2569,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script));
if (!strcatStub) if (!strcatStub)
return false; return false;
stub->addNewStub(cx, strcatStub); stub->addNewStub(strcatStub);
return true; return true;
} }
} }
@ -2588,13 +2585,13 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
ICStub *arithStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *arithStub = compiler.getStub(compiler.getStubSpace(script));
if (!arithStub) if (!arithStub)
return false; return false;
stub->addNewStub(cx, arithStub); stub->addNewStub(arithStub);
return true; return true;
} }
// Handle only int32 or double. // Handle only int32 or double.
if (!lhs.isNumber() || !rhs.isNumber()) { if (!lhs.isNumber() || !rhs.isNumber()) {
stub->noteUnoptimizableOperands(cx); stub->noteUnoptimizableOperands();
return true; return true;
} }
@ -2618,7 +2615,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
if (!doubleStub) if (!doubleStub)
return false; return false;
stub->addNewStub(cx, doubleStub); stub->addNewStub(doubleStub);
return true; return true;
} }
default: default:
@ -2636,7 +2633,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
ICStub *int32Stub = compilerInt32.getStub(compilerInt32.getStubSpace(script)); ICStub *int32Stub = compilerInt32.getStub(compilerInt32.getStubSpace(script));
if (!int32Stub) if (!int32Stub)
return false; return false;
stub->addNewStub(cx, int32Stub); stub->addNewStub(int32Stub);
return true; return true;
} }
@ -2655,7 +2652,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
ICStub *optStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *optStub = compiler.getStub(compiler.getStubSpace(script));
if (!optStub) if (!optStub)
return false; return false;
stub->addNewStub(cx, optStub); stub->addNewStub(optStub);
return true; return true;
} }
default: default:
@ -2663,7 +2660,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
} }
} }
stub->noteUnoptimizableOperands(cx); stub->noteUnoptimizableOperands();
return true; return true;
} }
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -3058,7 +3055,7 @@ DoUnaryArithFallback(JSContext *cx, BaselineFrame *frame, ICUnaryArith_Fallback
ICStub *int32Stub = compiler.getStub(compiler.getStubSpace(script)); ICStub *int32Stub = compiler.getStub(compiler.getStubSpace(script));
if (!int32Stub) if (!int32Stub)
return false; return false;
stub->addNewStub(cx, int32Stub); stub->addNewStub(int32Stub);
return true; return true;
} }
@ -3072,7 +3069,7 @@ DoUnaryArithFallback(JSContext *cx, BaselineFrame *frame, ICUnaryArith_Fallback
ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
if (!doubleStub) if (!doubleStub)
return false; return false;
stub->addNewStub(cx, doubleStub); stub->addNewStub(doubleStub);
return true; return true;
} }
@ -3757,7 +3754,7 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -3809,7 +3806,7 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -3843,7 +3840,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
if (!stringStub) if (!stringStub)
return false; return false;
stub->addNewStub(cx, stringStub); stub->addNewStub(stringStub);
return true; return true;
} }
@ -3861,7 +3858,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
if (!argsStub) if (!argsStub)
return false; return false;
stub->addNewStub(cx, argsStub); stub->addNewStub(argsStub);
return true; return true;
} }
@ -3883,7 +3880,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
if (!argsStub) if (!argsStub)
return false; return false;
stub->addNewStub(cx, argsStub); stub->addNewStub(argsStub);
return true; return true;
} }
} }
@ -3898,7 +3895,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
if (!denseStub) if (!denseStub)
return false; return false;
stub->addNewStub(cx, denseStub); stub->addNewStub(denseStub);
return true; return true;
} }
@ -3934,7 +3931,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
if (!typedArrayStub) if (!typedArrayStub)
return false; return false;
stub->addNewStub(cx, typedArrayStub); stub->addNewStub(typedArrayStub);
return true; 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 // be cached by either Baseline or Ion. Indicate this in the cache so that
// Ion does not generate a cache for this op. // Ion does not generate a cache for this op.
if (!obj->isNative() && !obj->is<TypedArrayObject>()) if (!obj->isNative() && !obj->is<TypedArrayObject>())
stub->noteNonNativeAccess(cx); stub->noteNonNativeAccess();
// GetElem operations which could access negative indexes generally can't // GetElem operations which could access negative indexes generally can't
// be optimized without the potential for bailouts, as we can't statically // be optimized without the potential for bailouts, as we can't statically
// determine that an object has no properties on such indexes. // determine that an object has no properties on such indexes.
if (rhs.isNumber() && rhs.toNumber() < 0) if (rhs.isNumber() && rhs.toNumber() < 0)
stub->noteNegativeIndex(cx); stub->noteNegativeIndex();
return true; return true;
} }
@ -5014,7 +5011,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
if (!denseStub->addUpdateStubForValue(cx, script, obj, JSID_VOIDHANDLE, rhs)) if (!denseStub->addUpdateStubForValue(cx, script, obj, JSID_VOIDHANDLE, rhs))
return false; return false;
stub->addNewStub(cx, denseStub); stub->addNewStub(denseStub);
} else if (!addingCase && } else if (!addingCase &&
!DenseSetElemStubExists(cx, ICStub::SetElem_Dense, stub, obj)) !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)) if (!denseStub->addUpdateStubForValue(cx, script, obj, JSID_VOIDHANDLE, rhs))
return false; return false;
stub->addNewStub(cx, denseStub); stub->addNewStub(denseStub);
} }
} }
@ -5061,7 +5058,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
if (!typedArrayStub) if (!typedArrayStub)
return false; return false;
stub->addNewStub(cx, typedArrayStub); stub->addNewStub(typedArrayStub);
return true; return true;
} }
} }
@ -5111,13 +5108,13 @@ ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
} }
void void
BaselineScript::noteArrayWriteHole(JSContext *cx, uint32_t pcOffset) BaselineScript::noteArrayWriteHole(uint32_t pcOffset)
{ {
ICEntry &entry = icEntryFromPCOffset(pcOffset); ICEntry &entry = icEntryFromPCOffset(pcOffset);
ICFallbackStub *stub = entry.fallbackStub(); ICFallbackStub *stub = entry.fallbackStub();
if (stub->isSetElem_Fallback()) 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) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -5729,7 +5726,7 @@ TryAttachScopeNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *s
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -5936,7 +5933,7 @@ DoGetIntrinsicFallback(JSContext *cx, BaselineFrame *frame, ICGetIntrinsic_Fallb
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -5984,7 +5981,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
return false; return false;
*attached = true; *attached = true;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -5996,7 +5993,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
return false; return false;
*attached = true; *attached = true;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -6013,7 +6010,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
return false; return false;
*attached = true; *attached = true;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
if (obj->is<TypedArrayObject>()) { if (obj->is<TypedArrayObject>()) {
@ -6025,7 +6022,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
return false; return false;
*attached = true; *attached = true;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -6041,7 +6038,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
return false; return false;
*attached = true; *attached = true;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -6124,7 +6121,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -6155,7 +6152,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -6202,7 +6199,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
} }
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -6222,7 +6219,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script)); ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -6277,7 +6274,7 @@ TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -6364,7 +6361,7 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
} }
JS_ASSERT(!attached); JS_ASSERT(!attached);
stub->noteUnoptimizableAccess(cx); stub->noteUnoptimizableAccess();
return true; return true;
} }
@ -7109,13 +7106,13 @@ ICGetProp_ArgumentsLength::Compiler::generateStubCode(MacroAssembler &masm)
} }
void void
BaselineScript::noteAccessedGetter(JSContext *cx, uint32_t pcOffset) BaselineScript::noteAccessedGetter(uint32_t pcOffset)
{ {
ICEntry &entry = icEntryFromPCOffset(pcOffset); ICEntry &entry = icEntryFromPCOffset(pcOffset);
ICFallbackStub *stub = entry.fallbackStub(); ICFallbackStub *stub = entry.fallbackStub();
if (stub->isGetProp_Fallback()) 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)) if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -7174,7 +7171,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs)) if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -7196,7 +7193,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -7215,7 +7212,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
*attached = true; *attached = true;
return true; return true;
} }
@ -7290,7 +7287,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub,
return true; return true;
JS_ASSERT(!attached); JS_ASSERT(!attached);
stub->noteUnoptimizableAccess(cx); stub->noteUnoptimizableAccess();
return true; return true;
} }
@ -7796,7 +7793,7 @@ TryAttachFunApplyStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script,
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -7813,7 +7810,7 @@ TryAttachFunApplyStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script,
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
} }
@ -7957,7 +7954,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
stub->unlinkStubsWithKind(cx, ICStub::Call_Scripted); stub->unlinkStubsWithKind(cx, ICStub::Call_Scripted);
// Add new generalized stub. // Add new generalized stub.
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -7986,7 +7983,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -8023,7 +8020,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
return true; return true;
} }
@ -9155,7 +9152,7 @@ DoIteratorMoreFallback(JSContext *cx, BaselineFrame *frame, ICIteratorMore_Fallb
ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script())); ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script()));
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
} }
return true; return true;
@ -9229,7 +9226,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb
return false; return false;
if (!res.isString() && !stub->hasNonStringResult()) if (!res.isString() && !stub->hasNonStringResult())
stub->setHasNonStringResult(cx); stub->setHasNonStringResult();
if (iteratorObject->is<PropertyIteratorObject>() && if (iteratorObject->is<PropertyIteratorObject>() &&
!stub->hasStub(ICStub::IteratorNext_Native)) !stub->hasStub(ICStub::IteratorNext_Native))
@ -9238,7 +9235,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb
ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script())); ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script()));
if (!newStub) if (!newStub)
return false; return false;
stub->addNewStub(cx, newStub); stub->addNewStub(newStub);
} }
return true; return true;
@ -9402,7 +9399,7 @@ DoTypeOfFallback(JSContext *cx, BaselineFrame *frame, ICTypeOf_Fallback *stub, H
ICStub *typeOfStub = compiler.getStub(compiler.getStubSpace(frame->script())); ICStub *typeOfStub = compiler.getStub(compiler.getStubSpace(frame->script()));
if (!typeOfStub) if (!typeOfStub)
return false; return false;
stub->addNewStub(cx, typeOfStub); stub->addNewStub(typeOfStub);
} }
return true; return true;
@ -9489,7 +9486,7 @@ DoRetSubFallback(JSContext *cx, BaselineFrame *frame, ICRetSub_Fallback *stub,
if (!optStub) if (!optStub)
return false; return false;
stub->addNewStub(cx, optStub); stub->addNewStub(optStub);
return true; return true;
} }

View File

@ -835,8 +835,7 @@ class ICFallbackStub : public ICStub
} }
// Add a new stub to the IC chain terminated by this fallback stub. // Add a new stub to the IC chain terminated by this fallback stub.
void addNewStub(JSContext *cx, ICStub *stub) { void addNewStub(ICStub *stub) {
AutoLockForCompilation lock(cx);
JS_ASSERT(*lastStubPtrAddr_ == this); JS_ASSERT(*lastStubPtrAddr_ == this);
JS_ASSERT(stub->next() == nullptr); JS_ASSERT(stub->next() == nullptr);
stub->setNext(this); stub->setNext(this);
@ -2442,15 +2441,13 @@ class ICBinaryArith_Fallback : public ICFallbackStub
bool sawDoubleResult() const { bool sawDoubleResult() const {
return extra_ & SAW_DOUBLE_RESULT_BIT; return extra_ & SAW_DOUBLE_RESULT_BIT;
} }
void setSawDoubleResult(JSContext *cx) { void setSawDoubleResult() {
AutoLockForCompilation lock(cx);
extra_ |= SAW_DOUBLE_RESULT_BIT; extra_ |= SAW_DOUBLE_RESULT_BIT;
} }
bool hadUnoptimizableOperands() const { bool hadUnoptimizableOperands() const {
return extra_ & UNOPTIMIZABLE_OPERANDS_BIT; return extra_ & UNOPTIMIZABLE_OPERANDS_BIT;
} }
void noteUnoptimizableOperands(JSContext *cx) { void noteUnoptimizableOperands() {
AutoLockForCompilation lock(cx);
extra_ |= UNOPTIMIZABLE_OPERANDS_BIT; extra_ |= UNOPTIMIZABLE_OPERANDS_BIT;
} }
@ -2851,16 +2848,14 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub
return space->allocate<ICGetElem_Fallback>(code); return space->allocate<ICGetElem_Fallback>(code);
} }
void noteNonNativeAccess(JSContext *cx) { void noteNonNativeAccess() {
AutoLockForCompilation lock(cx);
extra_ |= EXTRA_NON_NATIVE; extra_ |= EXTRA_NON_NATIVE;
} }
bool hasNonNativeAccess() const { bool hasNonNativeAccess() const {
return extra_ & EXTRA_NON_NATIVE; return extra_ & EXTRA_NON_NATIVE;
} }
void noteNegativeIndex(JSContext *cx) { void noteNegativeIndex() {
AutoLockForCompilation lock(cx);
extra_ |= EXTRA_NEGATIVE_INDEX; extra_ |= EXTRA_NEGATIVE_INDEX;
} }
bool hasNegativeIndex() const { bool hasNegativeIndex() const {
@ -3448,8 +3443,7 @@ class ICSetElem_Fallback : public ICFallbackStub
return space->allocate<ICSetElem_Fallback>(code); return space->allocate<ICSetElem_Fallback>(code);
} }
void noteArrayWriteHole(JSContext *cx) { void noteArrayWriteHole() {
AutoLockForCompilation lock(cx);
extra_ = 1; extra_ = 1;
} }
bool hasArrayWriteHole() const { bool hasArrayWriteHole() const {
@ -4024,16 +4018,14 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub
static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0; static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
static const size_t ACCESSED_GETTER_BIT = 1; static const size_t ACCESSED_GETTER_BIT = 1;
void noteUnoptimizableAccess(JSContext *cx) { void noteUnoptimizableAccess() {
AutoLockForCompilation lock(cx);
extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT); extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
} }
bool hadUnoptimizableAccess() const { bool hadUnoptimizableAccess() const {
return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT); return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
} }
void noteAccessedGetter(JSContext *cx) { void noteAccessedGetter() {
AutoLockForCompilation lock(cx);
extra_ |= (1u << ACCESSED_GETTER_BIT); extra_ |= (1u << ACCESSED_GETTER_BIT);
} }
bool hasAccessedGetter() const { bool hasAccessedGetter() const {
@ -4840,8 +4832,7 @@ class ICSetProp_Fallback : public ICFallbackStub
} }
static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0; static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
void noteUnoptimizableAccess(JSContext *cx) { void noteUnoptimizableAccess() {
AutoLockForCompilation lock(cx);
extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT); extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
} }
bool hadUnoptimizableAccess() const { bool hadUnoptimizableAccess() const {
@ -5742,8 +5733,7 @@ class ICIteratorNext_Fallback : public ICFallbackStub
return space->allocate<ICIteratorNext_Fallback>(code); return space->allocate<ICIteratorNext_Fallback>(code);
} }
void setHasNonStringResult(JSContext *cx) { void setHasNonStringResult() {
AutoLockForCompilation lock(cx);
JS_ASSERT(extra_ == 0); JS_ASSERT(extra_ == 0);
extra_ = 1; extra_ = 1;
} }

View File

@ -18,8 +18,6 @@ using mozilla::DebugOnly;
bool bool
SetElemICInspector::sawOOBDenseWrite() const SetElemICInspector::sawOOBDenseWrite() const
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!icEntry_) if (!icEntry_)
return false; return false;
@ -40,8 +38,6 @@ SetElemICInspector::sawOOBDenseWrite() const
bool bool
SetElemICInspector::sawOOBTypedArrayWrite() const SetElemICInspector::sawOOBTypedArrayWrite() const
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!icEntry_) if (!icEntry_)
return false; return false;
@ -58,8 +54,6 @@ SetElemICInspector::sawOOBTypedArrayWrite() const
bool bool
SetElemICInspector::sawDenseWrite() const SetElemICInspector::sawDenseWrite() const
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!icEntry_) if (!icEntry_)
return false; return false;
@ -74,8 +68,6 @@ SetElemICInspector::sawDenseWrite() const
bool bool
SetElemICInspector::sawTypedArrayWrite() const SetElemICInspector::sawTypedArrayWrite() const
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!icEntry_) if (!icEntry_)
return false; return false;
@ -90,8 +82,6 @@ SetElemICInspector::sawTypedArrayWrite() const
bool bool
BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes) BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
// Return a list of shapes seen by the baseline IC for the current op. // 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 // An empty list indicates no shapes are known, or there was an uncacheable
// access. // access.
@ -149,8 +139,6 @@ BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes)
ICStub * ICStub *
BaselineInspector::monomorphicStub(jsbytecode *pc) BaselineInspector::monomorphicStub(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return nullptr; return nullptr;
@ -168,8 +156,6 @@ BaselineInspector::monomorphicStub(jsbytecode *pc)
bool bool
BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **psecond) BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **psecond)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return false; return false;
@ -190,8 +176,6 @@ BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **pseco
MIRType MIRType
BaselineInspector::expectedResultType(jsbytecode *pc) BaselineInspector::expectedResultType(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
// Look at the IC entries for this op to guess what type it will produce, // Look at the IC entries for this op to guess what type it will produce,
// returning MIRType_None otherwise. // returning MIRType_None otherwise.
@ -238,8 +222,6 @@ CanUseInt32Compare(ICStub::Kind kind)
MCompare::CompareType MCompare::CompareType
BaselineInspector::expectedCompareType(jsbytecode *pc) BaselineInspector::expectedCompareType(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
ICStub *first = monomorphicStub(pc), *second = nullptr; ICStub *first = monomorphicStub(pc), *second = nullptr;
if (!first && !dimorphicStub(pc, &first, &second)) if (!first && !dimorphicStub(pc, &first, &second))
return MCompare::Compare_Unknown; return MCompare::Compare_Unknown;
@ -322,8 +304,6 @@ TryToSpecializeBinaryArithOp(ICStub **stubs,
MIRType MIRType
BaselineInspector::expectedBinaryArithSpecialization(jsbytecode *pc) BaselineInspector::expectedBinaryArithSpecialization(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
MIRType result; MIRType result;
ICStub *stubs[2]; ICStub *stubs[2];
@ -352,8 +332,6 @@ BaselineInspector::expectedBinaryArithSpecialization(jsbytecode *pc)
bool bool
BaselineInspector::hasSeenNonNativeGetElement(jsbytecode *pc) BaselineInspector::hasSeenNonNativeGetElement(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return false; return false;
@ -368,8 +346,6 @@ BaselineInspector::hasSeenNonNativeGetElement(jsbytecode *pc)
bool bool
BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode *pc) BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return false; return false;
@ -384,8 +360,6 @@ BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode *pc)
bool bool
BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc) BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return false; return false;
@ -400,8 +374,6 @@ BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc)
bool bool
BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc) BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
JS_ASSERT(JSOp(*pc) == JSOP_ITERNEXT); JS_ASSERT(JSOp(*pc) == JSOP_ITERNEXT);
if (!hasBaselineScript()) if (!hasBaselineScript())
@ -416,8 +388,6 @@ BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc)
bool bool
BaselineInspector::hasSeenDoubleResult(jsbytecode *pc) BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return false; return false;
@ -437,8 +407,6 @@ BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
JSObject * JSObject *
BaselineInspector::getTemplateObject(jsbytecode *pc) BaselineInspector::getTemplateObject(jsbytecode *pc)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return nullptr; return nullptr;
@ -466,8 +434,6 @@ BaselineInspector::getTemplateObject(jsbytecode *pc)
JSObject * JSObject *
BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native) BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
if (!hasBaselineScript()) if (!hasBaselineScript())
return nullptr; return nullptr;
@ -501,8 +467,6 @@ BaselineInspector::templateCallObject()
JSObject * JSObject *
BaselineInspector::commonGetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonGetter) BaselineInspector::commonGetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonGetter)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
const ICEntry &entry = icEntryFromPC(pc); const ICEntry &entry = icEntryFromPC(pc);
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) { for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
if (stub->isGetProp_CallScripted() || stub->isGetProp_CallNative()) { if (stub->isGetProp_CallScripted() || stub->isGetProp_CallNative()) {
@ -518,8 +482,6 @@ BaselineInspector::commonGetPropFunction(jsbytecode *pc, Shape **lastProperty, J
JSObject * JSObject *
BaselineInspector::commonSetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonSetter) BaselineInspector::commonSetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonSetter)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
const ICEntry &entry = icEntryFromPC(pc); const ICEntry &entry = icEntryFromPC(pc);
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) { for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) { if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {

View File

@ -294,8 +294,8 @@ struct BaselineScript
void toggleSPS(bool enable); void toggleSPS(bool enable);
void noteAccessedGetter(JSContext *cx, uint32_t pcOffset); void noteAccessedGetter(uint32_t pcOffset);
void noteArrayWriteHole(JSContext *cx, uint32_t pcOffset); void noteArrayWriteHole(uint32_t pcOffset);
static size_t offsetOfFlags() { static size_t offsetOfFlags() {
return offsetof(BaselineScript, flags_); return offsetof(BaselineScript, flags_);

View File

@ -3568,7 +3568,6 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
Register obj = ToRegister(lir->output()); Register obj = ToRegister(lir->output());
JSObject *templateObj = lir->mir()->templateObject(); JSObject *templateObj = lir->mir()->templateObject();
AutoThreadSafeAccess ts(templateObj);
// If we have a template object, we can inline call object creation. // If we have a template object, we can inline call object creation.
OutOfLineCode *ool; OutOfLineCode *ool;

View File

@ -252,15 +252,6 @@ CompileCompartment::setSingletonsAsValues()
return JS::CompartmentOptionsRef(compartment()).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() JitCompileOptions::JitCompileOptions()
: cloneSingletons_(false), : cloneSingletons_(false),
spsSlowAssertionsEnabled_(false) spsSlowAssertionsEnabled_(false)

View File

@ -102,8 +102,6 @@ class CompileCompartment
{ {
JSCompartment *compartment(); JSCompartment *compartment();
friend class js::AutoLockForCompilation;
public: public:
static CompileCompartment *get(JSCompartment *comp); static CompileCompartment *get(JSCompartment *comp);

View File

@ -52,7 +52,6 @@
using namespace js; using namespace js;
using namespace js::jit; using namespace js::jit;
using mozilla::Maybe;
using mozilla::ThreadLocal; using mozilla::ThreadLocal;
// Assert that JitCode is gc::Cell aligned. // Assert that JitCode is gc::Cell aligned.
@ -492,8 +491,6 @@ JitCompartment::ensureIonStubsExist(JSContext *cx)
void void
jit::FinishOffThreadBuilder(IonBuilder *builder) jit::FinishOffThreadBuilder(IonBuilder *builder)
{ {
builder->script()->runtimeFromMainThread()->removeCompilationThread();
ExecutionMode executionMode = builder->info().executionMode(); ExecutionMode executionMode = builder->info().executionMode();
// Clear the recompiling flag if it would have failed. // Clear the recompiling flag if it would have failed.
@ -1565,9 +1562,6 @@ AttachFinishedCompilations(JSContext *cx)
// operation callback and can't propagate failures. // operation callback and can't propagate failures.
cx->clearPendingException(); cx->clearPendingException();
} }
} else {
if (builder->abortReason() == AbortReason_Disable)
SetIonScript(builder->script(), builder->info().executionMode(), ION_DISABLED_SCRIPT);
} }
FinishOffThreadBuilder(builder); FinishOffThreadBuilder(builder);
@ -1722,6 +1716,14 @@ IonCompile(JSContext *cx, JSScript *script,
builderScript->ionScript()->setRecompiling(); 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 possible, compile the script off thread.
if (OffThreadCompilationAvailable(cx)) { if (OffThreadCompilationAvailable(cx)) {
if (!recompile) if (!recompile)
@ -1742,42 +1744,12 @@ IonCompile(JSContext *cx, JSScript *script,
return AbortReason_NoAbort; 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)); ScopedJSDeletePtr<CodeGenerator> codegen(CompileBackEnd(builder));
if (!codegen) { if (!codegen) {
IonSpew(IonSpew_Abort, "Failed during back-end compilation."); IonSpew(IonSpew_Abort, "Failed during back-end compilation.");
return AbortReason_Disable; return AbortReason_Disable;
} }
if (!protect.empty())
protect.destroy();
if (!ionCompiling.empty())
ionCompiling.destroy();
bool success = codegen->link(cx, builder->constraints()); bool success = codegen->link(cx, builder->constraints());
IonSpewEndFunction(); IonSpewEndFunction();

View File

@ -140,21 +140,13 @@ IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
script_ = info->script(); script_ = info->script();
pc = info->startPC(); pc = info->startPC();
#ifdef DEBUG
lock();
JS_ASSERT(script()->hasBaselineScript()); JS_ASSERT(script()->hasBaselineScript());
unlock();
#endif
JS_ASSERT(!!analysisContext == (info->executionMode() == DefinitePropertiesAnalysis)); JS_ASSERT(!!analysisContext == (info->executionMode() == DefinitePropertiesAnalysis));
} }
void void
IonBuilder::clearForBackEnd() IonBuilder::clearForBackEnd()
{ {
// This case should only be hit if there was a failure while building.
if (!lock_.empty())
lock_.destroy();
JS_ASSERT(!analysisContext); JS_ASSERT(!analysisContext);
baselineFrame_ = nullptr; baselineFrame_ = nullptr;
@ -292,8 +284,6 @@ IonBuilder::getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constr
fun = &obj->as<JSFunction>(); fun = &obj->as<JSFunction>();
} else { } else {
types::TypeObject *typeObj = calleeTypes->getTypeObject(i); types::TypeObject *typeObj = calleeTypes->getTypeObject(i);
AutoThreadSafeAccess ts(typeObj);
JS_ASSERT(typeObj); JS_ASSERT(typeObj);
if (!typeObj->interpretedFunction) { if (!typeObj->interpretedFunction) {
targets.clear(); targets.clear();
@ -593,16 +583,12 @@ IonBuilder::pushLoop(CFGState::State initial, jsbytecode *stopAt, MBasicBlock *e
bool bool
IonBuilder::init() IonBuilder::init()
{ {
lock();
if (!types::TypeScript::FreezeTypeSets(constraints(), script(), if (!types::TypeScript::FreezeTypeSets(constraints(), script(),
&thisTypes, &argTypes, &typeArray)) &thisTypes, &argTypes, &typeArray))
{ {
return false; return false;
} }
unlock();
if (!analysis().init(alloc(), gsn)) if (!analysis().init(alloc(), gsn))
return false; return false;
@ -721,8 +707,6 @@ IonBuilder::build()
if (!traverseBytecode()) if (!traverseBytecode())
return false; return false;
unlock();
if (!maybeAddOsrTypeBarriers()) if (!maybeAddOsrTypeBarriers())
return false; return false;
@ -882,7 +866,6 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
if (!traverseBytecode()) if (!traverseBytecode())
return false; return false;
unlock();
return true; return true;
} }
@ -937,9 +920,6 @@ IonBuilder::initParameters()
// interpreter and didn't accumulate type information, try to use that OSR // interpreter and didn't accumulate type information, try to use that OSR
// frame to determine possible initial types for 'this' and parameters. // frame to determine possible initial types for 'this' and parameters.
// For unknownProperties() tests under addType.
lock();
if (thisTypes->empty() && baselineFrame_) { if (thisTypes->empty() && baselineFrame_) {
if (!thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc())) if (!thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc()))
return false; return false;
@ -963,8 +943,6 @@ IonBuilder::initParameters()
current->initSlot(info().argSlotUnchecked(i), param); current->initSlot(info().argSlotUnchecked(i), param);
} }
unlock();
return true; return true;
} }
@ -987,8 +965,6 @@ IonBuilder::initScopeChain(MDefinition *callee)
if (!script()->compileAndGo()) if (!script()->compileAndGo())
return abort("non-CNG global scripts are not supported"); return abort("non-CNG global scripts are not supported");
lock();
if (JSFunction *fun = info().funMaybeLazy()) { if (JSFunction *fun = info().funMaybeLazy()) {
if (!callee) { if (!callee) {
MCallee *calleeIns = MCallee::New(alloc()); MCallee *calleeIns = MCallee::New(alloc());
@ -1014,8 +990,6 @@ IonBuilder::initScopeChain(MDefinition *callee)
scope = constant(ObjectValue(script()->global())); scope = constant(ObjectValue(script()->global()));
} }
unlock();
current->setScopeChain(scope); current->setScopeChain(scope);
return true; return true;
} }
@ -1209,14 +1183,6 @@ IonBuilder::maybeAddOsrTypeBarriers()
bool bool
IonBuilder::traverseBytecode() 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 (;;) { for (;;) {
JS_ASSERT(pc < info().limitPC()); JS_ASSERT(pc < info().limitPC());
@ -1291,12 +1257,6 @@ IonBuilder::traverseBytecode()
if (!inspectOpcode(op)) if (!inspectOpcode(op))
return false; return false;
if (++lockOpcodeCount == LOCK_OPCODE_GRANULARITY) {
unlock();
lock();
lockOpcodeCount = 0;
}
#ifdef DEBUG #ifdef DEBUG
for (size_t i = 0; i < popped.length(); i++) { for (size_t i = 0; i < popped.length(); i++) {
switch (op) { switch (op) {
@ -3881,21 +3841,17 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
JSScript *calleeScript = target->nonLazyScript(); JSScript *calleeScript = target->nonLazyScript();
BaselineInspector inspector(calleeScript); BaselineInspector inspector(calleeScript);
// Improve type information of |this| when not set.
if (callInfo.constructing() &&
!callInfo.thisArg()->resultTypeSet() &&
calleeScript->types)
{ {
AutoThreadSafeAccess ts(calleeScript); types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
if (!types->unknown()) {
// Improve type information of |this| when not set. MTypeBarrier *barrier =
if (callInfo.constructing() && MTypeBarrier::New(alloc(), callInfo.thisArg(), types->clone(alloc_->lifoAlloc()));
!callInfo.thisArg()->resultTypeSet() && current->add(barrier);
calleeScript->types) 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()); MIRGraphReturns returns(alloc());
AutoAccumulateReturns aar(graph(), returns); AutoAccumulateReturns aar(graph(), returns);
unlock();
// Build the graph. // Build the graph.
IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(), IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
&inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1, &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 // Inlining the callee failed. Mark the callee as uninlineable only if
// the inlining was aborted for a non-exception reason. // the inlining was aborted for a non-exception reason.
if (inlineBuilder.abortReason_ == AbortReason_Disable) { if (inlineBuilder.abortReason_ == AbortReason_Disable) {
AutoThreadSafeAccess ts(calleeScript);
calleeScript->setUninlineable(); calleeScript->setUninlineable();
abortReason_ = AbortReason_Inlining; abortReason_ = AbortReason_Inlining;
} else if (inlineBuilder.abortReason_ == AbortReason_Inlining) { } else if (inlineBuilder.abortReason_ == AbortReason_Inlining) {
@ -3937,8 +3890,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
return false; return false;
} }
lock();
// Create return block. // Create return block.
jsbytecode *postCall = GetNextPc(pc); jsbytecode *postCall = GetNextPc(pc);
MBasicBlock *returnBlock = newBlock(nullptr, postCall); MBasicBlock *returnBlock = newBlock(nullptr, postCall);
@ -3957,7 +3908,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
// Accumulate return values. // Accumulate return values.
if (returns.empty()) { if (returns.empty()) {
// Inlining of functions that have no exit is not supported. // Inlining of functions that have no exit is not supported.
AutoThreadSafeAccess ts(calleeScript);
calleeScript->setUninlineable(); calleeScript->setUninlineable();
abortReason_ = AbortReason_Inlining; abortReason_ = AbortReason_Inlining;
return false; return false;
@ -4618,7 +4568,6 @@ IonBuilder::createDeclEnvObject(MDefinition *callee, MDefinition *scope)
// Get a template CallObject that we'll use to generate inline object // Get a template CallObject that we'll use to generate inline object
// creation. // creation.
DeclEnvObject *templateObj = inspector->templateDeclEnvObject(); DeclEnvObject *templateObj = inspector->templateDeclEnvObject();
AutoThreadSafeAccess ts(templateObj);
// One field is added to the function to handle its name. This cannot be a // 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. // 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 // Get a template CallObject that we'll use to generate inline object
// creation. // creation.
CallObject *templateObj = inspector->templateCallObject(); CallObject *templateObj = inspector->templateCallObject();
AutoThreadSafeAccess ts(templateObj);
// If the CallObject needs dynamic slots, allocate those now. // If the CallObject needs dynamic slots, allocate those now.
MInstruction *slots; MInstruction *slots;
if (templateObj->hasDynamicSlots()) { if (templateObj->hasDynamicSlots()) {
size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlotsForCompilation(), size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlots(),
templateObj->lastProperty()->slotSpan(templateObj->getClass()), templateObj->lastProperty()->slotSpan(templateObj->getClass()),
templateObj->getClass()); templateObj->getClass());
slots = MNewSlots::New(alloc(), nslots); slots = MNewSlots::New(alloc(), nslots);
@ -4677,8 +4625,8 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
unsigned slot = i.scopeSlot(); unsigned slot = i.scopeSlot();
unsigned formal = i.frameIndex(); unsigned formal = i.frameIndex();
MDefinition *param = current->getSlot(info().argSlotUnchecked(formal)); MDefinition *param = current->getSlot(info().argSlotUnchecked(formal));
if (slot >= templateObj->numFixedSlotsForCompilation()) if (slot >= templateObj->numFixedSlots())
current->add(MStoreSlot::New(alloc(), slots, slot - templateObj->numFixedSlotsForCompilation(), param)); current->add(MStoreSlot::New(alloc(), slots, slot - templateObj->numFixedSlots(), param));
else else
current->add(MStoreFixedSlot::New(alloc(), callObj, slot, param)); current->add(MStoreFixedSlot::New(alloc(), callObj, slot, param));
} }
@ -4750,13 +4698,10 @@ IonBuilder::createThisScriptedSingleton(JSFunction *target, MDefinition *callee)
if (!templateObject->hasTenuredProto() || templateObject->getProto() != proto) if (!templateObject->hasTenuredProto() || templateObject->getProto() != proto)
return nullptr; return nullptr;
{ if (!target->nonLazyScript()->types)
AutoThreadSafeAccess ts(target->nonLazyScript()); return nullptr;
if (!target->nonLazyScript()->types) if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(templateObject)))
return nullptr; return nullptr;
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(templateObject)))
return nullptr;
}
// For template objects with NewScript info, the appropriate allocation // For template objects with NewScript info, the appropriate allocation
// kind to use may change due to dynamic property adds. In these cases // 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(); JSScript *targetScript = target->nonLazyScript();
AutoThreadSafeAccess ts(targetScript);
if (!targetScript->types) if (!targetScript->types)
return true; return true;
@ -5357,7 +5300,6 @@ IonBuilder::jsop_eval(uint32_t argc)
string->getOperand(1)->toConstant()->value().isString()) string->getOperand(1)->toConstant()->value().isString())
{ {
JSAtom *atom = &string->getOperand(1)->toConstant()->value().toString()->asAtom(); JSAtom *atom = &string->getOperand(1)->toConstant()->value().toString()->asAtom();
AutoThreadSafeAccess ts(atom);
if (StringEqualsAscii(atom, "()")) { if (StringEqualsAscii(atom, "()")) {
MDefinition *name = string->getOperand(0); MDefinition *name = string->getOperand(0);
@ -5431,7 +5373,6 @@ IonBuilder::jsop_newarray(uint32_t count)
types::TemporaryTypeSet::DoubleConversion conversion = types::TemporaryTypeSet::DoubleConversion conversion =
ins->resultTypeSet()->convertDoubleElements(constraints()); ins->resultTypeSet()->convertDoubleElements(constraints());
AutoThreadSafeAccess ts(templateObject);
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles) if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
templateObject->setShouldConvertDoubleElements(); templateObject->setShouldConvertDoubleElements();
else else
@ -5514,7 +5455,6 @@ IonBuilder::jsop_initelem_array()
current->add(elements); current->add(elements);
JSObject *templateObject = obj->toNewArray()->templateObject(); JSObject *templateObject = obj->toNewArray()->templateObject();
AutoThreadSafeAccess ts(templateObject);
if (templateObject->shouldConvertDoubleElements()) { if (templateObject->shouldConvertDoubleElements()) {
MInstruction *valueDouble = MToDouble::New(alloc(), value); MInstruction *valueDouble = MToDouble::New(alloc(), value);
@ -5556,7 +5496,6 @@ IonBuilder::jsop_initprop(PropertyName *name)
MDefinition *obj = current->peek(-1); MDefinition *obj = current->peek(-1);
JSObject *templateObject = obj->toNewObject()->templateObject(); JSObject *templateObject = obj->toNewObject()->templateObject();
AutoThreadSafeAccess ts(templateObject);
Shape *shape = templateObject->lastProperty()->searchLinear(NameToId(name)); 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 // then check if this regex object only flows into known natives and can
// avoid cloning in this case. // avoid cloning in this case.
// RegExpObjects embedded in scripts are immutable.
AutoThreadSafeAccess ts(reobj);
bool mustClone = true; bool mustClone = true;
types::TypeObjectKey *typeObj = types::TypeObjectKey::get(&script()->global()); types::TypeObjectKey *typeObj = types::TypeObjectKey::get(&script()->global());
if (!typeObj->hasFlags(constraints(), types::OBJECT_FLAG_REGEXP_FLAGS_SET)) { if (!typeObj->hasFlags(constraints(), types::OBJECT_FLAG_REGEXP_FLAGS_SET)) {

View File

@ -787,17 +787,6 @@ class IonBuilder : public MIRGenerator
// Constraints for recording dependencies on type information. // Constraints for recording dependencies on type information.
types::CompilerConstraintList *constraints_; 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. // Basic analysis information about the script.
BytecodeAnalysis analysis_; BytecodeAnalysis analysis_;
BytecodeAnalysis &analysis() { BytecodeAnalysis &analysis() {

View File

@ -82,7 +82,6 @@ class JitCode : public gc::BarrieredCell<JitCode>
public: public:
uint8_t *raw() const { uint8_t *raw() const {
AutoThreadSafeAccess ts(this);
return code_; return code_;
} }
size_t instructionsSize() const { size_t instructionsSize() const {

View File

@ -787,10 +787,6 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
{ {
// Fast initialization of an empty object returned by NewGCThing(). // 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()); JS_ASSERT(!templateObject->hasDynamicElements());
storePtr(ImmGCPtr(templateObject->lastProperty()), Address(obj, JSObject::offsetOfShape())); 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. // Fixed slots of non-array objects are required to be initialized.
// Use the values currently in the template object. // 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())); templateObject->lastProperty()->slotSpan(templateObject->getClass()));
for (unsigned i = 0; i < nslots; i++) { for (unsigned i = 0; i < nslots; i++) {
storeValue(templateObject->getFixedSlot(i), storeValue(templateObject->getFixedSlot(i),

View File

@ -33,10 +33,6 @@ JitOptions::JitOptions()
// RangeAnalysis results. // RangeAnalysis results.
checkRangeAnalysis = false; 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. // Whether Ion should compile try-catch statements.
compileTryCatch = true; compileTryCatch = true;

View File

@ -45,7 +45,6 @@ struct JitOptions
bool checkOsiPointRegisters; bool checkOsiPointRegisters;
#endif #endif
bool checkRangeAnalysis; bool checkRangeAnalysis;
bool checkThreadSafety;
bool compileTryCatch; bool compileTryCatch;
bool disableGvn; bool disableGvn;
bool disableLicm; bool disableLicm;

View File

@ -257,13 +257,10 @@ IonBuilder::inlineArray(CallInfo &callInfo)
types::TemporaryTypeSet::DoubleConversion conversion = types::TemporaryTypeSet::DoubleConversion conversion =
getInlineReturnTypeSet()->convertDoubleElements(constraints()); getInlineReturnTypeSet()->convertDoubleElements(constraints());
{ if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
AutoThreadSafeAccess ts(templateObject); templateObject->setShouldConvertDoubleElements();
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles) else
templateObject->setShouldConvertDoubleElements(); templateObject->clearShouldConvertDoubleElements();
else
templateObject->clearShouldConvertDoubleElements();
}
MNewArray *ins = MNewArray::New(alloc(), constraints(), initLength, templateObject, MNewArray *ins = MNewArray::New(alloc(), constraints(), initLength, templateObject,
templateObject->type()->initialHeap(constraints()), templateObject->type()->initialHeap(constraints()),

View File

@ -788,8 +788,6 @@ MStringLength::foldsTo(TempAllocator &alloc, bool useValueNumbers)
if ((type() == MIRType_Int32) && (string()->isConstant())) { if ((type() == MIRType_Int32) && (string()->isConstant())) {
Value value = string()->toConstant()->value(); Value value = string()->toConstant()->value();
JSAtom *atom = &value.toString()->asAtom(); JSAtom *atom = &value.toString()->asAtom();
AutoThreadSafeAccess ts(atom);
return MConstant::New(alloc, Int32Value(atom->length())); return MConstant::New(alloc, Int32Value(atom->length()));
} }
@ -2607,7 +2605,6 @@ MBeta::printOpcode(FILE *fp) const
bool bool
MNewObject::shouldUseVM() const MNewObject::shouldUseVM() const
{ {
AutoThreadSafeAccess ts(templateObject());
return templateObject()->hasSingletonType() || return templateObject()->hasSingletonType() ||
templateObject()->hasDynamicSlots(); templateObject()->hasDynamicSlots();
} }

View File

@ -279,7 +279,6 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
#ifdef DEBUG #ifdef DEBUG
if (GetIonContext()->cx) { if (GetIonContext()->cx) {
AutoThreadSafeAccess ts(script);
uint32_t stackDepth; uint32_t stackDepth;
bool reachablePC; bool reachablePC;
if (!ReconstructStackDepth(GetIonContext()->cx, script, bailPC, &stackDepth, &reachablePC)) if (!ReconstructStackDepth(GetIonContext()->cx, script, bailPC, &stackDepth, &reachablePC))

View File

@ -31,7 +31,6 @@ namespace js {
inline jsid inline jsid
AtomToId(JSAtom *atom) AtomToId(JSAtom *atom)
{ {
AutoThreadSafeAccess ts(atom);
JS_STATIC_ASSERT(JSID_INT_MIN == 0); JS_STATIC_ASSERT(JSID_INT_MIN == 0);
uint32_t index; uint32_t index;

View File

@ -29,8 +29,6 @@ BooleanGetPrimitiveValue(HandleObject obj, JSContext *cx)
inline bool inline bool
EmulatesUndefined(JSObject *obj) EmulatesUndefined(JSObject *obj)
{ {
AutoThreadSafeAccess ts0(obj);
AutoThreadSafeAccess ts1(obj->typeRaw());
JSObject *actual = MOZ_LIKELY(!obj->is<WrapperObject>()) ? obj : UncheckedUnwrap(obj); JSObject *actual = MOZ_LIKELY(!obj->is<WrapperObject>()) ? obj : UncheckedUnwrap(obj);
return actual->getClass()->emulatesUndefined(); return actual->getClass()->emulatesUndefined();
} }

View File

@ -116,7 +116,6 @@ js::ExistingCloneFunctionAtCallsite(const CallsiteCloneTable &table, JSFunction
JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite()); JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite());
JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope()); JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
JS_ASSERT(types::UseNewTypeForClone(fun)); JS_ASSERT(types::UseNewTypeForClone(fun));
JS_ASSERT(CurrentThreadCanReadCompilationData());
/* /*
* If we start allocating function objects in the nursery, then the callsite * 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 CallsiteCloneKey Key;
typedef CallsiteCloneTable Table; typedef CallsiteCloneTable Table;
AutoLockForCompilation lock(cx);
Table &table = cx->compartment()->callsiteClones; Table &table = cx->compartment()->callsiteClones;
if (!table.initialized() && !table.init()) if (!table.initialized() && !table.init())
return nullptr; return nullptr;

View File

@ -1087,69 +1087,6 @@ class AutoLockForExclusiveAccess
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 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 */ } /* namespace js */
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -22,14 +22,7 @@ JSCompartment::initGlobal(js::GlobalObject &global)
js::GlobalObject * js::GlobalObject *
JSCompartment::maybeGlobal() const JSCompartment::maybeGlobal() const
{ {
#ifdef DEBUG JS_ASSERT_IF(global_, global_->compartment() == this);
if (global_) {
js::AutoThreadSafeAccess ts0(global_);
js::AutoThreadSafeAccess ts1(global_->lastProperty());
js::AutoThreadSafeAccess ts2(global_->lastProperty()->base());
JS_ASSERT(global_->compartment() == this);
}
#endif
return global_; return global_;
} }

View File

@ -1150,7 +1150,6 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
RootedScript script(cx, lazy->maybeScript()); RootedScript script(cx, lazy->maybeScript());
if (script) { if (script) {
AutoLockForCompilation lock(cx);
fun->setUnlazifiedScript(script); fun->setUnlazifiedScript(script);
// Remember the lazy script on the compiled script, so it can be // Remember the lazy script on the compiled script, so it can be
// stored on the function again in case of re-lazification. // stored on the function again in case of re-lazification.
@ -1167,7 +1166,6 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
if (!script) if (!script)
return false; return false;
AutoLockForCompilation lock(cx);
fun->setUnlazifiedScript(script); fun->setUnlazifiedScript(script);
return true; return true;
} }
@ -1196,10 +1194,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
fun->initAtom(script->functionNonDelazifying()->displayAtom()); fun->initAtom(script->functionNonDelazifying()->displayAtom());
clonedScript->setFunction(fun); clonedScript->setFunction(fun);
{ fun->setUnlazifiedScript(clonedScript);
AutoLockForCompilation lock(cx);
fun->setUnlazifiedScript(clonedScript);
}
CallNewScriptHook(cx, clonedScript, fun); CallNewScriptHook(cx, clonedScript, fun);

View File

@ -105,12 +105,10 @@ class JSFunction : public JSObject
} }
size_t nargs() const { size_t nargs() const {
js::AutoThreadSafeAccess ts(this);
return nargs_; return nargs_;
} }
uint16_t flags() const { uint16_t flags() const {
js::AutoThreadSafeAccess ts(this);
return flags_; return flags_;
} }
@ -134,14 +132,10 @@ class JSFunction : public JSObject
return flags() & SH_WRAPPABLE; return flags() & SH_WRAPPABLE;
} }
// Functions can change between being lazily interpreted and having scripts
// when under the compilation lock.
bool isInterpretedLazy() const { bool isInterpretedLazy() const {
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
return flags() & INTERPRETED_LAZY; return flags() & INTERPRETED_LAZY;
} }
bool hasScript() const { bool hasScript() const {
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
return flags() & INTERPRETED; return flags() & INTERPRETED;
} }
@ -238,7 +232,6 @@ class JSFunction : public JSObject
void initAtom(JSAtom *atom) { atom_.init(atom); } void initAtom(JSAtom *atom) { atom_.init(atom); }
JSAtom *displayAtom() const { JSAtom *displayAtom() const {
js::AutoThreadSafeAccess ts(this);
return atom_; return atom_;
} }
@ -258,7 +251,6 @@ class JSFunction : public JSObject
* activations (stack frames) of the function. * activations (stack frames) of the function.
*/ */
JSObject *environment() const { JSObject *environment() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(isInterpreted()); JS_ASSERT(isInterpreted());
return u.i.env_; return u.i.env_;
} }
@ -332,8 +324,6 @@ class JSFunction : public JSObject
} }
JSScript *nonLazyScript() const { JSScript *nonLazyScript() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
JS_ASSERT(hasScript()); JS_ASSERT(hasScript());
JS_ASSERT(u.i.s.script_); JS_ASSERT(u.i.s.script_);
return u.i.s.script_; return u.i.s.script_;
@ -355,16 +345,12 @@ class JSFunction : public JSObject
} }
js::LazyScript *lazyScript() const { js::LazyScript *lazyScript() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_); JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_);
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
return u.i.s.lazy_; return u.i.s.lazy_;
} }
js::LazyScript *lazyScriptOrNull() const { js::LazyScript *lazyScriptOrNull() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(isInterpretedLazy()); JS_ASSERT(isInterpretedLazy());
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
return u.i.s.lazy_; return u.i.s.lazy_;
} }
@ -398,7 +384,6 @@ class JSFunction : public JSObject
void setUnlazifiedScript(JSScript *script) { void setUnlazifiedScript(JSScript *script) {
// Note: createScriptForLazilyInterpretedFunction triggers a barrier on // Note: createScriptForLazilyInterpretedFunction triggers a barrier on
// lazy script before it is overwritten here. // lazy script before it is overwritten here.
JS_ASSERT(js::CurrentThreadCanWriteCompilationData());
JS_ASSERT(isInterpretedLazy()); JS_ASSERT(isInterpretedLazy());
if (!lazyScript()->maybeScript()) if (!lazyScript()->maybeScript())
lazyScript()->initScript(script); lazyScript()->initScript(script);
@ -415,7 +400,6 @@ class JSFunction : public JSObject
} }
JSNative native() const { JSNative native() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(isNative()); JS_ASSERT(isNative());
return u.n.native; return u.n.native;
} }
@ -440,7 +424,6 @@ class JSFunction : public JSObject
} }
const JSJitInfo *jitInfo() const { const JSJitInfo *jitInfo() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(isNative()); JS_ASSERT(isNative());
return u.n.jitinfo; return u.n.jitinfo;
} }

View File

@ -688,9 +688,6 @@ TypeScript::FreezeTypeSets(CompilerConstraintList *constraints, JSScript *script
TemporaryTypeSet **pArgTypes, TemporaryTypeSet **pArgTypes,
TemporaryTypeSet **pBytecodeTypes) TemporaryTypeSet **pBytecodeTypes)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
AutoThreadSafeAccess ts(script);
LifoAlloc *alloc = constraints->alloc(); LifoAlloc *alloc = constraints->alloc();
StackTypeSet *existing = script->types->typeArray(); StackTypeSet *existing = script->types->typeArray();
@ -810,7 +807,6 @@ TypeObjectKey::proto()
bool bool
ObjectImpl::hasTenuredProto() const ObjectImpl::hasTenuredProto() const
{ {
AutoThreadSafeAccess ts(this);
return type_->hasTenuredProto(); return type_->hasTenuredProto();
} }
@ -856,7 +852,6 @@ HeapTypeSetKey
TypeObjectKey::property(jsid id) TypeObjectKey::property(jsid id)
{ {
JS_ASSERT(!unknownProperties()); JS_ASSERT(!unknownProperties());
JS_ASSERT(CurrentThreadCanReadCompilationData());
HeapTypeSetKey property; HeapTypeSetKey property;
property.object_ = this; property.object_ = this;
@ -1513,10 +1508,8 @@ ObjectStateChange(ExclusiveContext *cxArg, TypeObject *object, bool markingUnkno
HeapTypeSet *types = object->maybeGetProperty(JSID_EMPTY); HeapTypeSet *types = object->maybeGetProperty(JSID_EMPTY);
/* Mark as unknown after getting the types, to avoid assertion. */ /* Mark as unknown after getting the types, to avoid assertion. */
if (markingUnknown) { if (markingUnknown)
AutoLockForCompilation lock(cxArg);
object->addFlags(OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES); object->addFlags(OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES);
}
if (types) { if (types) {
if (JSContext *cx = cxArg->maybeJSContext()) { 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); target->addFlags(OBJECT_FLAG_SETS_MARKED_UNKNOWN);
} }
@ -2756,28 +2748,9 @@ TypeCompartment::newTypedObject(JSContext *cx, IdValuePair *properties, size_t n
// TypeObject // 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 void
TypeObject::setProto(JSContext *cx, TaggedProto proto) TypeObject::setProto(JSContext *cx, TaggedProto proto)
{ {
JS_ASSERT(CurrentThreadCanWriteCompilationData());
JS_ASSERT(singleton()); JS_ASSERT(singleton());
if (proto.isObject() && IsInsideNursery(cx->runtime(), proto.toObject())) if (proto.isObject() && IsInsideNursery(cx->runtime(), proto.toObject()))
@ -3056,10 +3029,7 @@ TypeObject::setFlags(ExclusiveContext *cx, TypeObjectFlags flags)
singleton()->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON)); singleton()->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON));
} }
{ addFlags(flags);
AutoLockForCompilation lock(cx);
addFlags(flags);
}
InferSpew(ISpewOps, "%s: setFlags 0x%x", TypeObjectString(this), flags); InferSpew(ISpewOps, "%s: setFlags 0x%x", TypeObjectString(this), flags);
@ -3104,10 +3074,8 @@ void
TypeObject::clearAddendum(ExclusiveContext *cx) TypeObject::clearAddendum(ExclusiveContext *cx)
{ {
JS_ASSERT(!(flags() & OBJECT_FLAG_ADDENDUM_CLEARED)); 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 * 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 #endif
new (newScript) TypeNewScript(); new (newScript) TypeNewScript();
{ type->setAddendum(newScript);
AutoLockForCompilation lock(cx);
type->setAddendum(newScript);
}
if (!newScript) { if (!newScript) {
cx->compartment()->types.setPendingNukeTypes(cx); cx->compartment()->types.setPendingNukeTypes(cx);
@ -3692,10 +3657,7 @@ JSScript::makeTypes(JSContext *cx)
for (unsigned i = 0; i < count; i++) for (unsigned i = 0; i < count; i++)
new (&typeArray[i]) StackTypeSet(); new (&typeArray[i]) StackTypeSet();
{ types = typeScript;
AutoLockForCompilation lock(cx);
types = typeScript;
}
#ifdef DEBUG #ifdef DEBUG
for (unsigned i = 0; i < nTypeSets(); i++) { for (unsigned i = 0; i < nTypeSets(); i++) {
@ -3825,12 +3787,8 @@ JSObject::splicePrototype(JSContext *cx, const Class *clasp, Handle<TaggedProto>
return true; return true;
} }
{ type->setClasp(clasp);
AutoLockForCompilation lock(cx); type->setProto(cx, proto);
type->setClasp(clasp);
type->setProto(cx, proto);
}
return true; return true;
} }
@ -3883,10 +3841,7 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted())
type->interpretedFunction = &obj->as<JSFunction>(); type->interpretedFunction = &obj->as<JSFunction>();
{ obj->type_ = type;
AutoLockForCompilation lock(cx);
obj->type_ = type;
}
return type; return type;
} }
@ -4628,7 +4583,6 @@ TypeScript::printTypes(JSContext *cx, HandleScript script) const
void void
TypeObject::setAddendum(TypeObjectAddendum *addendum) TypeObject::setAddendum(TypeObjectAddendum *addendum)
{ {
JS_ASSERT(CurrentThreadCanWriteCompilationData());
this->addendum = addendum; this->addendum = addendum;
} }

View File

@ -27,11 +27,6 @@ namespace js {
class TypeDescr; class TypeDescr;
#ifdef DEBUG
bool CurrentThreadCanWriteCompilationData();
bool CurrentThreadCanReadCompilationData();
#endif
class TaggedProto class TaggedProto
{ {
public: public:
@ -890,12 +885,6 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
/* Prototype shared by objects using this type. */ /* Prototype shared by objects using this type. */
HeapPtrObject proto_; 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 * 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 * must appear in type sets instead of this; we include the back reference
@ -906,24 +895,19 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
public: public:
const Class *clasp() const { const Class *clasp() const {
AutoThreadSafeAccess ts(this);
return clasp_; return clasp_;
} }
void setClasp(const Class *clasp) { void setClasp(const Class *clasp) {
JS_ASSERT(CurrentThreadCanWriteCompilationData());
JS_ASSERT(singleton()); JS_ASSERT(singleton());
clasp_ = clasp; clasp_ = clasp;
} }
TaggedProto proto() const { TaggedProto proto() const {
AutoThreadSafeAccess ts(this);
assertCanAccessProto();
return TaggedProto(proto_); return TaggedProto(proto_);
} }
JSObject *singleton() const { JSObject *singleton() const {
AutoThreadSafeAccess ts(this);
return singleton_; return singleton_;
} }
@ -965,42 +949,30 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
public: public:
TypeObjectFlags flags() const { TypeObjectFlags flags() const {
JS_ASSERT(CurrentThreadCanReadCompilationData());
AutoThreadSafeAccess ts(this);
return flags_; return flags_;
} }
void addFlags(TypeObjectFlags flags) { void addFlags(TypeObjectFlags flags) {
JS_ASSERT(CurrentThreadCanWriteCompilationData());
flags_ |= flags; flags_ |= flags;
} }
void clearFlags(TypeObjectFlags flags) { void clearFlags(TypeObjectFlags flags) {
JS_ASSERT(CurrentThreadCanWriteCompilationData());
flags_ &= ~flags; flags_ &= ~flags;
} }
bool hasNewScript() const { bool hasNewScript() const {
JS_ASSERT(CurrentThreadCanReadCompilationData());
AutoThreadSafeAccess ts(this);
return addendum && addendum->isNewScript(); return addendum && addendum->isNewScript();
} }
TypeNewScript *newScript() { TypeNewScript *newScript() {
JS_ASSERT(CurrentThreadCanReadCompilationData());
AutoThreadSafeAccess ts(this);
return addendum->asNewScript(); return addendum->asNewScript();
} }
bool hasTypedObject() { bool hasTypedObject() {
JS_ASSERT(CurrentThreadCanReadCompilationData());
AutoThreadSafeAccess ts(this);
return addendum && addendum->isTypedObject(); return addendum && addendum->isTypedObject();
} }
TypeTypedObject *typedObject() { TypeTypedObject *typedObject() {
JS_ASSERT(CurrentThreadCanReadCompilationData());
AutoThreadSafeAccess ts(this);
return addendum->asTypedObject(); return addendum->asTypedObject();
} }

View File

@ -87,7 +87,6 @@ Type::ObjectType(JSObject *obj)
/* static */ inline Type /* static */ inline Type
Type::ObjectType(TypeObject *obj) Type::ObjectType(TypeObject *obj)
{ {
AutoThreadSafeAccess ts(obj);
if (obj->singleton()) if (obj->singleton())
return Type(uintptr_t(obj->singleton()) | 1); return Type(uintptr_t(obj->singleton()) | 1);
return Type(uintptr_t(obj)); return Type(uintptr_t(obj));
@ -178,7 +177,6 @@ IdToTypeId(jsid id)
*/ */
if (JSID_IS_STRING(id)) { if (JSID_IS_STRING(id)) {
JSAtom *atom = JSID_TO_ATOM(id); JSAtom *atom = JSID_TO_ATOM(id);
js::AutoThreadSafeAccess ts(atom);
JS::TwoByteChars cp = atom->range(); JS::TwoByteChars cp = atom->range();
if (cp.length() > 0 && (JS7_ISDEC(cp[0]) || cp[0] == '-')) { if (cp.length() > 0 && (JS7_ISDEC(cp[0]) || cp[0] == '-')) {
for (size_t i = 1; i < cp.length(); ++i) { for (size_t i = 1; i < cp.length(); ++i) {
@ -565,7 +563,6 @@ TypeScript::NumTypeSets(JSScript *script)
/* static */ inline StackTypeSet * /* static */ inline StackTypeSet *
TypeScript::ThisTypes(JSScript *script) TypeScript::ThisTypes(JSScript *script)
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
return script->types->typeArray() + script->nTypeSets() + analyze::ThisSlot(); return script->types->typeArray() + script->nTypeSets() + analyze::ThisSlot();
} }
@ -579,7 +576,6 @@ TypeScript::ThisTypes(JSScript *script)
TypeScript::ArgTypes(JSScript *script, unsigned i) TypeScript::ArgTypes(JSScript *script, unsigned i)
{ {
JS_ASSERT(i < script->functionNonDelazifying()->nargs()); JS_ASSERT(i < script->functionNonDelazifying()->nargs());
JS_ASSERT(CurrentThreadCanReadCompilationData());
return script->types->typeArray() + script->nTypeSets() + analyze::ArgSlot(i); return script->types->typeArray() + script->nTypeSets() + analyze::ArgSlot(i);
} }
@ -1128,12 +1124,9 @@ ConstraintTypeSet::addType(ExclusiveContext *cxArg, Type type)
if (hasType(type)) if (hasType(type))
return; return;
{ if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) {
AutoLockForCompilation lock(cxArg); cxArg->compartment()->types.setPendingNukeTypes(cxArg);
if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) { return;
cxArg->compartment()->types.setPendingNukeTypes(cxArg);
return;
}
} }
InferSpew(ISpewOps, "addType: %sT%p%s %s", InferSpew(ISpewOps, "addType: %sT%p%s %s",
@ -1277,7 +1270,6 @@ inline TypeObject::TypeObject(const Class *clasp, TaggedProto proto, TypeObjectF
inline uint32_t inline uint32_t
TypeObject::basePropertyCount() const TypeObject::basePropertyCount() const
{ {
JS_ASSERT(CurrentThreadCanReadCompilationData());
return (flags() & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT; 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)) if (HeapTypeSet *types = maybeGetProperty(id))
return types; return types;
uint32_t propertyCount; uint32_t propertyCount = basePropertyCount();
Property **pprop; Property **pprop = HashSetInsert<jsid,Property,Property>
{ (cx->typeLifoAlloc(), propertySet, propertyCount, id);
AutoLockForCompilation lock(cx); if (!pprop) {
cx->compartment()->types.setPendingNukeTypes(cx);
return nullptr;
}
propertyCount = basePropertyCount(); JS_ASSERT(!*pprop);
pprop = HashSetInsert<jsid,Property,Property>
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
if (!pprop) {
cx->compartment()->types.setPendingNukeTypes(cx);
return nullptr;
}
JS_ASSERT(!*pprop); setBasePropertyCount(propertyCount);
if (!addProperty(cx, id, pprop)) {
setBasePropertyCount(propertyCount); setBasePropertyCount(0);
if (!addProperty(cx, id, pprop)) { propertySet = nullptr;
setBasePropertyCount(0); return nullptr;
propertySet = nullptr;
return nullptr;
}
} }
if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) { 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(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id)); JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
JS_ASSERT(!unknownProperties()); JS_ASSERT(!unknownProperties());
JS_ASSERT(CurrentThreadCanReadCompilationData());
AutoThreadSafeAccess ts(this);
Property *prop = HashSetLookup<jsid,Property,Property> Property *prop = HashSetLookup<jsid,Property,Property>
(propertySet, basePropertyCount(), id); (propertySet, basePropertyCount(), id);

View File

@ -2048,7 +2048,6 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
if (!LinkConstructorAndPrototype(cx, genFunction, genFunctionProto)) if (!LinkConstructorAndPrototype(cx, genFunction, genFunctionProto))
return false; return false;
AutoLockForCompilation lock(cx);
global->setSlot(STAR_GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto)); global->setSlot(STAR_GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto));
global->setConstructor(JSProto_GeneratorFunction, ObjectValue(*genFunction)); global->setConstructor(JSProto_GeneratorFunction, ObjectValue(*genFunction));
global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto)); global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto));

View File

@ -2250,12 +2250,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
* Swap the object's types, to restore their initial type information. * Swap the object's types, to restore their initial type information.
* The prototypes and classes of the objects were swapped in ReserveForTradeGuts. * The prototypes and classes of the objects were swapped in ReserveForTradeGuts.
*/ */
{ TypeObject *tmp = a->type_;
AutoLockForCompilation lock(cx); a->type_ = b->type_;
TypeObject *tmp = a->type_; b->type_ = tmp;
a->type_ = b->type_;
b->type_ = tmp;
}
/* Don't try to swap a JSFunction for a plain function JSObject. */ /* Don't try to swap a JSFunction for a plain function JSObject. */
JS_ASSERT_IF(a->is<JSFunction>(), a->tenuredSizeOfThis() == b->tenuredSizeOfThis()); 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]; char tmp[mozilla::tl::Max<sizeof(JSFunction), sizeof(JSObject_Slots16)>::value];
JS_ASSERT(size <= sizeof(tmp)); JS_ASSERT(size <= sizeof(tmp));
{ js_memcpy(tmp, a, size);
AutoLockForCompilation lock(cx); js_memcpy(a, b, size);
js_memcpy(tmp, a, size); js_memcpy(b, tmp, size);
js_memcpy(a, b, size);
js_memcpy(b, tmp, size);
}
#ifdef JSGC_GENERATIONAL #ifdef JSGC_GENERATIONAL
/* /*
@ -2330,12 +2324,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
void *bpriv = b->hasPrivate() ? b->getPrivate() : nullptr; void *bpriv = b->hasPrivate() ? b->getPrivate() : nullptr;
char tmp[sizeof(JSObject)]; char tmp[sizeof(JSObject)];
{ js_memcpy(&tmp, a, sizeof tmp);
AutoLockForCompilation lock(cx); js_memcpy(a, b, sizeof tmp);
js_memcpy(&tmp, a, sizeof tmp); js_memcpy(b, &tmp, sizeof tmp);
js_memcpy(a, b, sizeof tmp);
js_memcpy(b, &tmp, sizeof tmp);
}
if (a->isNative()) if (a->isNative())
a->shape_->setNumFixedSlots(reserved.newafixed); 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) { if (!oldCount) {
obj->slots = AllocateSlots(cx, obj, newCount); obj->slots = AllocateSlots(cx, obj, newCount);
if (!obj->slots) 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); 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); HeapSlot *newslots = ReallocateSlots(cx, obj, obj->slots, oldCount, newCount);
if (!newslots) if (!newslots)
return; /* Leave slots at its old size. */ return; /* Leave slots at its old size. */
@ -3227,10 +3206,7 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
MarkTypeObjectUnknownProperties(cx, obj->type(), true); MarkTypeObjectUnknownProperties(cx, obj->type(), true);
MarkTypeObjectUnknownProperties(cx, type, true); MarkTypeObjectUnknownProperties(cx, type, true);
{ obj->setType(type);
AutoLockForCompilation lock(cx);
obj->setType(type);
}
*succeeded = true; *succeeded = true;
return true; return true;
@ -4303,7 +4279,7 @@ NativeGetInline(JSContext *cx,
case JSOP_GETPROP: case JSOP_GETPROP:
case JSOP_CALLPROP: case JSOP_CALLPROP:
case JSOP_LENGTH: case JSOP_LENGTH:
script->baselineScript()->noteAccessedGetter(cx, script->pcToOffset(pc)); script->baselineScript()->noteAccessedGetter(script->pcToOffset(pc));
break; break;
default: default:
break; break;
@ -5697,8 +5673,6 @@ DumpProperty(JSObject *obj, Shape &shape)
bool bool
JSObject::uninlinedIsProxy() const JSObject::uninlinedIsProxy() const
{ {
AutoThreadSafeAccess ts0(this);
AutoThreadSafeAccess ts1(type_);
return is<ProxyObject>(); return is<ProxyObject>();
} }

View File

@ -289,10 +289,6 @@ class JSObject : public js::ObjectImpl
} }
bool isBoundFunction() const { 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); return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION);
} }
@ -354,10 +350,6 @@ class JSObject : public js::ObjectImpl
return lastProperty()->entryCount(); return lastProperty()->entryCount();
} }
uint32_t propertyCountForCompilation() const {
return lastProperty()->entryCountForCompilation();
}
bool hasShapeTable() const { bool hasShapeTable() const {
return lastProperty()->hasTable(); return lastProperty()->hasTable();
} }
@ -376,13 +368,13 @@ class JSObject : public js::ObjectImpl
/* Whether a slot is at a fixed offset from this object. */ /* Whether a slot is at a fixed offset from this object. */
bool isFixedSlot(size_t slot) { bool isFixedSlot(size_t slot) {
return slot < numFixedSlotsForCompilation(); return slot < numFixedSlots();
} }
/* Index into the dynamic slots array to use for a dynamic slot. */ /* Index into the dynamic slots array to use for a dynamic slot. */
size_t dynamicSlotIndex(size_t slot) { size_t dynamicSlotIndex(size_t slot) {
JS_ASSERT(slot >= numFixedSlotsForCompilation()); JS_ASSERT(slot >= numFixedSlots());
return slot - numFixedSlotsForCompilation(); return slot - numFixedSlots();
} }
/* /*

View File

@ -400,9 +400,6 @@ JSObject::clearType(JSContext *cx, js::HandleObject obj)
inline void inline void
JSObject::setType(js::types::TypeObject *newType) 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(newType);
JS_ASSERT(!hasSingletonType()); JS_ASSERT(!hasSingletonType());
type_ = newType; type_ = newType;
@ -999,11 +996,8 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
JS_ASSERT(!global->nativeLookup(cx, id)); JS_ASSERT(!global->nativeLookup(cx, id));
/* Set these first in case AddTypePropertyId looks for this class. */ /* Set these first in case AddTypePropertyId looks for this class. */
{ global->setConstructor(key, ObjectValue(*ctor));
AutoLockForCompilation lock(cx); global->setPrototype(key, ObjectValue(*proto));
global->setConstructor(key, ObjectValue(*ctor));
global->setPrototype(key, ObjectValue(*proto));
}
global->setConstructorPropertySlot(key, ObjectValue(*ctor)); global->setConstructorPropertySlot(key, ObjectValue(*ctor));
if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) { if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) {

View File

@ -3167,10 +3167,7 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
JS_ASSERT(!script->isGenerator()); JS_ASSERT(!script->isGenerator());
{ script->needsArgsObj_ = true;
AutoLockForCompilation lock(cx);
script->needsArgsObj_ = true;
}
#ifdef JS_ION #ifdef JS_ION
/* /*
@ -3230,14 +3227,12 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
bool bool
JSScript::varIsAliased(uint32_t varSlot) JSScript::varIsAliased(uint32_t varSlot)
{ {
AutoThreadSafeAccess ts(this);
return bindings.bindingIsAliased(bindings.numArgs() + varSlot); return bindings.bindingIsAliased(bindings.numArgs() + varSlot);
} }
bool bool
JSScript::formalIsAliased(unsigned argSlot) JSScript::formalIsAliased(unsigned argSlot)
{ {
AutoThreadSafeAccess ts(this);
return bindings.bindingIsAliased(argSlot); return bindings.bindingIsAliased(argSlot);
} }

View File

@ -249,8 +249,6 @@ class Bindings
if (!callObjShape_) if (!callObjShape_)
return false; return false;
// Binding shapes are immutable once constructed.
AutoThreadSafeAccess ts(callObjShape_);
return !callObjShape_->isEmptyShape(); return !callObjShape_->isEmptyShape();
} }
@ -554,10 +552,6 @@ class ScriptSourceObject : public JSObject
const ReadOnlyCompileOptions &options); const ReadOnlyCompileOptions &options);
ScriptSource *source() { 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()); 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) */ (and arguments if this is a function script) */
bool hasAnyAliasedBindings() const { bool hasAnyAliasedBindings() const {
js::AutoThreadSafeAccess ts(this);
return bindings.hasAnyAliasedBindings(); return bindings.hasAnyAliasedBindings();
} }
js::Binding *bindingArray() const { js::Binding *bindingArray() const {
js::AutoThreadSafeAccess ts(this);
return bindings.bindingArray(); return bindings.bindingArray();
} }
unsigned numArgs() const { unsigned numArgs() const {
js::AutoThreadSafeAccess ts(this);
return bindings.numArgs(); return bindings.numArgs();
} }
js::Shape *callObjShape() const { js::Shape *callObjShape() const {
js::AutoThreadSafeAccess ts(this);
return bindings.callObjShape(); return bindings.callObjShape();
} }
@ -889,11 +879,9 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
// Script bytecode is immutable after creation. // Script bytecode is immutable after creation.
jsbytecode *code() const { jsbytecode *code() const {
js::AutoThreadSafeAccess ts(this);
return code_; return code_;
} }
size_t length() const { size_t length() const {
js::AutoThreadSafeAccess ts(this);
return length_; return length_;
} }
@ -917,94 +905,77 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
} }
size_t mainOffset() const { size_t mainOffset() const {
js::AutoThreadSafeAccess ts(this);
return mainOffset_; return mainOffset_;
} }
size_t lineno() const { size_t lineno() const {
js::AutoThreadSafeAccess ts(this);
return lineno_; return lineno_;
} }
size_t column() const { size_t column() const {
js::AutoThreadSafeAccess ts(this);
return column_; return column_;
} }
void setColumn(size_t column) { column_ = column; } void setColumn(size_t column) { column_ = column; }
size_t nfixed() const { size_t nfixed() const {
js::AutoThreadSafeAccess ts(this);
return function_ ? bindings.numVars() : 0; return function_ ? bindings.numVars() : 0;
} }
size_t nslots() const { size_t nslots() const {
js::AutoThreadSafeAccess ts(this);
return nslots_; return nslots_;
} }
size_t staticLevel() const { size_t staticLevel() const {
js::AutoThreadSafeAccess ts(this);
return staticLevel_; return staticLevel_;
} }
size_t nTypeSets() const { size_t nTypeSets() const {
js::AutoThreadSafeAccess ts(this);
return nTypeSets_; return nTypeSets_;
} }
size_t funLength() const { size_t funLength() const {
js::AutoThreadSafeAccess ts(this);
return funLength_; return funLength_;
} }
size_t sourceStart() const { size_t sourceStart() const {
js::AutoThreadSafeAccess ts(this);
return sourceStart_; return sourceStart_;
} }
size_t sourceEnd() const { size_t sourceEnd() const {
js::AutoThreadSafeAccess ts(this);
return sourceEnd_; return sourceEnd_;
} }
bool noScriptRval() const { bool noScriptRval() const {
js::AutoThreadSafeAccess ts(this);
return noScriptRval_; return noScriptRval_;
} }
bool savedCallerFun() const { return savedCallerFun_; } bool savedCallerFun() const { return savedCallerFun_; }
bool strict() const { bool strict() const {
js::AutoThreadSafeAccess ts(this);
return strict_; return strict_;
} }
bool explicitUseStrict() const { return explicitUseStrict_; } bool explicitUseStrict() const { return explicitUseStrict_; }
bool compileAndGo() const { bool compileAndGo() const {
js::AutoThreadSafeAccess ts(this);
return compileAndGo_; return compileAndGo_;
} }
bool selfHosted() const { return selfHosted_; } bool selfHosted() const { return selfHosted_; }
bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; } bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; }
bool funHasExtensibleScope() const { bool funHasExtensibleScope() const {
js::AutoThreadSafeAccess ts(this);
return funHasExtensibleScope_; return funHasExtensibleScope_;
} }
bool funNeedsDeclEnvObject() const { bool funNeedsDeclEnvObject() const {
js::AutoThreadSafeAccess ts(this);
return funNeedsDeclEnvObject_; return funNeedsDeclEnvObject_;
} }
bool funHasAnyAliasedFormal() const { bool funHasAnyAliasedFormal() const {
js::AutoThreadSafeAccess ts(this);
return funHasAnyAliasedFormal_; return funHasAnyAliasedFormal_;
} }
bool hasSingletons() const { return hasSingletons_; } bool hasSingletons() const { return hasSingletons_; }
bool treatAsRunOnce() const { bool treatAsRunOnce() const {
js::AutoThreadSafeAccess ts(this);
return treatAsRunOnce_; return treatAsRunOnce_;
} }
bool hasRunOnce() const { return hasRunOnce_; } bool hasRunOnce() const { return hasRunOnce_; }
@ -1034,17 +1005,14 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
void setDirectlyInsideEval() { directlyInsideEval_ = true; } void setDirectlyInsideEval() { directlyInsideEval_ = true; }
bool usesArgumentsAndApply() const { bool usesArgumentsAndApply() const {
js::AutoThreadSafeAccess ts(this);
return usesArgumentsAndApply_; return usesArgumentsAndApply_;
} }
void setUsesArgumentsAndApply() { usesArgumentsAndApply_ = true; } void setUsesArgumentsAndApply() { usesArgumentsAndApply_ = true; }
bool shouldCloneAtCallsite() const { bool shouldCloneAtCallsite() const {
js::AutoThreadSafeAccess ts(this);
return shouldCloneAtCallsite_; return shouldCloneAtCallsite_;
} }
bool shouldInline() const { bool shouldInline() const {
js::AutoThreadSafeAccess ts(this);
return shouldInline_; return shouldInline_;
} }
@ -1052,29 +1020,23 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
void setShouldInline() { shouldInline_ = true; } void setShouldInline() { shouldInline_ = true; }
bool isCallsiteClone() const { bool isCallsiteClone() const {
js::AutoThreadSafeAccess ts(this);
return isCallsiteClone_; return isCallsiteClone_;
} }
bool isGeneratorExp() const { return isGeneratorExp_; } bool isGeneratorExp() const { return isGeneratorExp_; }
bool failedBoundsCheck() const { bool failedBoundsCheck() const {
js::AutoThreadSafeAccess ts(this);
return failedBoundsCheck_; return failedBoundsCheck_;
} }
bool failedShapeGuard() const { bool failedShapeGuard() const {
js::AutoThreadSafeAccess ts(this);
return failedShapeGuard_; return failedShapeGuard_;
} }
bool hadFrequentBailouts() const { bool hadFrequentBailouts() const {
js::AutoThreadSafeAccess ts(this);
return hadFrequentBailouts_; return hadFrequentBailouts_;
} }
bool uninlineable() const { bool uninlineable() const {
js::AutoThreadSafeAccess ts(this);
return uninlineable_; return uninlineable_;
} }
bool invalidatedIdempotentCache() const { bool invalidatedIdempotentCache() const {
js::AutoThreadSafeAccess ts(this);
return invalidatedIdempotentCache_; return invalidatedIdempotentCache_;
} }
@ -1095,7 +1057,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
/* See ContextFlags::funArgumentsHasLocalBinding comment. */ /* See ContextFlags::funArgumentsHasLocalBinding comment. */
bool argumentsHasVarBinding() const { bool argumentsHasVarBinding() const {
js::AutoThreadSafeAccess ts(this);
return argsHasVarBinding_; return argsHasVarBinding_;
} }
jsbytecode *argumentsBytecode() const { JS_ASSERT(code()[0] == JSOP_ARGUMENTS); return code(); } 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::GeneratorKind generatorKind() const {
js::AutoThreadSafeAccess ts(this);
return js::GeneratorKindFromBits(generatorKindBits_); return js::GeneratorKindFromBits(generatorKindBits_);
} }
bool isGenerator() const { return generatorKind() != js::NotGenerator; } bool isGenerator() const { return generatorKind() != js::NotGenerator; }
@ -1130,8 +1090,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
*/ */
bool analyzedArgsUsage() const { return !needsArgsAnalysis_; } bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
bool needsArgsObj() const { bool needsArgsObj() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
JS_ASSERT(analyzedArgsUsage()); JS_ASSERT(analyzedArgsUsage());
return needsArgsObj_; return needsArgsObj_;
} }
@ -1156,17 +1114,9 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
} }
bool hasIonScript() const { 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; return ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
} }
bool canIonCompile() const { bool canIonCompile() const {
// Note: see above comment.
js::AutoThreadSafeAccess ts(this);
return ion != ION_DISABLED_SCRIPT; return ion != ION_DISABLED_SCRIPT;
} }
@ -1192,8 +1142,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
} }
bool hasBaselineScript() const { bool hasBaselineScript() const {
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
js::AutoThreadSafeAccess ts(this);
return baseline && baseline != BASELINE_DISABLED_SCRIPT; return baseline && baseline != BASELINE_DISABLED_SCRIPT;
} }
bool canBaselineCompile() const { bool canBaselineCompile() const {
@ -1201,7 +1149,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
} }
js::jit::BaselineScript *baselineScript() const { js::jit::BaselineScript *baselineScript() const {
JS_ASSERT(hasBaselineScript()); JS_ASSERT(hasBaselineScript());
js::AutoThreadSafeAccess ts(this);
return baseline; return baseline;
} }
inline void setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript); inline void setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript);
@ -1213,7 +1160,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
} }
bool canParallelIonCompile() const { bool canParallelIonCompile() const {
js::AutoThreadSafeAccess ts(this);
return parallelIon != ION_DISABLED_SCRIPT; 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. * Original compiled function for the script, if it has a function.
* nullptr for global and eval scripts. * nullptr for global and eval scripts.
* The delazifying variant ensures that the function isn't lazy, but can * The delazifying variant ensures that the function isn't lazy. The
* only be used under a compilation lock. The non-delazifying variant * non-delazifying variant must only be used after earlier code has
* can be used off-thread and without the lock, but must only be used * called ensureNonLazyCanonicalFunction and while the function can't
* after earlier code has called ensureNonLazyCanonicalFunction and * have been relazified.
* while the function can't have been relazified.
*/ */
inline JSFunction *functionDelazifying() const; inline JSFunction *functionDelazifying() const;
JSFunction *functionNonDelazifying() const { JSFunction *functionNonDelazifying() const {
js::AutoThreadSafeAccess ts(this);
return function_; return function_;
} }
inline void setFunction(JSFunction *fun); inline void setFunction(JSFunction *fun);
/* /*
* Takes a compilation lock and de-lazifies the canonical function. Must * De-lazifies the canonical function. Must be called before entering code
* be called before entering code that expects the function to be non-lazy. * that expects the function to be non-lazy.
*/ */
inline void ensureNonLazyCanonicalFunction(JSContext *cx); inline void ensureNonLazyCanonicalFunction(JSContext *cx);
@ -1294,7 +1238,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
void setSourceObject(JSObject *object); void setSourceObject(JSObject *object);
JSObject *sourceObject() const { JSObject *sourceObject() const {
js::AutoThreadSafeAccess ts(this);
return sourceObject_; return sourceObject_;
} }
js::ScriptSource *scriptSource() const; js::ScriptSource *scriptSource() const;
@ -1335,7 +1278,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
JSObject *enclosingStaticScope() const { JSObject *enclosingStaticScope() const {
if (isCallsiteClone()) if (isCallsiteClone())
return nullptr; return nullptr;
js::AutoThreadSafeAccess ts(this);
return enclosingScopeOrOriginalFunction_; return enclosingScopeOrOriginalFunction_;
} }
@ -1345,8 +1287,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
public: public:
uint32_t getUseCount() const { uint32_t getUseCount() const {
// Note: We ignore races when reading the use count of a script off thread.
js::AutoThreadSafeAccess ts(this);
return useCount; return useCount;
} }
uint32_t incUseCount(uint32_t amount = 1) { return useCount += amount; } 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()); } jssrcnote *notes() { return (jssrcnote *)(code() + length()); }
bool hasArray(ArrayKind kind) { bool hasArray(ArrayKind kind) {
js::AutoThreadSafeAccess ts(this);
return (hasArrayBits & (1 << kind)); return (hasArrayBits & (1 << kind));
} }
void setHasArray(ArrayKind kind) { 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::ConstArray *consts() {
JS_ASSERT(hasConsts()); JS_ASSERT(hasConsts());
js::AutoThreadSafeAccess ts(this);
return reinterpret_cast<js::ConstArray *>(data + constsOffset()); return reinterpret_cast<js::ConstArray *>(data + constsOffset());
} }
js::ObjectArray *objects() { js::ObjectArray *objects() {
JS_ASSERT(hasObjects()); JS_ASSERT(hasObjects());
js::AutoThreadSafeAccess ts(this);
return reinterpret_cast<js::ObjectArray *>(data + objectsOffset()); return reinterpret_cast<js::ObjectArray *>(data + objectsOffset());
} }
js::ObjectArray *regexps() { js::ObjectArray *regexps() {
JS_ASSERT(hasRegexps()); JS_ASSERT(hasRegexps());
js::AutoThreadSafeAccess ts(this);
return reinterpret_cast<js::ObjectArray *>(data + regexpsOffset()); return reinterpret_cast<js::ObjectArray *>(data + regexpsOffset());
} }
js::TryNoteArray *trynotes() { js::TryNoteArray *trynotes() {
JS_ASSERT(hasTrynotes()); JS_ASSERT(hasTrynotes());
js::AutoThreadSafeAccess ts(this);
return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset()); return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset());
} }
js::BlockScopeArray *blockScopes() { js::BlockScopeArray *blockScopes() {
JS_ASSERT(hasBlockScopes()); JS_ASSERT(hasBlockScopes());
js::AutoThreadSafeAccess ts(this);
return reinterpret_cast<js::BlockScopeArray *>(data + blockScopesOffset()); return reinterpret_cast<js::BlockScopeArray *>(data + blockScopesOffset());
} }
@ -1438,7 +1372,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
size_t natoms() const { return natoms_; } size_t natoms() const { return natoms_; }
js::HeapPtrAtom &getAtom(size_t index) const { js::HeapPtrAtom &getAtom(size_t index) const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(index < natoms()); JS_ASSERT(index < natoms());
return atoms[index]; return atoms[index];
} }
@ -1795,7 +1728,6 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
} }
bool usesArgumentsAndApply() const { bool usesArgumentsAndApply() const {
AutoThreadSafeAccess ts(this);
return usesArgumentsAndApply_; return usesArgumentsAndApply_;
} }
void setUsesArgumentsAndApply() { void setUsesArgumentsAndApply() {
@ -1820,11 +1752,9 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
return sourceObject()->source(); return sourceObject()->source();
} }
uint32_t begin() const { uint32_t begin() const {
AutoThreadSafeAccess ts(this);
return begin_; return begin_;
} }
uint32_t end() const { uint32_t end() const {
AutoThreadSafeAccess ts(this);
return end_; return end_;
} }
uint32_t lineno() const { uint32_t lineno() const {

View File

@ -58,8 +58,6 @@ LazyScript::functionDelazifying(JSContext *cx) const
inline JSFunction * inline JSFunction *
JSScript::functionDelazifying() const JSScript::functionDelazifying() const
{ {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(js::CurrentThreadCanWriteCompilationData());
if (function_ && function_->isInterpretedLazy()) { if (function_ && function_->isInterpretedLazy()) {
function_->setUnlazifiedScript(const_cast<JSScript *>(this)); function_->setUnlazifiedScript(const_cast<JSScript *>(this));
// If this script has a LazyScript, make sure the LazyScript has a // If this script has a LazyScript, make sure the LazyScript has a
@ -81,19 +79,15 @@ inline void
JSScript::ensureNonLazyCanonicalFunction(JSContext *cx) JSScript::ensureNonLazyCanonicalFunction(JSContext *cx)
{ {
// Infallibly delazify the canonical script. // Infallibly delazify the canonical script.
if (function_ && function_->isInterpretedLazy()) { if (function_ && function_->isInterpretedLazy())
js::AutoLockForCompilation lock(cx);
functionDelazifying(); functionDelazifying();
}
} }
inline JSFunction * inline JSFunction *
JSScript::getFunction(size_t index) JSScript::getFunction(size_t index)
{ {
JSFunction *fun = &getObject(index)->as<JSFunction>(); JSFunction *fun = &getObject(index)->as<JSFunction>();
#ifdef DEBUG
JS_ASSERT_IF(fun->isNative(), IsAsmJSModuleNative(fun->native())); JS_ASSERT_IF(fun->isNative(), IsAsmJSModuleNative(fun->native()));
#endif
return fun; return fun;
} }
@ -138,7 +132,6 @@ JSScript::global() const
* A JSScript always marks its compartment's global (via bindings) so we * A JSScript always marks its compartment's global (via bindings) so we
* can assert that maybeGlobal is non-null here. * can assert that maybeGlobal is non-null here.
*/ */
js::AutoThreadSafeAccess ts(this);
return *compartment()->maybeGlobal(); return *compartment()->maybeGlobal();
} }
@ -149,14 +142,16 @@ JSScript::principals()
} }
inline JSFunction * inline JSFunction *
JSScript::donorFunction() const { JSScript::donorFunction() const
{
if (!isCallsiteClone()) if (!isCallsiteClone())
return nullptr; return nullptr;
return &enclosingScopeOrOriginalFunction_->as<JSFunction>(); return &enclosingScopeOrOriginalFunction_->as<JSFunction>();
} }
inline void inline void
JSScript::setIsCallsiteClone(JSObject *fun) { JSScript::setIsCallsiteClone(JSObject *fun)
{
JS_ASSERT(shouldCloneAtCallsite()); JS_ASSERT(shouldCloneAtCallsite());
shouldCloneAtCallsite_ = false; shouldCloneAtCallsite_ = false;
isCallsiteClone_ = true; isCallsiteClone_ = true;
@ -166,14 +161,12 @@ JSScript::setIsCallsiteClone(JSObject *fun) {
} }
inline void inline void
JSScript::setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript) { JSScript::setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript)
{
#ifdef JS_ION #ifdef JS_ION
if (hasBaselineScript()) if (hasBaselineScript())
js::jit::BaselineScript::writeBarrierPre(tenuredZone(), baseline); js::jit::BaselineScript::writeBarrierPre(tenuredZone(), baseline);
#endif #endif
mozilla::Maybe<js::AutoLockForCompilation> lock;
if (maybecx)
lock.construct(maybecx);
baseline = baselineScript; baseline = baselineScript;
updateBaselineOrIonRaw(); updateBaselineOrIonRaw();
} }

View File

@ -4254,8 +4254,6 @@ js::CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *resul
int32_t int32_t
js::CompareAtoms(JSAtom *atom1, JSAtom *atom2) js::CompareAtoms(JSAtom *atom1, JSAtom *atom2)
{ {
AutoThreadSafeAccess ts0(atom1);
AutoThreadSafeAccess ts1(atom2);
return CompareChars(atom1->chars(), atom1->length(), atom2->chars(), atom2->length()); return CompareChars(atom1->chars(), atom1->length(), atom2->chars(), atom2->length());
} }

View File

@ -93,8 +93,6 @@ js::StartOffThreadIonCompile(JSContext *cx, jit::IonBuilder *builder)
if (!WorkerThreadState().ionWorklist().append(builder)) if (!WorkerThreadState().ionWorklist().append(builder))
return false; return false;
cx->runtime()->addCompilationThread();
WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER); WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER);
return true; return true;
} }
@ -649,8 +647,6 @@ GlobalWorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void
JSObject *newProto = GetClassPrototypePure(&parseTask->scopeChain->global(), key); JSObject *newProto = GetClassPrototypePure(&parseTask->scopeChain->global(), key);
JS_ASSERT(newProto); 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); object->setProtoUnchecked(newProto);
} }
@ -791,11 +787,7 @@ WorkerThread::handleIonWorkload()
jit::IonContext ictx(jit::CompileRuntime::get(rt), jit::IonContext ictx(jit::CompileRuntime::get(rt),
jit::CompileCompartment::get(ionBuilder->script()->compartment()), jit::CompileCompartment::get(ionBuilder->script()->compartment()),
&ionBuilder->alloc()); &ionBuilder->alloc());
AutoEnterIonCompilation ionCompiling; ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
bool succeeded = ionBuilder->build();
ionBuilder->clearForBackEnd();
if (succeeded)
ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
} }
FinishOffThreadIonCompile(ionBuilder); FinishOffThreadIonCompile(ionBuilder);

View File

@ -83,9 +83,6 @@ js::UncheckedUnwrap(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp)
{ {
unsigned flags = 0; unsigned flags = 0;
while (true) { while (true) {
AutoThreadSafeAccess ts0(wrapped);
AutoThreadSafeAccess ts1(wrapped->typeRaw());
AutoThreadSafeAccess ts2(wrapped->lastProperty());
if (!wrapped->is<WrapperObject>() || if (!wrapped->is<WrapperObject>() ||
MOZ_UNLIKELY(stopAtOuter && wrapped->getClass()->ext.innerObject)) MOZ_UNLIKELY(stopAtOuter && wrapped->getClass()->ext.innerObject))
{ {

View File

@ -5511,9 +5511,6 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
if (op->getBoolOption("ion-check-range-analysis")) if (op->getBoolOption("ion-check-range-analysis"))
jit::js_JitOptions.checkRangeAnalysis = true; 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 (const char *str = op->getStringOption("ion-inlining")) {
if (strcmp(str, "on") == 0) if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableInlining = false; jit::js_JitOptions.disableInlining = false;
@ -5788,8 +5785,6 @@ main(int argc, char **argv, char **envp)
"Range analysis (default: on, off to disable)") "Range analysis (default: on, off to disable)")
|| !op.addBoolOption('\0', "ion-check-range-analysis", || !op.addBoolOption('\0', "ion-check-range-analysis",
"Range analysis checking") "Range analysis checking")
|| !op.addBoolOption('\0', "ion-check-thread-safety",
"IonBuilder thread safety checking")
|| !op.addStringOption('\0', "ion-inlining", "on/off", || !op.addStringOption('\0', "ion-inlining", "on/off",
"Inline methods where possible (default: on, off to disable)") "Inline methods where possible (default: on, off to disable)")
|| !op.addStringOption('\0', "ion-osr", "on/off", || !op.addStringOption('\0', "ion-osr", "on/off",
@ -5898,15 +5893,8 @@ main(int argc, char **argv, char **envp)
if (!JS_Init()) if (!JS_Init())
return 1; 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. */ /* 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) if (!rt)
return 1; return 1;
gTimeoutFunc = NullValue(); gTimeoutFunc = NullValue();

View File

@ -554,14 +554,14 @@ GlobalObject::getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global,
{ {
if (!global->getOrCreateObjectPrototype(cx)) if (!global->getOrCreateObjectPrototype(cx))
return false; return false;
eval.set(&global->getSlotForCompilation(EVAL).toObject()); eval.set(&global->getSlot(EVAL).toObject());
return true; return true;
} }
bool bool
GlobalObject::valueIsEval(Value val) GlobalObject::valueIsEval(Value val)
{ {
Value eval = getSlotForCompilation(EVAL); Value eval = getSlot(EVAL);
return eval.isObject() && eval == val; return eval.isObject() && eval == val;
} }
@ -788,10 +788,6 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
{ {
RootedObject holder(cx, intrinsicsHolder()); 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(); uint32_t slot = holder->slotSpan();
RootedShape last(cx, holder->lastProperty()); RootedShape last(cx, holder->lastProperty());
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned()); Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
@ -801,7 +797,6 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
if (!shape) if (!shape)
return false; return false;
AutoLockForCompilation lock(cx);
if (!JSObject::setLastProperty(cx, holder, shape)) if (!JSObject::setLastProperty(cx, holder, shape))
return false; return false;

View File

@ -158,7 +158,7 @@ class GlobalObject : public JSObject
public: public:
Value getConstructor(JSProtoKey key) const { Value getConstructor(JSProtoKey key) const {
JS_ASSERT(key <= JSProto_LIMIT); 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 ensureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
static bool initConstructor(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 { Value getPrototype(JSProtoKey key) const {
JS_ASSERT(key <= JSProto_LIMIT); 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) { void setPrototype(JSProtoKey key, const Value &value) {
@ -457,19 +457,6 @@ class GlobalObject : public JSObject
return &self->getSlot(slot).toObject(); 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: public:
static JSObject *getOrCreateIteratorPrototype(JSContext *cx, static JSObject *getOrCreateIteratorPrototype(JSContext *cx,
Handle<GlobalObject*> global) Handle<GlobalObject*> global)
@ -547,18 +534,13 @@ class GlobalObject : public JSObject
} }
JSObject *intrinsicsHolder() { JSObject *intrinsicsHolder() {
JS_ASSERT(!getSlotForCompilation(INTRINSICS).isUndefined()); JS_ASSERT(!getSlot(INTRINSICS).isUndefined());
return &getSlotForCompilation(INTRINSICS).toObject(); return &getSlot(INTRINSICS).toObject();
} }
bool maybeGetIntrinsicValue(jsid id, Value *vp) { bool maybeGetIntrinsicValue(jsid id, Value *vp) {
JS_ASSERT(CurrentThreadCanReadCompilationData());
JSObject *holder = intrinsicsHolder(); JSObject *holder = intrinsicsHolder();
AutoThreadSafeAccess ts0(holder);
AutoThreadSafeAccess ts1(holder->lastProperty());
AutoThreadSafeAccess ts2(holder->lastProperty()->base());
if (Shape *shape = holder->nativeLookupPure(id)) { if (Shape *shape = holder->nativeLookupPure(id)) {
*vp = holder->getSlot(shape->slot()); *vp = holder->getSlot(shape->slot());
return true; return true;
@ -596,8 +578,7 @@ class GlobalObject : public JSObject
unsigned nargs, MutableHandleValue funVal); unsigned nargs, MutableHandleValue funVal);
RegExpStatics *getRegExpStatics() const { RegExpStatics *getRegExpStatics() const {
JSObject &resObj = getSlotForCompilation(REGEXP_STATICS).toObject(); JSObject &resObj = getSlot(REGEXP_STATICS).toObject();
AutoThreadSafeAccess ts(&resObj);
return static_cast<RegExpStatics *>(resObj.getPrivate(/* nfixed = */ 1)); return static_cast<RegExpStatics *>(resObj.getPrivate(/* nfixed = */ 1));
} }

View File

@ -1320,7 +1320,7 @@ SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, con
if ((uint32_t)i >= length) { if ((uint32_t)i >= length) {
// Annotate script if provided with information (e.g. baseline) // Annotate script if provided with information (e.g. baseline)
if (script && script->hasBaselineScript() && *pc == JSOP_SETELEM) if (script && script->hasBaselineScript() && *pc == JSOP_SETELEM)
script->baselineScript()->noteArrayWriteHole(cx, script->pcToOffset(pc)); script->baselineScript()->noteArrayWriteHole(script->pcToOffset(pc));
} }
} }
#endif #endif

View File

@ -334,25 +334,6 @@ js::ObjectImpl::nativeLookupPure(jsid id)
return Shape::searchNoHashify(lastProperty(), 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 uint32_t
js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class *clasp) js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class *clasp)
{ {

View File

@ -984,14 +984,12 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
public: public:
TaggedProto getTaggedProto() const { TaggedProto getTaggedProto() const {
AutoThreadSafeAccess ts(this);
return type_->proto(); return type_->proto();
} }
bool hasTenuredProto() const; bool hasTenuredProto() const;
const Class *getClass() const { const Class *getClass() const {
AutoThreadSafeAccess ts(this);
return type_->clasp(); return type_->clasp();
} }
@ -1206,8 +1204,6 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
} }
types::TypeObject *typeRaw() const { types::TypeObject *typeRaw() const {
AutoThreadSafeAccess ts0(this);
AutoThreadSafeAccess ts1(type_);
return type_; return type_;
} }
@ -1215,14 +1211,11 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
return reinterpret_cast<const shadow::Object *>(this)->numFixedSlots(); return reinterpret_cast<const shadow::Object *>(this)->numFixedSlots();
} }
uint32_t numFixedSlotsForCompilation() const;
/* /*
* Whether this is the only object which has its specified type. This * Whether this is the only object which has its specified type. This
* object will have its type constructed lazily as needed by analysis. * object will have its type constructed lazily as needed by analysis.
*/ */
bool hasSingletonType() const { bool hasSingletonType() const {
AutoThreadSafeAccess ts(this);
return !!type_->singleton(); return !!type_->singleton();
} }
@ -1231,7 +1224,6 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
* might have a lazy type, use getType() below, otherwise type(). * might have a lazy type, use getType() below, otherwise type().
*/ */
bool hasLazyType() const { bool hasLazyType() const {
AutoThreadSafeAccess ts(this);
return type_->lazy(); return type_->lazy();
} }
@ -1391,7 +1383,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
} }
const Value &getFixedSlot(uint32_t slot) const { const Value &getFixedSlot(uint32_t slot) const {
MOZ_ASSERT(slot < numFixedSlotsForCompilation()); MOZ_ASSERT(slot < numFixedSlots());
return fixedSlots()[slot]; return fixedSlots()[slot];
} }
@ -1478,7 +1470,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
* Private pointers are stored immediately after the last fixed slot of * Private pointers are stored immediately after the last fixed slot of
* the object. * the object.
*/ */
MOZ_ASSERT(nfixed == numFixedSlotsForCompilation()); MOZ_ASSERT(nfixed == numFixedSlots());
MOZ_ASSERT(hasPrivate()); MOZ_ASSERT(hasPrivate());
HeapSlot *end = &fixedSlots()[nfixed]; HeapSlot *end = &fixedSlots()[nfixed];
return *reinterpret_cast<void**>(end); return *reinterpret_cast<void**>(end);
@ -1555,10 +1547,6 @@ MOZ_ALWAYS_INLINE Zone *
BarrieredCell<ObjectImpl>::zoneFromAnyThread() const BarrieredCell<ObjectImpl>::zoneFromAnyThread() const
{ {
const ObjectImpl* obj = static_cast<const ObjectImpl*>(this); 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(); return obj->shape_->zoneFromAnyThread();
} }

View File

@ -80,9 +80,6 @@ PerThreadData::PerThreadData(JSRuntime *runtime)
#endif #endif
dtoaState(nullptr), dtoaState(nullptr),
suppressGC(0), suppressGC(0),
#ifdef DEBUG
ionCompiling(false),
#endif
activeCompilations(0) activeCompilations(0)
{} {}
@ -132,12 +129,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
exclusiveAccessOwner(nullptr), exclusiveAccessOwner(nullptr),
mainThreadHasExclusiveAccess(false), mainThreadHasExclusiveAccess(false),
numExclusiveThreads(0), numExclusiveThreads(0),
compilationLock(nullptr),
#ifdef DEBUG
compilationLockOwner(nullptr),
mainThreadHasCompilationLock(false),
#endif
numCompilationThreads(0),
#else #else
operationCallbackLockTaken(false), operationCallbackLockTaken(false),
#endif #endif
@ -280,7 +271,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
decimalSeparator(0), decimalSeparator(0),
numGrouping(0), numGrouping(0),
#endif #endif
heapProtected_(false),
mathCache_(nullptr), mathCache_(nullptr),
activeCompilations_(0), activeCompilations_(0),
keepAtoms_(0), keepAtoms_(0),
@ -360,10 +350,6 @@ JSRuntime::init(uint32_t maxbytes)
exclusiveAccessLock = PR_NewLock(); exclusiveAccessLock = PR_NewLock();
if (!exclusiveAccessLock) if (!exclusiveAccessLock)
return false; return false;
compilationLock = PR_NewLock();
if (!compilationLock)
return false;
#endif #endif
if (!mainThread.init()) if (!mainThread.init())
@ -495,10 +481,6 @@ JSRuntime::~JSRuntime()
JS_ASSERT(!numExclusiveThreads); JS_ASSERT(!numExclusiveThreads);
mainThreadHasExclusiveAccess = true; mainThreadHasExclusiveAccess = true;
JS_ASSERT(!compilationLockOwner);
if (compilationLock)
PR_DestroyLock(compilationLock);
JS_ASSERT(!operationCallbackOwner); JS_ASSERT(!operationCallbackOwner);
if (operationCallbackLock) if (operationCallbackLock)
PR_DestroyLock(operationCallbackLock); PR_DestroyLock(operationCallbackLock);
@ -859,76 +841,6 @@ JSRuntime::activeGCInAtomsZone()
return zone->needsBarrier() || zone->isGCScheduled() || zone->wasGCStarted(); 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 #ifdef JS_THREADSAFE
void void
@ -993,8 +905,6 @@ JSRuntime::assertCanLock(RuntimeLock which)
JS_ASSERT(exclusiveAccessOwner != PR_GetCurrentThread()); JS_ASSERT(exclusiveAccessOwner != PR_GetCurrentThread());
case WorkerThreadStateLock: case WorkerThreadStateLock:
JS_ASSERT(!WorkerThreadState().isLocked()); JS_ASSERT(!WorkerThreadState().isLocked());
case CompilationLock:
JS_ASSERT(compilationLockOwner != PR_GetCurrentThread());
case OperationCallbackLock: case OperationCallbackLock:
JS_ASSERT(!currentThreadOwnsOperationCallbackLock()); JS_ASSERT(!currentThreadOwnsOperationCallbackLock());
case GCLock: case GCLock:
@ -1006,64 +916,6 @@ JSRuntime::assertCanLock(RuntimeLock which)
#endif // JS_THREADSAFE #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 void
js::AssertCurrentThreadCanLock(RuntimeLock which) js::AssertCurrentThreadCanLock(RuntimeLock which)
{ {

View File

@ -483,7 +483,6 @@ AtomStateOffsetToName(const JSAtomState &atomState, size_t offset)
enum RuntimeLock { enum RuntimeLock {
ExclusiveAccessLock, ExclusiveAccessLock,
WorkerThreadStateLock, WorkerThreadStateLock,
CompilationLock,
OperationCallbackLock, OperationCallbackLock,
GCLock GCLock
}; };
@ -553,7 +552,6 @@ class PerThreadData : public PerThreadDataFriendFields
friend class js::jit::JitActivation; friend class js::jit::JitActivation;
friend class js::AsmJSActivation; friend class js::AsmJSActivation;
#ifdef DEBUG #ifdef DEBUG
friend bool js::CurrentThreadCanReadCompilationData();
friend void js::AssertCurrentThreadCanLock(RuntimeLock which); friend void js::AssertCurrentThreadCanLock(RuntimeLock which);
#endif #endif
@ -603,11 +601,6 @@ class PerThreadData : public PerThreadDataFriendFields
*/ */
int32_t suppressGC; int32_t suppressGC;
#ifdef DEBUG
// Whether this thread is actively Ion compiling.
bool ionCompiling;
#endif
// Number of active bytecode compilation on this thread. // Number of active bytecode compilation on this thread.
unsigned activeCompilations; unsigned activeCompilations;
@ -658,8 +651,6 @@ class MarkingValidator;
typedef Vector<JS::Zone *, 4, SystemAllocPolicy> ZoneVector; typedef Vector<JS::Zone *, 4, SystemAllocPolicy> ZoneVector;
class AutoLockForExclusiveAccess; class AutoLockForExclusiveAccess;
class AutoLockForCompilation;
class AutoProtectHeapForIonCompilation;
void RecomputeStackLimit(JSRuntime *rt, StackKind kind); void RecomputeStackLimit(JSRuntime *rt, StackKind kind);
@ -774,28 +765,6 @@ struct JSRuntime : public JS::shadow::Runtime,
friend class js::AutoLockForExclusiveAccess; 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: public:
void setUsedByExclusiveThread(JS::Zone *zone); void setUsedByExclusiveThread(JS::Zone *zone);
void clearUsedByExclusiveThread(JS::Zone *zone); void clearUsedByExclusiveThread(JS::Zone *zone);
@ -821,41 +790,6 @@ struct JSRuntime : public JS::shadow::Runtime,
#endif #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. */ /* Embedders can use this zone however they wish. */
JS::Zone *systemZone; JS::Zone *systemZone;
@ -1474,18 +1408,6 @@ struct JSRuntime : public JS::shadow::Runtime,
const char *numGrouping; const char *numGrouping;
#endif #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: private:
js::MathCache *mathCache_; js::MathCache *mathCache_;
js::MathCache *createMathCache(JSContext *cx); js::MathCache *createMathCache(JSContext *cx);
@ -2083,43 +2005,6 @@ class RuntimeAllocPolicy
extern const JSSecurityCallbacks NullSecurityCallbacks; 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 */ } /* namespace js */
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -76,10 +76,8 @@ StaticScopeIter<allowGC>::scopeShape() const
{ {
JS_ASSERT(hasDynamicScopeObject()); JS_ASSERT(hasDynamicScopeObject());
JS_ASSERT(type() != NAMED_LAMBDA); JS_ASSERT(type() != NAMED_LAMBDA);
if (type() == BLOCK) { if (type() == BLOCK)
AutoThreadSafeAccess ts(&block());
return block().lastProperty(); return block().lastProperty();
}
return funScript()->callObjShape(); return funScript()->callObjShape();
} }

View File

@ -200,7 +200,6 @@ class ScopeObject : public JSObject
* enclosing scope of a ScopeObject is necessarily non-null. * enclosing scope of a ScopeObject is necessarily non-null.
*/ */
inline JSObject &enclosingScope() const { inline JSObject &enclosingScope() const {
AutoThreadSafeAccess ts(this);
return getFixedSlot(SCOPE_CHAIN_SLOT).toObject(); return getFixedSlot(SCOPE_CHAIN_SLOT).toObject();
} }
@ -252,7 +251,6 @@ class CallObject : public ScopeObject
/* True if this is for a strict mode eval frame. */ /* True if this is for a strict mode eval frame. */
bool isForEval() const { bool isForEval() const {
AutoThreadSafeAccess ts(this);
JS_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull()); JS_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull());
JS_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(), JS_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(),
getFixedSlot(CALLEE_SLOT).toObject().is<JSFunction>()); getFixedSlot(CALLEE_SLOT).toObject().is<JSFunction>());
@ -264,7 +262,6 @@ class CallObject : public ScopeObject
* only be called if !isForEval.) * only be called if !isForEval.)
*/ */
JSFunction &callee() const { JSFunction &callee() const {
AutoThreadSafeAccess ts(this);
return getFixedSlot(CALLEE_SLOT).toObject().as<JSFunction>(); return getFixedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
} }
@ -410,7 +407,7 @@ class BlockObject : public NestedScopeObject
/* Return the number of variables associated with this block. */ /* Return the number of variables associated with this block. */
uint32_t slotCount() const { uint32_t slotCount() const {
return propertyCountForCompilation(); return propertyCount();
} }
/* /*
@ -464,9 +461,6 @@ class StaticBlockObject : public BlockObject
* variable of the block isAliased. * variable of the block isAliased.
*/ */
bool needsClone() { 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(); return !getFixedSlot(RESERVED_SLOTS).isFalse();
} }

View File

@ -1026,13 +1026,11 @@ class Shape : public gc::BarrieredCell<Shape>
void popFront() { void popFront() {
JS_ASSERT(!empty()); JS_ASSERT(!empty());
AutoThreadSafeAccess ts(cursor);
cursor = cursor->parent; cursor = cursor->parent;
} }
}; };
const Class *getObjectClass() const { const Class *getObjectClass() const {
AutoThreadSafeAccess ts(base());
return base()->clasp; return base()->clasp;
} }
JSObject *getObjectParent() const { return base()->parent; } JSObject *getObjectParent() const { return base()->parent; }
@ -1092,7 +1090,6 @@ class Shape : public gc::BarrieredCell<Shape>
}; };
bool inDictionary() const { bool inDictionary() const {
AutoThreadSafeAccess ts(this);
return (flags & IN_DICTIONARY) != 0; return (flags & IN_DICTIONARY) != 0;
} }
unsigned getFlags() const { return flags & PUBLIC_FLAGS; } unsigned getFlags() const { return flags & PUBLIC_FLAGS; }
@ -1158,20 +1155,14 @@ class Shape : public gc::BarrieredCell<Shape>
BaseShape *base() const { return base_.get(); } BaseShape *base() const { return base_.get(); }
bool hasSlot() const { bool hasSlot() const {
AutoThreadSafeAccess ts(this);
return (attrs & JSPROP_SHARED) == 0; return (attrs & JSPROP_SHARED) == 0;
} }
uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); } uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); }
uint32_t maybeSlot() const { 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; return slotInfo & SLOT_MASK;
} }
bool isEmptyShape() const { bool isEmptyShape() const {
AutoThreadSafeAccess ts(this);
JS_ASSERT_IF(JSID_IS_EMPTY(propid_), hasMissingSlot()); JS_ASSERT_IF(JSID_IS_EMPTY(propid_), hasMissingSlot());
return JSID_IS_EMPTY(propid_); return JSID_IS_EMPTY(propid_);
} }
@ -1193,8 +1184,6 @@ class Shape : public gc::BarrieredCell<Shape>
} }
uint32_t numFixedSlots() const { uint32_t numFixedSlots() const {
// Note: The same race applies here as in maybeSlot().
AutoThreadSafeAccess ts(this);
return (slotInfo >> FIXED_SLOTS_SHIFT); return (slotInfo >> FIXED_SLOTS_SHIFT);
} }
@ -1216,7 +1205,6 @@ class Shape : public gc::BarrieredCell<Shape>
} }
const EncapsulatedId &propid() const { const EncapsulatedId &propid() const {
AutoThreadSafeAccess ts(this);
JS_ASSERT(!isEmptyShape()); JS_ASSERT(!isEmptyShape());
JS_ASSERT(!JSID_IS_VOID(propid_)); JS_ASSERT(!JSID_IS_VOID(propid_));
return propid_; return propid_;
@ -1224,7 +1212,6 @@ class Shape : public gc::BarrieredCell<Shape>
EncapsulatedId &propidRef() { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; } EncapsulatedId &propidRef() { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
jsid propidRaw() const { jsid propidRaw() const {
// Return the actual jsid, not an internal reference. // Return the actual jsid, not an internal reference.
AutoThreadSafeAccess ts(this);
return propid(); return propid();
} }
@ -1241,8 +1228,6 @@ class Shape : public gc::BarrieredCell<Shape>
bool configurable() const { return (attrs & JSPROP_PERMANENT) == 0; } bool configurable() const { return (attrs & JSPROP_PERMANENT) == 0; }
bool enumerable() const { return (attrs & JSPROP_ENUMERATE) != 0; } bool enumerable() const { return (attrs & JSPROP_ENUMERATE) != 0; }
bool writable() const { bool writable() const {
// JS_ASSERT(isDataDescriptor());
AutoThreadSafeAccess ts(this);
return (attrs & JSPROP_READONLY) == 0; return (attrs & JSPROP_READONLY) == 0;
} }
bool hasGetterValue() const { return attrs & JSPROP_GETTER; } bool hasGetterValue() const { return attrs & JSPROP_GETTER; }
@ -1279,10 +1264,6 @@ class Shape : public gc::BarrieredCell<Shape>
uint32_t entryCount() { uint32_t entryCount() {
if (hasTable()) if (hasTable())
return table().entryCount; return table().entryCount;
return entryCountForCompilation();
}
uint32_t entryCountForCompilation() {
uint32_t count = 0; uint32_t count = 0;
for (Shape::Range<NoGC> r(this); !r.empty(); r.popFront()) for (Shape::Range<NoGC> r(this); !r.empty(); r.popFront())
++count; ++count;
@ -1649,7 +1630,6 @@ Shape::searchLinear(jsid id)
JS_ASSERT(!inDictionary()); JS_ASSERT(!inDictionary());
for (Shape *shape = this; shape; ) { for (Shape *shape = this; shape; ) {
AutoThreadSafeAccess ts(shape);
if (shape->propidRef() == id) if (shape->propidRef() == id)
return shape; return shape;
shape = shape->parent; shape = shape->parent;

View File

@ -382,7 +382,6 @@ class JSString : public js::gc::BarrieredCell<JSString>
MOZ_ALWAYS_INLINE MOZ_ALWAYS_INLINE
JSAtom &asAtom() const { JSAtom &asAtom() const {
js::AutoThreadSafeAccess ts(this);
JS_ASSERT(isAtom()); JS_ASSERT(isAtom());
return *(JSAtom *)this; return *(JSAtom *)this;
} }
@ -1015,7 +1014,6 @@ JSString::base() const
inline js::PropertyName * inline js::PropertyName *
JSAtom::asPropertyName() JSAtom::asPropertyName()
{ {
js::AutoThreadSafeAccess ts(this);
#ifdef DEBUG #ifdef DEBUG
uint32_t dummy; uint32_t dummy;
JS_ASSERT(!isIndex(&dummy)); JS_ASSERT(!isIndex(&dummy));

View File

@ -1195,8 +1195,6 @@ TypedArrayObject::isArrayIndex(jsid id, uint32_t *ip)
void void
TypedArrayObject::neuter(JSContext *cx) TypedArrayObject::neuter(JSContext *cx)
{ {
AutoLockForCompilation lock(cx);
setSlot(LENGTH_SLOT, Int32Value(0)); setSlot(LENGTH_SLOT, Int32Value(0));
setSlot(BYTELENGTH_SLOT, Int32Value(0)); setSlot(BYTELENGTH_SLOT, Int32Value(0));
setSlot(BYTEOFFSET_SLOT, Int32Value(0)); setSlot(BYTEOFFSET_SLOT, Int32Value(0));

View File

@ -311,11 +311,9 @@ class TypedArrayObject : public ArrayBufferViewObject
return tarr->getFixedSlot(BYTEOFFSET_SLOT); return tarr->getFixedSlot(BYTEOFFSET_SLOT);
} }
static Value byteLengthValue(TypedArrayObject *tarr) { static Value byteLengthValue(TypedArrayObject *tarr) {
AutoThreadSafeAccess ts(tarr);
return tarr->getFixedSlot(BYTELENGTH_SLOT); return tarr->getFixedSlot(BYTELENGTH_SLOT);
} }
static Value lengthValue(TypedArrayObject *tarr) { static Value lengthValue(TypedArrayObject *tarr) {
AutoThreadSafeAccess ts(tarr);
return tarr->getFixedSlot(LENGTH_SLOT); return tarr->getFixedSlot(LENGTH_SLOT);
} }
@ -333,11 +331,9 @@ class TypedArrayObject : public ArrayBufferViewObject
} }
uint32_t type() const { uint32_t type() const {
AutoThreadSafeAccess ts(this);
return getFixedSlot(TYPE_SLOT).toInt32(); return getFixedSlot(TYPE_SLOT).toInt32();
} }
void *viewData() const { void *viewData() const {
AutoThreadSafeAccess ts(this);
return static_cast<void*>(getPrivate(DATA_SLOT)); return static_cast<void*>(getPrivate(DATA_SLOT));
} }

View File

@ -177,8 +177,10 @@ CacheFile::~CacheFile()
LOG(("CacheFile::~CacheFile() [this=%p]", this)); LOG(("CacheFile::~CacheFile() [this=%p]", this));
MutexAutoLock lock(mLock); MutexAutoLock lock(mLock);
if (!mMemoryOnly) if (!mMemoryOnly && mReady) {
// mReady flag indicates we have metadata plus in a valid state.
WriteMetadataIfNeededLocked(true); WriteMetadataIfNeededLocked(true);
}
} }
nsresult nsresult
@ -1335,6 +1337,11 @@ CacheFile::WriteMetadataIfNeededLocked(bool aFireAndForget)
AssertOwnsLock(); AssertOwnsLock();
MOZ_ASSERT(!mMemoryOnly); MOZ_ASSERT(!mMemoryOnly);
if (!mMetadata) {
MOZ_CRASH("Must have metadata here");
return;
}
if (!aFireAndForget) { if (!aFireAndForget) {
// if aFireAndForget is set, we are called from dtor. Write // if aFireAndForget is set, we are called from dtor. Write
// scheduler hard-refers CacheFile otherwise, so we cannot be here. // scheduler hard-refers CacheFile otherwise, so we cannot be here.

View File

@ -916,7 +916,12 @@ CacheFileIOManager::OnProfile()
{ {
LOG(("CacheFileIOManager::OnProfile() [gInstance=%p]", gInstance)); 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; nsresult rv;
@ -941,10 +946,10 @@ CacheFileIOManager::OnProfile()
} }
if (directory) { if (directory) {
rv = directory->Clone(getter_AddRefs(gInstance->mCacheDirectory)); rv = directory->Clone(getter_AddRefs(ioMan->mCacheDirectory));
NS_ENSURE_SUCCESS(rv, rv); 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); NS_ENSURE_SUCCESS(rv, rv);
} }

View File

@ -13,7 +13,10 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
EXPORT_LIBRARY = True EXPORT_LIBRARY = True
FORCE_STATIC_LIB = True FORCE_STATIC_LIB = True
DIRS += ['win/src/sandboxbroker'] DIRS += [
'win/src/sandboxbroker',
'win/src/sandboxtarget',
]
SOURCES += [ SOURCES += [
'chromium/base/at_exit.cc', 'chromium/base/at_exit.cc',

View File

@ -23,16 +23,26 @@ SandboxBroker::SandboxBroker()
sBrokerService = nullptr; 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 bool
SandboxBroker::LaunchApp(const wchar_t *aPath, SandboxBroker::LaunchApp(const wchar_t *aPath,
const wchar_t *aArguments, const wchar_t *aArguments,
void **aProcessHandle) void **aProcessHandle)
{ {
// If the broker service isn't already initialized, do it now // If the broker service isn't already initialized, do it now
if (!sBrokerService) { if (!sBrokerService || !mPolicy) {
return false; return false;
} }
@ -40,16 +50,15 @@ SandboxBroker::LaunchApp(const wchar_t *aPath,
// Medium integrity, unrestricted, in the same window station, within the // Medium integrity, unrestricted, in the same window station, within the
// same desktop, and has no job object. // same desktop, and has no job object.
// We'll start to increase the restrictions over time. // We'll start to increase the restrictions over time.
sandbox::TargetPolicy *policy = sBrokerService->CreatePolicy(); mPolicy->SetJobLevel(sandbox::JOB_NONE, 0);
policy->SetJobLevel(sandbox::JOB_NONE, 0); mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, sandbox::USER_RESTRICTED_SAME_ACCESS);
sandbox::USER_RESTRICTED_SAME_ACCESS); mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_MEDIUM);
// Ceate the sandboxed process // Ceate the sandboxed process
PROCESS_INFORMATION targetInfo; PROCESS_INFORMATION targetInfo;
sandbox::ResultCode result; 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 // The sandboxed process is started in a suspended state, resumeit now that
// we'eve set things up. // we'eve set things up.
@ -59,13 +68,15 @@ SandboxBroker::LaunchApp(const wchar_t *aPath,
// Return the process handle to the caller // Return the process handle to the caller
*aProcessHandle = targetInfo.hProcess; *aProcessHandle = targetInfo.hProcess;
policy->Release();
return true; return true;
} }
SandboxBroker::~SandboxBroker() SandboxBroker::~SandboxBroker()
{ {
if (mPolicy) {
mPolicy->Release();
mPolicy = nullptr;
}
} }
} }

View File

@ -15,6 +15,7 @@
namespace sandbox { namespace sandbox {
class BrokerServices; class BrokerServices;
class TargetPolicy;
} }
namespace mozilla { namespace mozilla {
@ -23,12 +24,14 @@ class SANDBOX_EXPORT SandboxBroker
{ {
public: public:
SandboxBroker(); SandboxBroker();
bool AllowPipe(const wchar_t *aPath);
bool LaunchApp(const wchar_t *aPath, const wchar_t *aArguments, bool LaunchApp(const wchar_t *aPath, const wchar_t *aArguments,
void **aProcessHandle); void **aProcessHandle);
virtual ~SandboxBroker(); virtual ~SandboxBroker();
private: private:
static sandbox::BrokerServices *sBrokerService; static sandbox::BrokerServices *sBrokerService;
sandbox::TargetPolicy *mPolicy;
}; };
} // mozilla } // mozilla

View 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',
]

View 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

View File

@ -99,10 +99,11 @@ this.BookmarkJSONUtils = Object.freeze({
Components.utils.reportError("Unable to report telemetry."); Components.utils.reportError("Unable to report telemetry.");
} }
// Write to the temp folder first, to avoid leaving back partial files. // Do not write to the tmp folder, otherwise if it has a different
let tmpPath = OS.Path.join(OS.Constants.Path.tmpDir, // filesystem writeAtomic will fail. Eventual dangling .tmp files should
OS.Path.basename(aFilePath) + ".tmp"); // be cleaned up by the caller.
yield OS.File.writeAtomic(aFilePath, jsonString, { tmpPath: tmpPath }); yield OS.File.writeAtomic(aFilePath, jsonString,
{ tmpPath: OS.Path.join(aFilePath + ".tmp") });
return count; return count;
}); });
}, },

View File

@ -132,6 +132,13 @@ this.PlacesBackups = {
let backupFolderPath = yield this.getBackupFolder(); let backupFolderPath = yield this.getBackupFolder();
let iterator = new OS.File.DirectoryIterator(backupFolderPath); let iterator = new OS.File.DirectoryIterator(backupFolderPath);
yield iterator.forEach(function(aEntry) { 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); let matches = aEntry.name.match(this._filenamesRegex);
if (matches) { if (matches) {
// Remove bogus backups in future dates. // Remove bogus backups in future dates.