mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:37:11 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1274192 part 1 - make the MediaDecoderReaderWrapper as a proxy of WaitForData(); r=jwwang (9debdca9a9) - Bug 1274192 part 2 - make MDSM and SeekTask to adopt new MediaDecoderReaderWrapper API; r=jwwang (156f924dc9) - Bug 1276495: Don't reset audio promises for video only seek. r=jwwang,jya (c4632c7ff6) - Bug 1276318, part 1 - Fix leading tabs in ipc/glue. r=billm (46bcc4ccb3) - Bug 1035125 Part 6: Take Chromium commit 3181ba39ee787e1b40f4aea4be23f4f666ad0945 to add Windows 10 version to enumeration. r=aklotz (af62c8065f) - Bug 1270752 - Fix lifetime of buffer passed to PR_SetEnv(). r=jduell (bfce06ebea) - Bug 1275117 - Fix static strings leaks when mozlogging is on. r=jduell (8e9066c5d7) - Bug 1273048 - Add MOZ_GCC_VERSION_AT_MOST macro. r=froydnj (cfb5acdbe6) - Bug 1269968 - Remove unnecessary deduction on RefPtr.h. r=froydnj (30cf9bbf47) - Bug 525063 - add attribute to mark member variables that should be skipped by clang plugin initialization checker. r=nfroyd (78aa863f88) - Bug 1278391 - add move constructor to EnumeratedArray (r=njn) (5effe4e473) - Bug 1268518: Update basic-integer tests for rotations + clean up; r=sunfish (46827b6211) - Bug 1270370 - Part 1: Move SetIteratorObject to MapObject.h; r=jorendorff (01a27fbd50) - Bug 1270370 - Part 2: Expose MapIterator and SetIterator through ESClassValues; r=jorendorff (3edb3c7551) - Bug 1267551 (part 3) - Use MOZ_MUST_USE more in js/src/builtin/. r=jonco. (ea96d0fae0) - Bug 1267551 (part 4) - Use MOZ_MUST_USE more in js/src/asmjs/. r=bbouvier. (3e622c736d) - Bug 1268910: Refactor WebAssembly trap handling; r=luke (b59394a287) - Bug 1268910: Trap on edge cases for integer div/mod; r=sunfish (3d85230cc8) - Bug 1267551 (part 5) - Use MOZ_MUST_USE more in js/src/ctypes/. r=sfink. (e6580fb645) - Bug 1267551 (part 6) - Remove dead GenerateBlockId declaration. r=jorendorff. (74afcc549e) - Bug 1240072 - Add public JS APIs related to modules r=shu Bug 1267551 (part 7) - Use MOZ_MUST_USE more in js/src/frontend/. r=jorendorff. (5275c57768) - Bug 1267551 (part 8) - Use MOZ_MUST_USE more in js/src/gc/. r=terrence. (2572cc1c58) - Bug 1261063 - Part 1 - Remove public Telemetry functions that return raw histogram instances. r=chutten (3a68653c8f) - Bug 1261063 - Part 2 - Expose C++ function to clear Telemetry histograms. r=chutten (1f42f6aa1e) - Bug 1261063 - Part 3 - Make RasterImage use the public Telemetry API. r=tnikkel (0f564f3836) - Bug 1261063 - Part 4 - Use a count histogram for WebRTC call counts. r=jesup (b6b7b649e0) - Bug 1270073 - Point to Telemetry documentation in Telemetry.h. r=chutten (517279b284) - Bug 1261052 - Move C++ histogram implementation code into a separate module. r=gfritzsche. (66bcb1e167) - Bug 1145164 - Allow non-unitary increments to count histograms. r=gfritzsche (507e076e28) - Bug 1173447 - Add test for incremental pre-barriers when storing things under roots, r=jonco (caf8bd16be) - Bug 1267551 (part 10) - Use MOZ_MUST_USE in AutoVectorRooterBase. r=terrence. (2c5ed87a9f) - This catches a missing check. (b2fcd30fc5) - Bug 1267551 (part 11b) - Follow-up to fix Android bustage. r=me (f464ca7b98) - Bug 1271854 - Part 1: Allow specifying multiple GC zeal levels; r=terrence (da3c3e1281) - Bug 1271854 - Part 2: Allow specifying zeal modes by name as well; r=terrence (f63926e45b) - Bug 1271854 - Part 3: Avoid saving the GC zeal string inside the JS shell; r=terrence (f09b262e55) - Bug 1270062 - Unbust Windows full duplex. a=Tomcat (3c8b5887b6) - Bug 1270062 - Update libcubeb. rs=jesup (71805cb0e0) - Bug 1270004 - Update libcubeb. rs=jesup (2d90b9662f) - Bug 1280280 - Update cubeb to 073c9f011114. r=kinetik (6bee6a7f21) - Bug 1280280 - Update media/libcube/update.sh to add cubeb_jack.cpp, and sort the list of files. r=kinetik (430b7533c4) - Bug 1272604 - Add a zeal mode to check the heap after a moving GC r=terrence (85c018d71f) - Bug 1272604 - Fix bad implicit conversion constructor build error r=me (5c4e1dbc44) - Bug 1272604 - Fix hazard analysis failure r=me (0591aa2dca) - Bug 1232417 - Use a Variant to represent the CrossCompartmentWrapperMap key; r=jonco (512da0bab3) - Bug 1269928 - Fold DirectProxyHandler into Wrapper, which is now its only (non-test) consumer. r=efaust (7c6bb6e898) - Bug 1273639 - Add a nonunified spidermonkey build, r=terrence (d6fa13545c) - Bug 1273639 - Fix nonunified spidermonkey builds, r=terrence (3e0544510d) - Bug 1273180 - Trigger major GC if necessary after minor GC r=terrence (a9a9be8b17) - Bug 1268992 - Assert that the heap is empty after a shutdown GC; r=jonco (fe3ac5bdd6) - Bug 1273908 - Refactor GC to make it easier to add new kinds of GC thing r=terrence (51c92e1b05)
This commit is contained in:
@@ -1081,7 +1081,9 @@ nsOuterWindowProxy::AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
|
||||
return false;
|
||||
}
|
||||
for (int32_t i = 0; i < int32_t(length); ++i) {
|
||||
props.append(INT_TO_JSID(i));
|
||||
if (!props.append(INT_TO_JSID(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
IMPL_EVENT_HANDLER(load)
|
||||
IMPL_EVENT_HANDLER(timeout)
|
||||
IMPL_EVENT_HANDLER(loadend)
|
||||
|
||||
|
||||
virtual void DisconnectFromOwner() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -3149,9 +3149,15 @@ ForEachHandler(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
|
||||
JS::AutoValueVector newArgs(aCx);
|
||||
// Arguments are passed in as value, key, object. Keep value and key, replace
|
||||
// object with the maplike/setlike object.
|
||||
newArgs.append(args.get(0));
|
||||
newArgs.append(args.get(1));
|
||||
newArgs.append(maplikeOrSetlikeObj);
|
||||
if (!newArgs.append(args.get(0))) {
|
||||
return false;
|
||||
}
|
||||
if (!newArgs.append(args.get(1))) {
|
||||
return false;
|
||||
}
|
||||
if (!newArgs.append(maplikeOrSetlikeObj)) {
|
||||
return false;
|
||||
}
|
||||
JS::Rooted<JS::Value> rval(aCx, JS::UndefinedValue());
|
||||
// Now actually call the user specified callback
|
||||
return JS::Call(aCx, args.thisv(), callbackFn, newArgs, &rval);
|
||||
|
||||
@@ -146,6 +146,8 @@ MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(bool aIsRealTime,
|
||||
, mReader(aReader)
|
||||
, mAudioCallbackID("AudioCallbackID")
|
||||
, mVideoCallbackID("VideoCallbackID")
|
||||
, mWaitAudioCallbackID("WaitAudioCallbackID")
|
||||
, mWaitVideoCallbackID("WaitVideoCallbackID")
|
||||
{}
|
||||
|
||||
MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
|
||||
@@ -198,6 +200,24 @@ MediaDecoderReaderWrapper::CancelVideoCallback(CallbackID aID)
|
||||
mRequestVideoDataCB = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderReaderWrapper::CancelWaitAudioCallback(CallbackID aID)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(aID == mWaitAudioCallbackID);
|
||||
++mWaitAudioCallbackID;
|
||||
mWaitAudioDataCB = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderReaderWrapper::CancelWaitVideoCallback(CallbackID aID)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(aID == mWaitVideoCallbackID);
|
||||
++mWaitVideoCallbackID;
|
||||
mWaitVideoDataCB = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderReaderWrapper::RequestAudioData()
|
||||
{
|
||||
@@ -285,6 +305,20 @@ MediaDecoderReaderWrapper::IsRequestingVideoData() const
|
||||
return mVideoDataRequest.Exists();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderReaderWrapper::IsWaitingAudioData() const
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
return mAudioWaitRequest.Exists();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderReaderWrapper::IsWaitingVideoData() const
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
return mVideoWaitRequest.Exists();
|
||||
}
|
||||
|
||||
RefPtr<MediaDecoderReader::SeekPromise>
|
||||
MediaDecoderReaderWrapper::Seek(SeekTarget aTarget, media::TimeUnit aEndTime)
|
||||
{
|
||||
@@ -295,12 +329,41 @@ MediaDecoderReaderWrapper::Seek(SeekTarget aTarget, media::TimeUnit aEndTime)
|
||||
aEndTime.ToMicroseconds());
|
||||
}
|
||||
|
||||
RefPtr<MediaDecoderReaderWrapper::WaitForDataPromise>
|
||||
void
|
||||
MediaDecoderReaderWrapper::WaitForData(MediaData::Type aType)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::WaitForData, aType);
|
||||
MOZ_ASSERT(WaitCallbackRef(aType));
|
||||
|
||||
auto p = InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::WaitForData, aType);
|
||||
|
||||
RefPtr<MediaDecoderReaderWrapper> self = this;
|
||||
WaitRequestRef(aType).Begin(p->Then(mOwnerThread, __func__,
|
||||
[self] (MediaData::Type aType) {
|
||||
MOZ_ASSERT(self->WaitCallbackRef(aType));
|
||||
self->WaitRequestRef(aType).Complete();
|
||||
self->WaitCallbackRef(aType)->OnResolved(aType);
|
||||
},
|
||||
[self, aType] (WaitForDataRejectValue aRejection) {
|
||||
MOZ_ASSERT(self->WaitCallbackRef(aType));
|
||||
self->WaitRequestRef(aType).Complete();
|
||||
self->WaitCallbackRef(aType)->OnRejected(aRejection);
|
||||
}));
|
||||
}
|
||||
|
||||
UniquePtr<MediaDecoderReaderWrapper::WaitForDataCallbackBase>&
|
||||
MediaDecoderReaderWrapper::WaitCallbackRef(MediaData::Type aType)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
return aType == MediaData::AUDIO_DATA ? mWaitAudioDataCB : mWaitVideoDataCB;
|
||||
}
|
||||
|
||||
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>&
|
||||
MediaDecoderReaderWrapper::WaitRequestRef(MediaData::Type aType)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
|
||||
}
|
||||
|
||||
RefPtr<MediaDecoderReaderWrapper::BufferedUpdatePromise>
|
||||
@@ -334,8 +397,12 @@ MediaDecoderReaderWrapper::ResetDecode(TargetQueues aQueues)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
mAudioDataRequest.DisconnectIfExists();
|
||||
if (aQueues == MediaDecoderReader::AUDIO_VIDEO) {
|
||||
mAudioDataRequest.DisconnectIfExists();
|
||||
mAudioWaitRequest.DisconnectIfExists();
|
||||
}
|
||||
mVideoDataRequest.DisconnectIfExists();
|
||||
mVideoWaitRequest.DisconnectIfExists();
|
||||
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NewRunnableMethod<TargetQueues>(mReader,
|
||||
|
||||
@@ -164,6 +164,58 @@ class MediaDecoderReaderWrapper {
|
||||
RejectFunctionType mRejectFunction;
|
||||
};
|
||||
|
||||
struct WaitForDataCallbackBase
|
||||
{
|
||||
virtual ~WaitForDataCallbackBase() {}
|
||||
virtual void OnResolved(MediaData::Type aType) = 0;
|
||||
virtual void OnRejected(WaitForDataRejectValue aRejection) = 0;
|
||||
};
|
||||
|
||||
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
|
||||
struct WaitForDataMethodCallback : public WaitForDataCallbackBase
|
||||
{
|
||||
WaitForDataMethodCallback(ThisType* aThis, ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
|
||||
: mThis(aThis), mResolveMethod(aResolveMethod), mRejectMethod(aRejectMethod)
|
||||
{
|
||||
}
|
||||
|
||||
void OnResolved(MediaData::Type aType) override
|
||||
{
|
||||
(mThis->*mResolveMethod)(aType);
|
||||
}
|
||||
|
||||
void OnRejected(WaitForDataRejectValue aRejection) override
|
||||
{
|
||||
(mThis->*mRejectMethod)(aRejection);
|
||||
}
|
||||
|
||||
RefPtr<ThisType> mThis;
|
||||
ResolveMethodType mResolveMethod;
|
||||
RejectMethodType mRejectMethod;
|
||||
};
|
||||
|
||||
template<typename ResolveFunctionType, typename RejectFunctionType>
|
||||
struct WaitForDataFunctionCallback : public WaitForDataCallbackBase
|
||||
{
|
||||
WaitForDataFunctionCallback(ResolveFunctionType&& aResolveFuntion, RejectFunctionType&& aRejectFunction)
|
||||
: mResolveFuntion(Move(aResolveFuntion)), mRejectFunction(Move(aRejectFunction))
|
||||
{
|
||||
}
|
||||
|
||||
void OnResolved(MediaData::Type aType) override
|
||||
{
|
||||
mResolveFuntion(aType);
|
||||
}
|
||||
|
||||
void OnRejected(WaitForDataRejectValue aRejection) override
|
||||
{
|
||||
mRejectFunction(aRejection);
|
||||
}
|
||||
|
||||
ResolveFunctionType mResolveFuntion;
|
||||
RejectFunctionType mRejectFunction;
|
||||
};
|
||||
|
||||
public:
|
||||
MediaDecoderReaderWrapper(bool aIsRealTime,
|
||||
AbstractThread* aOwnerThread,
|
||||
@@ -239,18 +291,90 @@ public:
|
||||
return mVideoCallbackID;
|
||||
}
|
||||
|
||||
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
|
||||
CallbackID
|
||||
SetWaitAudioCallback(ThisType* aThisVal,
|
||||
ResolveMethodType aResolveMethod,
|
||||
RejectMethodType aRejectMethod)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mWaitAudioDataCB,
|
||||
"Please cancel the original callback before setting a new one.");
|
||||
|
||||
mWaitAudioDataCB.reset(
|
||||
new WaitForDataMethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
|
||||
aThisVal, aResolveMethod, aRejectMethod));
|
||||
|
||||
return mWaitAudioCallbackID;
|
||||
}
|
||||
|
||||
template<typename ResolveFunction, typename RejectFunction>
|
||||
CallbackID
|
||||
SetWaitAudioCallback(ResolveFunction&& aResolveFunction,
|
||||
RejectFunction&& aRejectFunction)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mWaitAudioDataCB,
|
||||
"Please cancel the original callback before setting a new one.");
|
||||
|
||||
mWaitAudioDataCB.reset(
|
||||
new WaitForDataFunctionCallback<ResolveFunction, RejectFunction>(
|
||||
Move(aResolveFunction), Move(aRejectFunction)));
|
||||
|
||||
return mWaitAudioCallbackID;
|
||||
}
|
||||
|
||||
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
|
||||
CallbackID
|
||||
SetWaitVideoCallback(ThisType* aThisVal,
|
||||
ResolveMethodType aResolveMethod,
|
||||
RejectMethodType aRejectMethod)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mWaitVideoDataCB,
|
||||
"Please cancel the original callback before setting a new one.");
|
||||
|
||||
mWaitVideoDataCB.reset(
|
||||
new WaitForDataMethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
|
||||
aThisVal, aResolveMethod, aRejectMethod));
|
||||
|
||||
return mWaitVideoCallbackID;
|
||||
}
|
||||
|
||||
template<typename ResolveFunction, typename RejectFunction>
|
||||
CallbackID
|
||||
SetWaitVideoCallback(ResolveFunction&& aResolveFunction,
|
||||
RejectFunction&& aRejectFunction)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(!mWaitVideoDataCB,
|
||||
"Please cancel the original callback before setting a new one.");
|
||||
|
||||
mWaitVideoDataCB.reset(
|
||||
new WaitForDataFunctionCallback<ResolveFunction, RejectFunction>(
|
||||
Move(aResolveFunction), Move(aRejectFunction)));
|
||||
|
||||
return mWaitVideoCallbackID;
|
||||
}
|
||||
|
||||
void CancelAudioCallback(CallbackID aID);
|
||||
void CancelVideoCallback(CallbackID aID);
|
||||
void CancelWaitAudioCallback(CallbackID aID);
|
||||
void CancelWaitVideoCallback(CallbackID aID);
|
||||
|
||||
// NOTE: please set callbacks before requesting audio/video data!
|
||||
void RequestAudioData();
|
||||
void RequestVideoData(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);
|
||||
|
||||
// NOTE: please set callbacks before invoking WaitForData()!
|
||||
void WaitForData(MediaData::Type aType);
|
||||
|
||||
bool IsRequestingAudioData() const;
|
||||
bool IsRequestingVideoData() const;
|
||||
bool IsWaitingAudioData() const;
|
||||
bool IsWaitingVideoData() const;
|
||||
|
||||
RefPtr<SeekPromise> Seek(SeekTarget aTarget, media::TimeUnit aEndTime);
|
||||
RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType);
|
||||
RefPtr<BufferedUpdatePromise> UpdateBufferedWithPromise();
|
||||
RefPtr<ShutdownPromise> Shutdown();
|
||||
|
||||
@@ -306,6 +430,9 @@ private:
|
||||
void OnNotDecoded(CallbackBase* aCallback,
|
||||
MediaDecoderReader::NotDecodedReason aReason);
|
||||
|
||||
UniquePtr<WaitForDataCallbackBase>& WaitCallbackRef(MediaData::Type aType);
|
||||
MozPromiseRequestHolder<WaitForDataPromise>& WaitRequestRef(MediaData::Type aType);
|
||||
|
||||
const bool mForceZeroStartTime;
|
||||
const RefPtr<AbstractThread> mOwnerThread;
|
||||
const RefPtr<MediaDecoderReader> mReader;
|
||||
@@ -315,14 +442,20 @@ private:
|
||||
|
||||
UniquePtr<CallbackBase> mRequestAudioDataCB;
|
||||
UniquePtr<CallbackBase> mRequestVideoDataCB;
|
||||
UniquePtr<WaitForDataCallbackBase> mWaitAudioDataCB;
|
||||
UniquePtr<WaitForDataCallbackBase> mWaitVideoDataCB;
|
||||
MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
|
||||
MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest;
|
||||
MozPromiseRequestHolder<WaitForDataPromise> mAudioWaitRequest;
|
||||
MozPromiseRequestHolder<WaitForDataPromise> mVideoWaitRequest;
|
||||
|
||||
/*
|
||||
* These callback ids are used to prevent mis-canceling callback.
|
||||
*/
|
||||
CallbackID mAudioCallbackID;
|
||||
CallbackID mVideoCallbackID;
|
||||
CallbackID mWaitAudioCallbackID;
|
||||
CallbackID mWaitVideoCallbackID;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -696,21 +696,7 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
|
||||
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
|
||||
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
|
||||
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
|
||||
RefPtr<MediaDecoderStateMachine> self = this;
|
||||
WaitRequestRef(aType).Begin(
|
||||
mReader->WaitForData(aType)
|
||||
->Then(OwnerThread(), __func__,
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
self->WaitRequestRef(aType).Complete();
|
||||
if (aType == MediaData::AUDIO_DATA) {
|
||||
self->EnsureAudioDecodeTaskQueued();
|
||||
} else {
|
||||
self->EnsureVideoDecodeTaskQueued();
|
||||
}
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {
|
||||
self->WaitRequestRef(aRejection.mType).Complete();
|
||||
}));
|
||||
mReader->WaitForData(aType);
|
||||
|
||||
// We are out of data to decode and will enter buffering mode soon.
|
||||
// We want to play the frames we have already decoded, so we stop pre-rolling
|
||||
@@ -939,8 +925,25 @@ MediaDecoderStateMachine::SetMediaDecoderReaderWrapperCallback()
|
||||
&MediaDecoderStateMachine::OnVideoDecoded,
|
||||
&MediaDecoderStateMachine::OnVideoNotDecoded);
|
||||
|
||||
RefPtr<MediaDecoderStateMachine> self = this;
|
||||
mWaitAudioCallbackID =
|
||||
mReader->SetWaitAudioCallback(
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
self->EnsureAudioDecodeTaskQueued();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {});
|
||||
|
||||
mWaitVideoCallbackID =
|
||||
mReader->SetWaitVideoCallback(
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
self->EnsureVideoDecodeTaskQueued();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {});
|
||||
|
||||
DECODER_LOG("MDSM set audio callbacks: mAudioCallbackID = %d\n", (int)mAudioCallbackID);
|
||||
DECODER_LOG("MDSM set video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
|
||||
DECODER_LOG("MDSM set wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
|
||||
DECODER_LOG("MDSM set wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -951,6 +954,12 @@ MediaDecoderStateMachine::CancelMediaDecoderReaderWrapperCallback()
|
||||
|
||||
DECODER_LOG("MDSM cancel video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
|
||||
mReader->CancelVideoCallback(mVideoCallbackID);
|
||||
|
||||
DECODER_LOG("MDSM cancel wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
|
||||
mReader->CancelWaitAudioCallback(mWaitAudioCallbackID);
|
||||
|
||||
DECODER_LOG("MDSM cancel wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
|
||||
mReader->CancelWaitVideoCallback(mWaitVideoCallbackID);
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::StopPlayback()
|
||||
@@ -1016,8 +1025,8 @@ MediaDecoderStateMachine::MaybeStartBuffering()
|
||||
(JustExitedQuickBuffering() || HasLowUndecodedData());
|
||||
} else {
|
||||
MOZ_ASSERT(mReader->IsWaitForDataSupported());
|
||||
shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) ||
|
||||
(OutOfDecodedVideo() && mVideoWaitRequest.Exists());
|
||||
shouldBuffer = (OutOfDecodedAudio() && mReader->IsWaitingAudioData()) ||
|
||||
(OutOfDecodedVideo() && mReader->IsWaitingVideoData());
|
||||
}
|
||||
if (shouldBuffer) {
|
||||
StartBuffering();
|
||||
@@ -1277,8 +1286,8 @@ void MediaDecoderStateMachine::StartDecoding()
|
||||
}
|
||||
|
||||
// Reset other state to pristine values before starting decode.
|
||||
mIsAudioPrerolling = !DonePrerollingAudio() && !mAudioWaitRequest.Exists();
|
||||
mIsVideoPrerolling = !DonePrerollingVideo() && !mVideoWaitRequest.Exists();
|
||||
mIsAudioPrerolling = !DonePrerollingAudio() && !mReader->IsWaitingAudioData();
|
||||
mIsVideoPrerolling = !DonePrerollingVideo() && !mReader->IsWaitingVideoData();
|
||||
|
||||
// Ensure that we've got tasks enqueued to decode data if we need to.
|
||||
DispatchDecodeTasksIfNeeded();
|
||||
@@ -1707,7 +1716,7 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
|
||||
}
|
||||
|
||||
if (!IsAudioDecoding() || mReader->IsRequestingAudioData() ||
|
||||
mAudioWaitRequest.Exists()) {
|
||||
mReader->IsWaitingAudioData()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1765,7 +1774,7 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
|
||||
}
|
||||
|
||||
if (!IsVideoDecoding() || mReader->IsRequestingVideoData() ||
|
||||
mVideoWaitRequest.Exists()) {
|
||||
mReader->IsWaitingVideoData()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -2276,8 +2285,8 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
|
||||
"Don't yet have a strategy for non-heuristic + non-WaitForData");
|
||||
DispatchDecodeTasksIfNeeded();
|
||||
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mAudioWaitRequest.Exists());
|
||||
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mReader->IsRequestingVideoData() || mVideoWaitRequest.Exists());
|
||||
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mReader->IsWaitingAudioData());
|
||||
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mReader->IsRequestingVideoData() || mReader->IsWaitingVideoData());
|
||||
DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
|
||||
"mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
|
||||
OutOfDecodedAudio(), AudioRequestStatus(),
|
||||
@@ -2362,7 +2371,6 @@ MediaDecoderStateMachine::Reset(MediaDecoderReader::TargetQueues aQueues /*= AUD
|
||||
mDecodedVideoEndTime = 0;
|
||||
mVideoCompleted = false;
|
||||
VideoQueue().Reset();
|
||||
mVideoWaitRequest.DisconnectIfExists();
|
||||
|
||||
if (aQueues == MediaDecoderReader::AUDIO_VIDEO) {
|
||||
// Stop the audio thread. Otherwise, MediaSink might be accessing AudioQueue
|
||||
@@ -2372,7 +2380,6 @@ MediaDecoderStateMachine::Reset(MediaDecoderReader::TargetQueues aQueues /*= AUD
|
||||
mDecodedAudioEndTime = 0;
|
||||
mAudioCompleted = false;
|
||||
AudioQueue().Reset();
|
||||
mAudioWaitRequest.DisconnectIfExists();
|
||||
}
|
||||
|
||||
mMetadataRequest.DisconnectIfExists();
|
||||
@@ -2848,9 +2855,9 @@ MediaDecoderStateMachine::AudioRequestStatus() const
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
if (mReader->IsRequestingAudioData()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingAudioData());
|
||||
return "pending";
|
||||
} else if (mAudioWaitRequest.Exists()) {
|
||||
} else if (mReader->IsWaitingAudioData()) {
|
||||
return "waiting";
|
||||
}
|
||||
return "idle";
|
||||
@@ -2861,9 +2868,9 @@ MediaDecoderStateMachine::VideoRequestStatus() const
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
if (mReader->IsRequestingVideoData()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingVideoData());
|
||||
return "pending";
|
||||
} else if (mVideoWaitRequest.Exists()) {
|
||||
} else if (mReader->IsWaitingVideoData()) {
|
||||
return "waiting";
|
||||
}
|
||||
return "idle";
|
||||
|
||||
@@ -830,19 +830,13 @@ private:
|
||||
// should exist at any given moment.
|
||||
|
||||
CallbackID mAudioCallbackID;
|
||||
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
|
||||
CallbackID mWaitAudioCallbackID;
|
||||
const char* AudioRequestStatus() const;
|
||||
|
||||
CallbackID mVideoCallbackID;
|
||||
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
|
||||
CallbackID mWaitVideoCallbackID;
|
||||
const char* VideoRequestStatus() const;
|
||||
|
||||
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>& WaitRequestRef(MediaData::Type aType)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
|
||||
}
|
||||
|
||||
// True if we shouldn't play our audio (but still write it to any capturing
|
||||
// streams). When this is true, the audio thread will never start again after
|
||||
// it has stopped.
|
||||
|
||||
+31
-28
@@ -157,8 +157,6 @@ SeekTask::Discard()
|
||||
|
||||
// Disconnect MediaDecoderReaderWrapper.
|
||||
mSeekRequest.DisconnectIfExists();
|
||||
mAudioWaitRequest.DisconnectIfExists();
|
||||
mVideoWaitRequest.DisconnectIfExists();
|
||||
CancelMediaDecoderReaderWrapperCallback();
|
||||
|
||||
mIsDiscarded = true;
|
||||
@@ -219,7 +217,7 @@ SeekTask::EnsureAudioDecodeTaskQueued()
|
||||
|
||||
if (!IsAudioDecoding() ||
|
||||
mReader->IsRequestingAudioData() ||
|
||||
mAudioWaitRequest.Exists() ||
|
||||
mReader->IsWaitingAudioData() ||
|
||||
mSeekRequest.Exists()) {
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -238,7 +236,7 @@ SeekTask::EnsureVideoDecodeTaskQueued()
|
||||
|
||||
if (!IsVideoDecoding() ||
|
||||
mReader->IsRequestingVideoData() ||
|
||||
mVideoWaitRequest.Exists() ||
|
||||
mReader->IsWaitingVideoData() ||
|
||||
mSeekRequest.Exists()) {
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -252,9 +250,9 @@ SeekTask::AudioRequestStatus()
|
||||
{
|
||||
AssertOwnerThread();
|
||||
if (mReader->IsRequestingAudioData()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingAudioData());
|
||||
return "pending";
|
||||
} else if (mAudioWaitRequest.Exists()) {
|
||||
} else if (mReader->IsWaitingAudioData()) {
|
||||
return "waiting";
|
||||
}
|
||||
return "idle";
|
||||
@@ -265,9 +263,9 @@ SeekTask::VideoRequestStatus()
|
||||
{
|
||||
AssertOwnerThread();
|
||||
if (mReader->IsRequestingVideoData()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingVideoData());
|
||||
return "pending";
|
||||
} else if (mVideoWaitRequest.Exists()) {
|
||||
} else if (mReader->IsWaitingVideoData()) {
|
||||
return "waiting";
|
||||
}
|
||||
return "idle";
|
||||
@@ -564,16 +562,7 @@ SeekTask::OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
|
||||
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
|
||||
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
|
||||
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
|
||||
RefPtr<SeekTask> self = this;
|
||||
mAudioWaitRequest.Begin(mReader->WaitForData(MediaData::AUDIO_DATA)
|
||||
->Then(OwnerThread(), __func__,
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
self->mAudioWaitRequest.Complete();
|
||||
self->EnsureAudioDecodeTaskQueued();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {
|
||||
self->mAudioWaitRequest.Complete();
|
||||
}));
|
||||
mReader->WaitForData(MediaData::AUDIO_DATA);
|
||||
|
||||
// We are out of data to decode and will enter buffering mode soon.
|
||||
// We want to play the frames we have already decoded, so we stop pre-rolling
|
||||
@@ -666,16 +655,7 @@ SeekTask::OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
|
||||
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
|
||||
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
|
||||
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
|
||||
RefPtr<SeekTask> self = this;
|
||||
mVideoWaitRequest.Begin(mReader->WaitForData(MediaData::VIDEO_DATA)
|
||||
->Then(OwnerThread(), __func__,
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
self->mVideoWaitRequest.Complete();
|
||||
self->EnsureVideoDecodeTaskQueued();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {
|
||||
self->mVideoWaitRequest.Complete();
|
||||
}));
|
||||
mReader->WaitForData(MediaData::VIDEO_DATA);
|
||||
|
||||
// We are out of data to decode and will enter buffering mode soon.
|
||||
// We want to play the frames we have already decoded, so we stop pre-rolling
|
||||
@@ -717,8 +697,25 @@ SeekTask::SetMediaDecoderReaderWrapperCallback()
|
||||
mReader->SetVideoCallback(this, &SeekTask::OnVideoDecoded,
|
||||
&SeekTask::OnVideoNotDecoded);
|
||||
|
||||
RefPtr<SeekTask> self = this;
|
||||
mWaitAudioCallbackID =
|
||||
mReader->SetWaitAudioCallback(
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
self->EnsureAudioDecodeTaskQueued();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {});
|
||||
|
||||
mWaitVideoCallbackID =
|
||||
mReader->SetWaitVideoCallback(
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
self->EnsureVideoDecodeTaskQueued();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {});
|
||||
|
||||
DECODER_LOG("SeekTask set audio callbacks: mAudioCallbackID = %d\n", (int)mAudioCallbackID);
|
||||
DECODER_LOG("SeekTask set video callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
|
||||
DECODER_LOG("SeekTask set wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
|
||||
DECODER_LOG("SeekTask set wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -729,5 +726,11 @@ SeekTask::CancelMediaDecoderReaderWrapperCallback()
|
||||
|
||||
DECODER_LOG("SeekTask cancel video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
|
||||
mReader->CancelVideoCallback(mVideoCallbackID);
|
||||
|
||||
DECODER_LOG("SeekTask cancel wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
|
||||
mReader->CancelWaitAudioCallback(mWaitAudioCallbackID);
|
||||
|
||||
DECODER_LOG("SeekTask cancel wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
|
||||
mReader->CancelWaitVideoCallback(mWaitVideoCallbackID);
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -164,8 +164,8 @@ protected:
|
||||
MozPromiseRequestHolder<MediaDecoderReader::SeekPromise> mSeekRequest;
|
||||
CallbackID mAudioCallbackID;
|
||||
CallbackID mVideoCallbackID;
|
||||
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
|
||||
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
|
||||
CallbackID mWaitAudioCallbackID;
|
||||
CallbackID mWaitVideoCallbackID;
|
||||
|
||||
/*
|
||||
* Information which are going to be returned to MDSM.
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "RasterImage.h"
|
||||
|
||||
#include "base/histogram.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsError.h"
|
||||
@@ -106,7 +105,6 @@ RasterImage::RasterImage(ImageURL* aURI /* = nullptr */) :
|
||||
mAnimationFinished(false),
|
||||
mWantFullDecode(false)
|
||||
{
|
||||
//Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(0);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
@@ -1337,16 +1335,6 @@ RasterImage::Decode(const IntSize& aSize, uint32_t aFlags)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mDecodeCount > sMaxDecodeCount) {
|
||||
// Don't subtract out 0 from the histogram, because that causes its count
|
||||
// to go negative, which is not kosher.
|
||||
if (sMaxDecodeCount > 0) {
|
||||
/*Telemetry::GetHistogramById(Telemetry::IMAGE_MAX_DECODE_COUNT)
|
||||
->Subtract(sMaxDecodeCount);*/
|
||||
}
|
||||
sMaxDecodeCount = mDecodeCount;
|
||||
}
|
||||
|
||||
// We're ready to decode; start the decoder.
|
||||
LaunchDecoder(decoder, this, aFlags, mHasSourceData);
|
||||
return NS_OK;
|
||||
|
||||
@@ -941,7 +941,7 @@ void
|
||||
CountHistogram::Accumulate(Sample value, Count count, size_t index)
|
||||
{
|
||||
size_t zero_index = BucketIndex(0);
|
||||
LinearHistogram::Accumulate(1, 1, zero_index);
|
||||
LinearHistogram::Accumulate(value, 1, zero_index);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -435,7 +435,7 @@ private:
|
||||
threadLocalInfo->mActor.forget(&actor);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
NS_DispatchToMainThread(NewNonOwningRunnableMethod(actor, &ChildImpl::Release)));
|
||||
NS_DispatchToMainThread(NewNonOwningRunnableMethod(actor, &ChildImpl::Release)));
|
||||
}
|
||||
}
|
||||
delete threadLocalInfo;
|
||||
@@ -1258,7 +1258,7 @@ ParentImpl::ShutdownTimerCallback(nsITimer* aTimer, void* aClosure)
|
||||
nsCOMPtr<nsIRunnable> forceCloseRunnable =
|
||||
new ForceCloseBackgroundActorsRunnable(closure->mLiveActors);
|
||||
MOZ_ALWAYS_SUCCEEDS(closure->mThread->Dispatch(forceCloseRunnable,
|
||||
NS_DISPATCH_NORMAL));
|
||||
NS_DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -72,7 +72,7 @@ private:
|
||||
inline void AssertIOThread()
|
||||
{
|
||||
NS_ASSERTION(MessageLoop::TYPE_IO == MessageLoop::current()->type(),
|
||||
"should be on the IO thread!");
|
||||
"should be on the IO thread!");
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*/
|
||||
/* 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/. */
|
||||
@@ -492,22 +490,24 @@ GeckoChildProcessHost::DissociateActor()
|
||||
int32_t GeckoChildProcessHost::mChildCounter = 0;
|
||||
|
||||
void
|
||||
GeckoChildProcessHost::SetChildLogName(const char* varName, const char* origLogName)
|
||||
GeckoChildProcessHost::SetChildLogName(const char* varName, const char* origLogName,
|
||||
nsACString &buffer)
|
||||
{
|
||||
// We currently have no portable way to launch child with environment
|
||||
// different than parent. So temporarily change NSPR_LOG_FILE so child
|
||||
// inherits value we want it to have. (NSPR only looks at NSPR_LOG_FILE at
|
||||
// startup, so it's 'safe' to play with the parent's environment this way.)
|
||||
nsAutoCString setChildLogName(varName);
|
||||
setChildLogName.Append(origLogName);
|
||||
buffer.Assign(varName);
|
||||
buffer.Append(origLogName);
|
||||
|
||||
// Append child-specific postfix to name
|
||||
setChildLogName.AppendLiteral(".child-");
|
||||
setChildLogName.AppendInt(mChildCounter);
|
||||
buffer.AppendLiteral(".child-");
|
||||
buffer.AppendInt(mChildCounter);
|
||||
|
||||
// Passing temporary to PR_SetEnv is ok here because env gets copied
|
||||
// by exec, etc., to permanent storage in child when process launched.
|
||||
PR_SetEnv(setChildLogName.get());
|
||||
// Passing temporary to PR_SetEnv is ok here if we keep the temporary
|
||||
// for the time we launch the sub-process. It's copied to the new
|
||||
// environment.
|
||||
PR_SetEnv(buffer.BeginReading());
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -520,37 +520,38 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts, b
|
||||
return PerformAsyncLaunchInternal(aExtraOpts, arch);
|
||||
}
|
||||
|
||||
++mChildCounter;
|
||||
|
||||
// remember original value so we can restore it.
|
||||
// - Note: this code is not called re-entrantly, nor are restoreOrig*LogName
|
||||
// or mChildCounter touched by any other thread, so this is safe.
|
||||
static nsAutoCString restoreOrigNSPRLogName;
|
||||
static nsAutoCString restoreOrigMozLogName;
|
||||
++mChildCounter;
|
||||
|
||||
// Must keep these on the same stack where from we call PerformAsyncLaunchInternal
|
||||
// so that PR_DuplicateEnvironment() still sees a valid memory.
|
||||
nsAutoCString nsprLogName;
|
||||
nsAutoCString mozLogName;
|
||||
|
||||
if (origNSPRLogName) {
|
||||
if (restoreOrigNSPRLogName.IsEmpty()) {
|
||||
restoreOrigNSPRLogName.AssignLiteral("NSPR_LOG_FILE=");
|
||||
restoreOrigNSPRLogName.Append(origNSPRLogName);
|
||||
if (mRestoreOrigNSPRLogName.IsEmpty()) {
|
||||
mRestoreOrigNSPRLogName.AssignLiteral("NSPR_LOG_FILE=");
|
||||
mRestoreOrigNSPRLogName.Append(origNSPRLogName);
|
||||
}
|
||||
SetChildLogName("NSPR_LOG_FILE=", origNSPRLogName);
|
||||
SetChildLogName("NSPR_LOG_FILE=", origNSPRLogName, nsprLogName);
|
||||
}
|
||||
if (origMozLogName) {
|
||||
if (restoreOrigMozLogName.IsEmpty()) {
|
||||
restoreOrigMozLogName.AssignLiteral("MOZ_LOG_FILE=");
|
||||
restoreOrigMozLogName.Append(origMozLogName);
|
||||
if (mRestoreOrigMozLogName.IsEmpty()) {
|
||||
mRestoreOrigMozLogName.AssignLiteral("MOZ_LOG_FILE=");
|
||||
mRestoreOrigMozLogName.Append(origMozLogName);
|
||||
}
|
||||
SetChildLogName("MOZ_LOG_FILE=", origMozLogName);
|
||||
SetChildLogName("MOZ_LOG_FILE=", origMozLogName, mozLogName);
|
||||
}
|
||||
|
||||
bool retval = PerformAsyncLaunchInternal(aExtraOpts, arch);
|
||||
|
||||
// Revert to original value
|
||||
if (origNSPRLogName) {
|
||||
PR_SetEnv(restoreOrigNSPRLogName.get());
|
||||
PR_SetEnv(mRestoreOrigNSPRLogName.get());
|
||||
}
|
||||
if (origMozLogName) {
|
||||
PR_SetEnv(restoreOrigMozLogName.get());
|
||||
PR_SetEnv(mRestoreOrigMozLogName.get());
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
@@ -196,11 +196,14 @@ private:
|
||||
base::ProcessArchitecture arch);
|
||||
|
||||
bool RunPerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
|
||||
base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture());
|
||||
base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture());
|
||||
|
||||
static void GetPathToBinary(FilePath& exePath);
|
||||
|
||||
void SetChildLogName(const char* varName, const char* origLogName);
|
||||
// The buffer is passed to preserve its lifetime until we are done
|
||||
// with launching the sub-process.
|
||||
void SetChildLogName(const char* varName, const char* origLogName,
|
||||
nsACString &buffer);
|
||||
|
||||
// In between launching the subprocess and handing off its IPC
|
||||
// channel, there's a small window of time in which *we* might still
|
||||
@@ -215,6 +218,12 @@ private:
|
||||
// it to stay alive and have not yet been destroyed.
|
||||
Atomic<int32_t> mAssociatedActors;
|
||||
|
||||
// Remember original env values so we can restore it (there is no other
|
||||
// simple way how to change environment of a child process than to modify
|
||||
// the current environment).
|
||||
nsCString mRestoreOrigNSPRLogName;
|
||||
nsCString mRestoreOrigMozLogName;
|
||||
|
||||
static uint32_t sNextUniqueID;
|
||||
};
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ MessagePump::Run(MessagePump::Delegate* aDelegate)
|
||||
{
|
||||
MOZ_ASSERT(keep_running_);
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread(),
|
||||
"Use mozilla::ipc::MessagePumpForNonMainThreads instead!");
|
||||
"Use mozilla::ipc::MessagePumpForNonMainThreads instead!");
|
||||
MOZ_RELEASE_ASSERT(!mThread);
|
||||
|
||||
nsIThread* thisThread = NS_GetCurrentThread();
|
||||
@@ -172,7 +172,7 @@ MessagePump::ScheduleDelayedWork(const base::TimeTicks& aDelayedTime)
|
||||
// To avoid racing on mDelayedWorkTimer, we need to be on the same thread as
|
||||
// ::Run().
|
||||
MOZ_RELEASE_ASSERT(NS_GetCurrentThread() == mThread ||
|
||||
(!mThread && NS_IsMainThread()));
|
||||
(!mThread && NS_IsMainThread()));
|
||||
|
||||
if (!mDelayedWorkTimer) {
|
||||
mDelayedWorkTimer = do_CreateInstance(kNS_TIMER_CID);
|
||||
@@ -222,7 +222,7 @@ MessagePump::DoDelayedWork(base::MessagePump::Delegate* aDelegate)
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(DoWorkRunnable, CancelableRunnable,
|
||||
nsITimerCallback)
|
||||
nsITimerCallback)
|
||||
|
||||
NS_IMETHODIMP
|
||||
DoWorkRunnable::Run()
|
||||
|
||||
+2
-1
@@ -953,7 +953,8 @@ Valueify(const JSClass* c)
|
||||
enum ESClassValue {
|
||||
ESClass_Object, ESClass_Array, ESClass_Number, ESClass_String,
|
||||
ESClass_Boolean, ESClass_RegExp, ESClass_ArrayBuffer, ESClass_SharedArrayBuffer,
|
||||
ESClass_Date, ESClass_Set, ESClass_Map, ESClass_Promise,
|
||||
ESClass_Date, ESClass_Set, ESClass_Map, ESClass_Promise, ESClass_MapIterator,
|
||||
ESClass_SetIterator,
|
||||
|
||||
/** None of the above. */
|
||||
ESClass_Other
|
||||
|
||||
+2
-1
@@ -578,7 +578,8 @@ class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertOnGC
|
||||
|
||||
/**
|
||||
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
|
||||
* JS::TraceKind::Shape. |thing| should be non-null.
|
||||
* JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
|
||||
* if anything was unmarked.
|
||||
*/
|
||||
extern JS_FRIEND_API(bool)
|
||||
UnmarkGrayGCThingRecursively(GCCellPtr thing);
|
||||
|
||||
+2
-79
@@ -101,10 +101,8 @@ class JS_FRIEND_API(Wrapper);
|
||||
*
|
||||
* BaseProxyHandler
|
||||
* |
|
||||
* DirectProxyHandler // has a target
|
||||
* |
|
||||
* Wrapper // can be unwrapped, revealing target
|
||||
* | // (see js::CheckedUnwrap)
|
||||
* Wrapper // has a target, can be unwrapped to reveal
|
||||
* | // target (see js::CheckedUnwrap)
|
||||
* |
|
||||
* CrossCompartmentWrapper // target is in another compartment;
|
||||
* // implements membrane between compartments
|
||||
@@ -349,81 +347,6 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
virtual bool isScripted() const { return false; }
|
||||
};
|
||||
|
||||
/*
|
||||
* DirectProxyHandler includes a notion of a target object. All methods are
|
||||
* reimplemented such that they forward their behavior to the target. This
|
||||
* allows consumers of this class to forward to another object as transparently
|
||||
* and efficiently as possible.
|
||||
*
|
||||
* Important: If you add a method implementation here, you probably also need
|
||||
* to add an override in CrossCompartmentWrapper. If you don't, you risk
|
||||
* compartment mismatches. See bug 945826 comment 0.
|
||||
*/
|
||||
class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
|
||||
{
|
||||
public:
|
||||
explicit MOZ_CONSTEXPR DirectProxyHandler(const void* aFamily, bool aHasPrototype = false,
|
||||
bool aHasSecurityPolicy = false)
|
||||
: BaseProxyHandler(aFamily, aHasPrototype, aHasSecurityPolicy)
|
||||
{ }
|
||||
|
||||
/* Standard internal methods. */
|
||||
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc) const override;
|
||||
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
ObjectOpResult& result) const override;
|
||||
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
|
||||
AutoIdVector& props) const override;
|
||||
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
ObjectOpResult& result) const override;
|
||||
virtual bool enumerate(JSContext* cx, HandleObject proxy,
|
||||
MutableHandleObject objp) const override;
|
||||
virtual bool getPrototype(JSContext* cx, HandleObject proxy,
|
||||
MutableHandleObject protop) const override;
|
||||
virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
|
||||
ObjectOpResult& result) const override;
|
||||
virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
|
||||
MutableHandleObject protop) const override;
|
||||
virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
|
||||
bool* succeeded) const override;
|
||||
virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
|
||||
ObjectOpResult& result) const override;
|
||||
virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
|
||||
virtual bool has(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const override;
|
||||
virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
||||
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
||||
|
||||
/* SpiderMonkey extensions. */
|
||||
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc) const override;
|
||||
virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
bool* bp) const override;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
|
||||
AutoIdVector& props) const override;
|
||||
virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
|
||||
const CallArgs& args) const override;
|
||||
virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
|
||||
bool* bp) const override;
|
||||
virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy,
|
||||
ESClassValue* classValue) const override;
|
||||
virtual bool isArray(JSContext* cx, HandleObject proxy,
|
||||
JS::IsArrayAnswer* answer) const override;
|
||||
virtual const char* className(JSContext* cx, HandleObject proxy) const override;
|
||||
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
|
||||
unsigned indent) const override;
|
||||
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
|
||||
RegExpGuard* g) const override;
|
||||
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
|
||||
virtual bool isCallable(JSObject* obj) const override;
|
||||
virtual JSObject* weakmapKeyDelegate(JSObject* proxy) const override;
|
||||
};
|
||||
|
||||
extern JS_FRIEND_DATA(const js::Class* const) ProxyClassPtr;
|
||||
|
||||
inline bool IsProxy(const JSObject* obj)
|
||||
|
||||
@@ -98,15 +98,10 @@ JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
|
||||
enum class RootKind : int8_t
|
||||
{
|
||||
// These map 1:1 with trace kinds.
|
||||
BaseShape = 0,
|
||||
JitCode,
|
||||
LazyScript,
|
||||
Object,
|
||||
ObjectGroup,
|
||||
Script,
|
||||
Shape,
|
||||
String,
|
||||
Symbol,
|
||||
#define EXPAND_ROOT_KIND(name, _0, _1) \
|
||||
name,
|
||||
JS_FOR_EACH_TRACEKIND(EXPAND_ROOT_KIND)
|
||||
#undef EXPAND_ROOT_KIND
|
||||
|
||||
// These tagged pointers are special-cased for performance.
|
||||
Id,
|
||||
|
||||
+22
-4
@@ -71,19 +71,37 @@ class JS_PUBLIC_API(JSTracer)
|
||||
bool isTenuringTracer() const { return tag_ == TracerKindTag::Tenuring; }
|
||||
bool isCallbackTracer() const { return tag_ == TracerKindTag::Callback; }
|
||||
inline JS::CallbackTracer* asCallbackTracer();
|
||||
#ifdef DEBUG
|
||||
bool checkEdges() { return checkEdges_; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
JSTracer(JSRuntime* rt, TracerKindTag tag,
|
||||
WeakMapTraceKind weakTraceKind = TraceWeakMapValues)
|
||||
: runtime_(rt), weakMapAction_(weakTraceKind), tag_(tag)
|
||||
: runtime_(rt)
|
||||
, weakMapAction_(weakTraceKind)
|
||||
#ifdef DEBUG
|
||||
, checkEdges_(true)
|
||||
#endif
|
||||
, tag_(tag)
|
||||
{}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Set whether to check edges are valid in debug builds.
|
||||
void setCheckEdges(bool check) {
|
||||
checkEdges_ = check;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
JSRuntime* runtime_;
|
||||
WeakMapTraceKind weakMapAction_;
|
||||
JSRuntime* runtime_;
|
||||
WeakMapTraceKind weakMapAction_;
|
||||
#ifdef DEBUG
|
||||
bool checkEdges_;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
TracerKindTag tag_;
|
||||
TracerKindTag tag_;
|
||||
};
|
||||
|
||||
namespace JS {
|
||||
|
||||
@@ -2025,8 +2025,7 @@ class MOZ_STACK_CLASS ModuleValidator
|
||||
uint32_t funcIndex = numFunctions();
|
||||
if (funcIndex >= MaxFuncs)
|
||||
return failCurrentOffset("too many functions");
|
||||
if (!mg_.initFuncSig(funcIndex, sigIndex))
|
||||
return false;
|
||||
mg_.initFuncSig(funcIndex, sigIndex);
|
||||
Global* global = validationLifo_.new_<Global>(Global::Function);
|
||||
if (!global)
|
||||
return false;
|
||||
|
||||
@@ -40,7 +40,7 @@ typedef frontend::ParseContext<frontend::FullParseHandler> AsmJSParseContext;
|
||||
// indeterminate amount and the entire function should be reparsed from the
|
||||
// beginning.
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
CompileAsmJS(ExclusiveContext* cx, AsmJSParser& parser, frontend::ParseNode* stmtList,
|
||||
bool* validated);
|
||||
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ static const uint64_t MappedSize = 2 * Uint32Range + PageSize;
|
||||
|
||||
// Compiles the given binary wasm module given the ArrayBufferObject
|
||||
// and links the module's imports with the given import object.
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
Eval(JSContext* cx, Handle<TypedArrayObject*> code, HandleObject importObj,
|
||||
MutableHandleObject exportObj);
|
||||
|
||||
|
||||
@@ -815,10 +815,10 @@ class Decoder
|
||||
|
||||
typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
EncodeLocalEntries(Encoder& d, const ValTypeVector& locals);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
DecodeLocalEntries(Decoder& d, ValTypeVector* locals);
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
@@ -390,7 +390,7 @@ class MOZ_STACK_CLASS ExprIter : private Policy
|
||||
}
|
||||
|
||||
// Read the value stack entry at depth |index|.
|
||||
bool peek(uint32_t index, TypeAndValue<Value>* tv) {
|
||||
MOZ_MUST_USE bool peek(uint32_t index, TypeAndValue<Value>* tv) {
|
||||
if (Validate && valueStack_.length() - controlStack_.back().valueStackStart() <= index)
|
||||
return fail("peeking at value from outside block");
|
||||
*tv = valueStack_[valueStack_.length() - index];
|
||||
@@ -536,7 +536,7 @@ ExprIter<Policy>::typeMismatch(ExprType actual, ExprType expected)
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::checkType(ExprType actual, ExprType expected)
|
||||
{
|
||||
if (!Validate) {
|
||||
@@ -1230,7 +1230,7 @@ ExprIter<Policy>::readSetGlobal(const GlobalDescVector& globals, uint32_t* id, V
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::readI32Const(int32_t* i32)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::I32);
|
||||
@@ -1241,7 +1241,7 @@ ExprIter<Policy>::readI32Const(int32_t* i32)
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::readI64Const(int64_t* i64)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::I64);
|
||||
@@ -1252,7 +1252,7 @@ ExprIter<Policy>::readI64Const(int64_t* i64)
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::readF32Const(float* f32)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::F32);
|
||||
@@ -1271,7 +1271,7 @@ ExprIter<Policy>::readF32Const(float* f32)
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::readF64Const(double* f64)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::F64);
|
||||
@@ -1290,7 +1290,7 @@ ExprIter<Policy>::readF64Const(double* f64)
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::readI32x4Const(I32x4* i32x4)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::I32x4);
|
||||
@@ -1301,7 +1301,7 @@ ExprIter<Policy>::readI32x4Const(I32x4* i32x4)
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::readF32x4Const(F32x4* f32x4)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::F32x4);
|
||||
@@ -1312,7 +1312,7 @@ ExprIter<Policy>::readF32x4Const(F32x4* f32x4)
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline MOZ_MUST_USE bool
|
||||
inline bool
|
||||
ExprIter<Policy>::readB32x4Const(I32x4* i32x4)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::B32x4);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace wasm {
|
||||
// Translate the given binary representation of a wasm module into the module's textual
|
||||
// representation.
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
BinaryToText(JSContext* cx, const uint8_t* bytes, size_t length, StringBuffer& buffer);
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
@@ -627,7 +627,7 @@ ModuleGenerator::sig(uint32_t index) const
|
||||
return shared_->sigs[index];
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
ModuleGenerator::initFuncSig(uint32_t funcIndex, uint32_t sigIndex)
|
||||
{
|
||||
MOZ_ASSERT(isAsmJS());
|
||||
@@ -636,7 +636,6 @@ ModuleGenerator::initFuncSig(uint32_t funcIndex, uint32_t sigIndex)
|
||||
|
||||
module_->numFuncs++;
|
||||
shared_->funcSigs[funcIndex] = &shared_->sigs[sigIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -145,21 +145,22 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
DebugOnly<bool> startedFuncDefs_;
|
||||
DebugOnly<bool> finishedFuncDefs_;
|
||||
|
||||
bool finishOutstandingTask();
|
||||
MOZ_MUST_USE bool finishOutstandingTask();
|
||||
bool funcIsDefined(uint32_t funcIndex) const;
|
||||
uint32_t funcEntry(uint32_t funcIndex) const;
|
||||
bool convertOutOfRangeBranchesToThunks();
|
||||
bool finishTask(IonCompileTask* task);
|
||||
bool finishCodegen(StaticLinkData* link);
|
||||
bool finishStaticLinkData(uint8_t* code, uint32_t codeBytes, StaticLinkData* link);
|
||||
bool addImport(const Sig& sig, uint32_t globalDataOffset);
|
||||
bool allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOffset);
|
||||
MOZ_MUST_USE bool convertOutOfRangeBranchesToThunks();
|
||||
MOZ_MUST_USE bool finishTask(IonCompileTask* task);
|
||||
MOZ_MUST_USE bool finishCodegen(StaticLinkData* link);
|
||||
MOZ_MUST_USE bool finishStaticLinkData(uint8_t* code, uint32_t codeBytes, StaticLinkData* link);
|
||||
MOZ_MUST_USE bool addImport(const Sig& sig, uint32_t globalDataOffset);
|
||||
MOZ_MUST_USE bool allocateGlobalBytes(uint32_t bytes, uint32_t align,
|
||||
uint32_t* globalDataOffset);
|
||||
|
||||
public:
|
||||
explicit ModuleGenerator(ExclusiveContext* cx);
|
||||
~ModuleGenerator();
|
||||
|
||||
bool init(UniqueModuleGeneratorData shared, UniqueChars filename);
|
||||
MOZ_MUST_USE bool init(UniqueModuleGeneratorData shared, UniqueChars filename);
|
||||
|
||||
bool isAsmJS() const { return module_->kind == ModuleKind::AsmJS; }
|
||||
CompileArgs args() const { return module_->compileArgs; }
|
||||
@@ -178,7 +179,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
const DeclaredSig& funcSig(uint32_t funcIndex) const;
|
||||
|
||||
// Globals:
|
||||
bool allocateGlobal(ValType type, bool isConst, uint32_t* index);
|
||||
MOZ_MUST_USE bool allocateGlobal(ValType type, bool isConst, uint32_t* index);
|
||||
const GlobalDesc& global(unsigned index) const { return shared_->globals[index]; }
|
||||
|
||||
// Imports:
|
||||
@@ -186,35 +187,37 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
const ImportModuleGeneratorData& import(uint32_t index) const;
|
||||
|
||||
// Exports:
|
||||
bool declareExport(UniqueChars fieldName, uint32_t funcIndex, uint32_t* exportIndex = nullptr);
|
||||
MOZ_MUST_USE bool declareExport(UniqueChars fieldName, uint32_t funcIndex,
|
||||
uint32_t* exportIndex = nullptr);
|
||||
uint32_t numExports() const;
|
||||
bool addMemoryExport(UniqueChars fieldName);
|
||||
MOZ_MUST_USE bool addMemoryExport(UniqueChars fieldName);
|
||||
|
||||
// Function definitions:
|
||||
bool startFuncDefs();
|
||||
bool startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg);
|
||||
bool finishFuncDef(uint32_t funcIndex, unsigned generateTime, FunctionGenerator* fg);
|
||||
bool finishFuncDefs();
|
||||
MOZ_MUST_USE bool startFuncDefs();
|
||||
MOZ_MUST_USE bool startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg);
|
||||
MOZ_MUST_USE bool finishFuncDef(uint32_t funcIndex, unsigned generateTime,
|
||||
FunctionGenerator* fg);
|
||||
MOZ_MUST_USE bool finishFuncDefs();
|
||||
|
||||
// Function-pointer tables:
|
||||
static const uint32_t BadIndirectCall = UINT32_MAX;
|
||||
|
||||
// asm.js lazy initialization:
|
||||
void initSig(uint32_t sigIndex, Sig&& sig);
|
||||
bool initFuncSig(uint32_t funcIndex, uint32_t sigIndex);
|
||||
bool initImport(uint32_t importIndex, uint32_t sigIndex);
|
||||
bool initSigTableLength(uint32_t sigIndex, uint32_t numElems);
|
||||
void initFuncSig(uint32_t funcIndex, uint32_t sigIndex);
|
||||
MOZ_MUST_USE bool initImport(uint32_t importIndex, uint32_t sigIndex);
|
||||
MOZ_MUST_USE bool initSigTableLength(uint32_t sigIndex, uint32_t numElems);
|
||||
void initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncIndices);
|
||||
void bumpMinHeapLength(uint32_t newMinHeapLength);
|
||||
|
||||
// Return a ModuleData object which may be used to construct a Module, the
|
||||
// StaticLinkData required to call Module::staticallyLink, and the list of
|
||||
// functions that took a long time to compile.
|
||||
bool finish(CacheableCharsVector&& prettyFuncNames,
|
||||
UniqueModuleData* module,
|
||||
UniqueStaticLinkData* staticLinkData,
|
||||
UniqueExportMap* exportMap,
|
||||
SlowFunctionVector* slowFuncs);
|
||||
MOZ_MUST_USE bool finish(CacheableCharsVector&& prettyFuncNames,
|
||||
UniqueModuleData* module,
|
||||
UniqueStaticLinkData* staticLinkData,
|
||||
UniqueExportMap* exportMap,
|
||||
SlowFunctionVector* slowFuncs);
|
||||
};
|
||||
|
||||
// A FunctionGenerator encapsulates the generation of a single function body.
|
||||
@@ -245,7 +248,7 @@ class MOZ_STACK_CLASS FunctionGenerator
|
||||
Bytes& bytes() {
|
||||
return bytes_;
|
||||
}
|
||||
bool addCallSiteLineNum(uint32_t lineno) {
|
||||
MOZ_MUST_USE bool addCallSiteLineNum(uint32_t lineno) {
|
||||
return callSiteLineNums_.append(lineno);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -461,20 +461,22 @@ class FunctionCompiler
|
||||
return ins;
|
||||
}
|
||||
|
||||
MDefinition* div(MDefinition* lhs, MDefinition* rhs, MIRType type, bool unsignd)
|
||||
MDefinition* div(MDefinition* lhs, MDefinition* rhs, MIRType type, bool unsignd,
|
||||
bool trapOnError)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
MDiv* ins = MDiv::NewAsmJS(alloc(), lhs, rhs, type, unsignd);
|
||||
MDiv* ins = MDiv::NewAsmJS(alloc(), lhs, rhs, type, unsignd, trapOnError);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
||||
MDefinition* mod(MDefinition* lhs, MDefinition* rhs, MIRType type, bool unsignd)
|
||||
MDefinition* mod(MDefinition* lhs, MDefinition* rhs, MIRType type, bool unsignd,
|
||||
bool trapOnError)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
MMod* ins = MMod::NewAsmJS(alloc(), lhs, rhs, type, unsignd);
|
||||
MMod* ins = MMod::NewAsmJS(alloc(), lhs, rhs, type, unsignd, trapOnError);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -1975,7 +1977,8 @@ EmitDiv(FunctionCompiler& f, ValType operandType, MIRType mirType, bool isUnsign
|
||||
if (!f.iter().readBinary(operandType, &lhs, &rhs))
|
||||
return false;
|
||||
|
||||
f.iter().setResult(f.div(lhs, rhs, mirType, isUnsigned));
|
||||
bool trapOnError = f.mg().kind == ModuleKind::Wasm;
|
||||
f.iter().setResult(f.div(lhs, rhs, mirType, isUnsigned, trapOnError));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1987,7 +1990,8 @@ EmitRem(FunctionCompiler& f, ValType operandType, MIRType mirType, bool isUnsign
|
||||
if (!f.iter().readBinary(operandType, &lhs, &rhs))
|
||||
return false;
|
||||
|
||||
f.iter().setResult(f.mod(lhs, rhs, mirType, isUnsigned));
|
||||
bool trapOnError = f.mg().kind == ModuleKind::Wasm;
|
||||
f.iter().setResult(f.mod(lhs, rhs, mirType, isUnsigned, trapOnError));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ class IonCompileTask
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
IonCompileFunction(IonCompileTask* task);
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
+14
-14
@@ -45,7 +45,7 @@ namespace wasm {
|
||||
size_t serializedSize() const; \
|
||||
uint8_t* serialize(uint8_t* cursor) const; \
|
||||
const uint8_t* deserialize(ExclusiveContext* cx, const uint8_t* cursor); \
|
||||
bool clone(JSContext* cx, Type* out) const; \
|
||||
MOZ_MUST_USE bool clone(JSContext* cx, Type* out) const; \
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
// The StaticLinkData contains all the metadata necessary to perform
|
||||
@@ -500,7 +500,7 @@ class Module : public mozilla::LinkedListElement<Module>
|
||||
WasmActivation*& activation();
|
||||
void specializeToHeap(ArrayBufferObjectMaybeShared* heap);
|
||||
void despecializeFromHeap(ArrayBufferObjectMaybeShared* heap);
|
||||
bool sendCodeRangesToProfiler(JSContext* cx);
|
||||
MOZ_MUST_USE bool sendCodeRangesToProfiler(JSContext* cx);
|
||||
MOZ_MUST_USE bool setProfilingEnabled(JSContext* cx, bool enabled);
|
||||
ImportExit& importToExit(const Import& import);
|
||||
|
||||
@@ -508,7 +508,7 @@ class Module : public mozilla::LinkedListElement<Module>
|
||||
|
||||
protected:
|
||||
const ModuleData& base() const { return *module_; }
|
||||
bool clone(JSContext* cx, const StaticLinkData& link, Module* clone) const;
|
||||
MOZ_MUST_USE bool clone(JSContext* cx, const StaticLinkData& link, Module* clone) const;
|
||||
|
||||
public:
|
||||
static const unsigned SizeOfImportExit = sizeof(ImportExit);
|
||||
@@ -570,19 +570,19 @@ class Module : public mozilla::LinkedListElement<Module>
|
||||
// statically-linked state. The given StaticLinkData must have come from the
|
||||
// compilation of this module.
|
||||
|
||||
bool staticallyLink(ExclusiveContext* cx, const StaticLinkData& link);
|
||||
MOZ_MUST_USE bool staticallyLink(ExclusiveContext* cx, const StaticLinkData& link);
|
||||
|
||||
// This function transitions the module from a statically-linked state to a
|
||||
// dynamically-linked state. If this module usesHeap(), a non-null heap
|
||||
// buffer must be given. The given import vector must match the module's
|
||||
// ImportVector. The function returns a new export object for this module.
|
||||
|
||||
bool dynamicallyLink(JSContext* cx,
|
||||
Handle<WasmModuleObject*> moduleObj,
|
||||
Handle<ArrayBufferObjectMaybeShared*> heap,
|
||||
Handle<FunctionVector> imports,
|
||||
const ExportMap& exportMap,
|
||||
MutableHandleObject exportObj);
|
||||
MOZ_MUST_USE bool dynamicallyLink(JSContext* cx,
|
||||
Handle<WasmModuleObject*> moduleObj,
|
||||
Handle<ArrayBufferObjectMaybeShared*> heap,
|
||||
Handle<FunctionVector> imports,
|
||||
const ExportMap& exportMap,
|
||||
MutableHandleObject exportObj);
|
||||
|
||||
// The wasm heap, established by dynamicallyLink.
|
||||
|
||||
@@ -593,7 +593,7 @@ class Module : public mozilla::LinkedListElement<Module>
|
||||
// arguments (coerced to the corresponding types of the Export signature)
|
||||
// and calling the export's entry trampoline.
|
||||
|
||||
bool callExport(JSContext* cx, uint32_t exportIndex, CallArgs args);
|
||||
MOZ_MUST_USE bool callExport(JSContext* cx, uint32_t exportIndex, CallArgs args);
|
||||
|
||||
// Initially, calls to imports in wasm code call out through the generic
|
||||
// callImport method. If the imported callee gets JIT compiled and the types
|
||||
@@ -601,8 +601,8 @@ class Module : public mozilla::LinkedListElement<Module>
|
||||
// directly into the JIT code. If the JIT code is released, the Module must
|
||||
// be notified so it can go back to the generic callImport.
|
||||
|
||||
bool callImport(JSContext* cx, uint32_t importIndex, unsigned argc, const uint64_t* argv,
|
||||
MutableHandleValue rval);
|
||||
MOZ_MUST_USE bool callImport(JSContext* cx, uint32_t importIndex, unsigned argc,
|
||||
const uint64_t* argv, MutableHandleValue rval);
|
||||
void deoptimizeImportExit(uint32_t importIndex);
|
||||
|
||||
// At runtime, when $pc is in wasm function code (containsFunctionPC($pc)),
|
||||
@@ -666,7 +666,7 @@ class WasmModuleObject : public NativeObject
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 1;
|
||||
static WasmModuleObject* create(ExclusiveContext* cx);
|
||||
bool init(wasm::Module* module);
|
||||
MOZ_MUST_USE bool init(wasm::Module* module);
|
||||
wasm::Module& module() const;
|
||||
void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t* code, size_t* data);
|
||||
static const Class class_;
|
||||
|
||||
@@ -165,7 +165,7 @@ DeserializeVector(ExclusiveContext* cx, const uint8_t* cursor,
|
||||
}
|
||||
|
||||
template <class T, size_t N>
|
||||
static inline bool
|
||||
static inline MOZ_MUST_USE bool
|
||||
CloneVector(JSContext* cx, const mozilla::Vector<T, N, SystemAllocPolicy>& in,
|
||||
mozilla::Vector<T, N, SystemAllocPolicy>* out)
|
||||
{
|
||||
@@ -220,7 +220,7 @@ DeserializePodVector(ExclusiveContext* cx, const uint8_t* cursor,
|
||||
}
|
||||
|
||||
template <class T, size_t N>
|
||||
static inline bool
|
||||
static inline MOZ_MUST_USE bool
|
||||
ClonePodVector(JSContext* cx, const mozilla::Vector<T, N, SystemAllocPolicy>& in,
|
||||
mozilla::Vector<T, N, SystemAllocPolicy>* out)
|
||||
{
|
||||
@@ -230,7 +230,7 @@ ClonePodVector(JSContext* cx, const mozilla::Vector<T, N, SystemAllocPolicy>& in
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline MOZ_MUST_USE bool
|
||||
GetCPUID(uint32_t* cpuId)
|
||||
{
|
||||
enum Arch {
|
||||
@@ -273,7 +273,7 @@ class MachineId
|
||||
JS::BuildIdCharVector buildId_;
|
||||
|
||||
public:
|
||||
bool extractCurrentState(ExclusiveContext* cx) {
|
||||
MOZ_MUST_USE bool extractCurrentState(ExclusiveContext* cx) {
|
||||
if (!cx->buildIdOp())
|
||||
return false;
|
||||
if (!cx->buildIdOp()(&buildId_))
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace wasm {
|
||||
// runtime. Return whether runtime can:
|
||||
// - rely on fault handler support for avoiding asm.js heap bounds checks
|
||||
// - rely on InterruptRunningJitCode to halt running Ion/asm.js from any thread
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
EnsureSignalHandlersInstalled(JSRuntime* rt);
|
||||
|
||||
#if defined(XP_DARWIN) && defined(ASMJS_MAY_USE_SIGNAL_HANDLERS)
|
||||
|
||||
@@ -856,6 +856,43 @@ GenerateErrorStub(MacroAssembler& masm, SymbolicAddress address)
|
||||
return offsets;
|
||||
}
|
||||
|
||||
// Generate a stub that calls into HandleTrap with the right trap reason.
|
||||
static Offsets
|
||||
GenerateTrapStub(MacroAssembler& masm, Trap reason)
|
||||
{
|
||||
masm.haltingAlign(CodeAlignment);
|
||||
|
||||
Offsets offsets;
|
||||
offsets.begin = masm.currentOffset();
|
||||
|
||||
// sp can be anything at this point, so ensure it is aligned when calling
|
||||
// into C++. We unconditionally jump to throw so don't worry about
|
||||
// restoring sp.
|
||||
masm.andToStackPtr(Imm32(~(ABIStackAlignment - 1)));
|
||||
if (ShadowStackSpace)
|
||||
masm.subFromStackPtr(Imm32(ShadowStackSpace));
|
||||
|
||||
MIRTypeVector args;
|
||||
JS_ALWAYS_TRUE(args.append(MIRType::Int32));
|
||||
|
||||
ABIArgMIRTypeIter i(args);
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
masm.move32(Imm32(int32_t(reason)), i->gpr());
|
||||
} else {
|
||||
masm.store32(Imm32(int32_t(reason)),
|
||||
Address(masm.getStackPointer(), i->offsetFromArgBase()));
|
||||
}
|
||||
|
||||
i++;
|
||||
MOZ_ASSERT(i.done());
|
||||
|
||||
masm.call(SymbolicAddress::HandleTrap);
|
||||
masm.jump(JumpTarget::Throw);
|
||||
|
||||
offsets.end = masm.currentOffset();
|
||||
return offsets;
|
||||
}
|
||||
|
||||
// If an exception is thrown, simply pop all frames (since asm.js does not
|
||||
// contain try/catch). To do this:
|
||||
// 1. Restore 'sp' to it's value right after the PushRegsInMask in GenerateEntry.
|
||||
@@ -895,20 +932,18 @@ wasm::GenerateJumpTarget(MacroAssembler& masm, JumpTarget target)
|
||||
switch (target) {
|
||||
case JumpTarget::StackOverflow:
|
||||
return GenerateStackOverflow(masm);
|
||||
case JumpTarget::ConversionError:
|
||||
return GenerateErrorStub(masm, SymbolicAddress::OnImpreciseConversion);
|
||||
case JumpTarget::OutOfBounds:
|
||||
return GenerateErrorStub(masm, SymbolicAddress::OnOutOfBounds);
|
||||
case JumpTarget::BadIndirectCall:
|
||||
return GenerateErrorStub(masm, SymbolicAddress::BadIndirectCall);
|
||||
case JumpTarget::UnreachableTrap:
|
||||
return GenerateErrorStub(masm, SymbolicAddress::UnreachableTrap);
|
||||
case JumpTarget::InvalidConversionToIntegerTrap:
|
||||
return GenerateErrorStub(masm, SymbolicAddress::InvalidConversionToIntegerTrap);
|
||||
case JumpTarget::IntegerOverflowTrap:
|
||||
return GenerateErrorStub(masm, SymbolicAddress::IntegerOverflowTrap);
|
||||
case JumpTarget::Throw:
|
||||
return GenerateThrow(masm);
|
||||
case JumpTarget::Unreachable:
|
||||
case JumpTarget::IntegerOverflow:
|
||||
case JumpTarget::InvalidConversionToInteger:
|
||||
case JumpTarget::IntegerDivideByZero:
|
||||
case JumpTarget::ImpreciseSimdConversion:
|
||||
return GenerateTrapStub(masm, Trap(target));
|
||||
case JumpTarget::Limit:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace wasm {
|
||||
// null-terminated char16_t array) into serialized bytes. If there is an error
|
||||
// other than out-of-memory an error message string will be stored in 'error'.
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
TextToBinary(const char16_t* text, Bytes* bytes, UniqueChars* error);
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
+27
-29
@@ -65,13 +65,6 @@ OnOutOfBounds()
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
|
||||
}
|
||||
|
||||
static void
|
||||
OnImpreciseConversion()
|
||||
{
|
||||
JSContext* cx = JSRuntime::innermostWasmActivation()->cx();
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SIMD_FAILED_CONVERSION);
|
||||
}
|
||||
|
||||
static void
|
||||
BadIndirectCall()
|
||||
{
|
||||
@@ -80,24 +73,35 @@ BadIndirectCall()
|
||||
}
|
||||
|
||||
static void
|
||||
UnreachableTrap()
|
||||
HandleTrap(int32_t trapIndex)
|
||||
{
|
||||
JSContext* cx = JSRuntime::innermostWasmActivation()->cx();
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_UNREACHABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
IntegerOverflowTrap()
|
||||
{
|
||||
JSContext* cx = JSRuntime::innermostWasmActivation()->cx();
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_INTEGER_OVERFLOW);
|
||||
}
|
||||
MOZ_ASSERT(trapIndex < int32_t(Trap::Limit) && trapIndex >= 0);
|
||||
Trap trap = Trap(trapIndex);
|
||||
|
||||
static void
|
||||
InvalidConversionToIntegerTrap()
|
||||
{
|
||||
JSContext* cx = JSRuntime::innermostWasmActivation()->cx();
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_INVALID_CONVERSION);
|
||||
unsigned errorNumber;
|
||||
switch (trap) {
|
||||
case Trap::Unreachable:
|
||||
errorNumber = JSMSG_WASM_UNREACHABLE;
|
||||
break;
|
||||
case Trap::IntegerOverflow:
|
||||
errorNumber = JSMSG_WASM_INTEGER_OVERFLOW;
|
||||
break;
|
||||
case Trap::InvalidConversionToInteger:
|
||||
errorNumber = JSMSG_WASM_INVALID_CONVERSION;
|
||||
break;
|
||||
case Trap::IntegerDivideByZero:
|
||||
errorNumber = JSMSG_WASM_INT_DIVIDE_BY_ZERO;
|
||||
break;
|
||||
case Trap::ImpreciseSimdConversion:
|
||||
errorNumber = JSMSG_SIMD_FAILED_CONVERSION;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("unexpected trap");
|
||||
}
|
||||
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, errorNumber);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
@@ -246,18 +250,12 @@ wasm::AddressOf(SymbolicAddress imm, ExclusiveContext* cx)
|
||||
return FuncCast(WasmReportOverRecursed, Args_General0);
|
||||
case SymbolicAddress::OnOutOfBounds:
|
||||
return FuncCast(OnOutOfBounds, Args_General0);
|
||||
case SymbolicAddress::OnImpreciseConversion:
|
||||
return FuncCast(OnImpreciseConversion, Args_General0);
|
||||
case SymbolicAddress::BadIndirectCall:
|
||||
return FuncCast(BadIndirectCall, Args_General0);
|
||||
case SymbolicAddress::UnreachableTrap:
|
||||
return FuncCast(UnreachableTrap, Args_General0);
|
||||
case SymbolicAddress::IntegerOverflowTrap:
|
||||
return FuncCast(IntegerOverflowTrap, Args_General0);
|
||||
case SymbolicAddress::InvalidConversionToIntegerTrap:
|
||||
return FuncCast(InvalidConversionToIntegerTrap, Args_General0);
|
||||
case SymbolicAddress::HandleExecutionInterrupt:
|
||||
return FuncCast(WasmHandleExecutionInterrupt, Args_General0);
|
||||
case SymbolicAddress::HandleTrap:
|
||||
return FuncCast(HandleTrap, Args_General1);
|
||||
case SymbolicAddress::InvokeImport_Void:
|
||||
return FuncCast(InvokeImport_Void, Args_General3);
|
||||
case SymbolicAddress::InvokeImport_I32:
|
||||
|
||||
+31
-10
@@ -263,7 +263,7 @@ class Sig
|
||||
Sig(Sig&& rhs) : args_(Move(rhs.args_)), ret_(rhs.ret_) {}
|
||||
Sig(ValTypeVector&& args, ExprType ret) : args_(Move(args)), ret_(ret) {}
|
||||
|
||||
bool clone(const Sig& rhs) {
|
||||
MOZ_MUST_USE bool clone(const Sig& rhs) {
|
||||
ret_ = rhs.ret_;
|
||||
MOZ_ASSERT(args_.empty());
|
||||
return args_.appendAll(rhs.args_);
|
||||
@@ -611,12 +611,9 @@ enum class SymbolicAddress
|
||||
StackLimit,
|
||||
ReportOverRecursed,
|
||||
OnOutOfBounds,
|
||||
OnImpreciseConversion,
|
||||
BadIndirectCall,
|
||||
UnreachableTrap,
|
||||
IntegerOverflowTrap,
|
||||
InvalidConversionToIntegerTrap,
|
||||
HandleExecutionInterrupt,
|
||||
HandleTrap,
|
||||
InvokeImport_Void,
|
||||
InvokeImport_I32,
|
||||
InvokeImport_I64,
|
||||
@@ -631,7 +628,28 @@ AddressOf(SymbolicAddress imm, ExclusiveContext* cx);
|
||||
|
||||
// Extracts low and high from an int64 object {low: int32, high: int32}, for
|
||||
// testing purposes mainly.
|
||||
bool ReadI64Object(JSContext* cx, HandleValue v, int64_t* val);
|
||||
MOZ_MUST_USE bool ReadI64Object(JSContext* cx, HandleValue v, int64_t* val);
|
||||
|
||||
// A wasm::Trap is a reason for why we reached a trap in executed code. Each
|
||||
// different trap is mapped to a different error message.
|
||||
|
||||
enum class Trap
|
||||
{
|
||||
// The Unreachable opcode has been executed.
|
||||
Unreachable,
|
||||
// An integer arithmetic operation led to an overflow.
|
||||
IntegerOverflow,
|
||||
// Trying to coerce NaN to an integer.
|
||||
InvalidConversionToInteger,
|
||||
// Integer division by zero.
|
||||
IntegerDivideByZero,
|
||||
|
||||
// (asm.js only) SIMD float to int conversion failed because the input
|
||||
// wasn't in bounds.
|
||||
ImpreciseSimdConversion,
|
||||
|
||||
Limit
|
||||
};
|
||||
|
||||
// A wasm::JumpTarget represents one of a special set of stubs that can be
|
||||
// jumped to from any function. Because wasm modules can be larger than the
|
||||
@@ -640,13 +658,16 @@ bool ReadI64Object(JSContext* cx, HandleValue v, int64_t* val);
|
||||
|
||||
enum class JumpTarget
|
||||
{
|
||||
// Traps
|
||||
Unreachable = unsigned(Trap::Unreachable),
|
||||
IntegerOverflow = unsigned(Trap::IntegerOverflow),
|
||||
InvalidConversionToInteger = unsigned(Trap::InvalidConversionToInteger),
|
||||
IntegerDivideByZero = unsigned(Trap::IntegerDivideByZero),
|
||||
ImpreciseSimdConversion = unsigned(Trap::ImpreciseSimdConversion),
|
||||
// Non-traps
|
||||
StackOverflow,
|
||||
OutOfBounds,
|
||||
ConversionError,
|
||||
BadIndirectCall,
|
||||
UnreachableTrap,
|
||||
IntegerOverflowTrap,
|
||||
InvalidConversionToIntegerTrap,
|
||||
Throw,
|
||||
Limit
|
||||
};
|
||||
|
||||
@@ -17,21 +17,21 @@ class AtomicsObject : public JSObject
|
||||
public:
|
||||
static const Class class_;
|
||||
static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global);
|
||||
static bool toString(JSContext* cx, unsigned int argc, Value* vp);
|
||||
static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
|
||||
};
|
||||
|
||||
bool atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_exchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_load(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_store(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_add(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_sub(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_and(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool atomics_wake(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_exchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_load(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_store(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_add(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_sub(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_and(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_wake(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/* asm.js callouts */
|
||||
int32_t atomics_add_asm_callout(int32_t vt, int32_t offset, int32_t value);
|
||||
@@ -45,14 +45,14 @@ int32_t atomics_xchg_asm_callout(int32_t vt, int32_t offset, int32_t value);
|
||||
class FutexRuntime
|
||||
{
|
||||
public:
|
||||
static bool initialize();
|
||||
static MOZ_MUST_USE bool initialize();
|
||||
static void destroy();
|
||||
|
||||
static void lock();
|
||||
static void unlock();
|
||||
|
||||
FutexRuntime();
|
||||
bool initInstance();
|
||||
MOZ_MUST_USE bool initInstance();
|
||||
void destroyInstance();
|
||||
|
||||
// Parameters to wake().
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
// wait() will not wake up spuriously. It will return true and
|
||||
// set *result to a return code appropriate for
|
||||
// Atomics.wait() on success, and return false on error.
|
||||
bool wait(JSContext* cx, double timeout, WaitResult* result);
|
||||
MOZ_MUST_USE bool wait(JSContext* cx, double timeout, WaitResult* result);
|
||||
|
||||
// Wake the thread represented by this Runtime.
|
||||
//
|
||||
|
||||
@@ -17,17 +17,17 @@ namespace js {
|
||||
// JSOP_EVAL which in turn calls DirectEval. Thus, even though IndirectEval is
|
||||
// the callee function object for *all* calls to eval, it is by construction
|
||||
// only ever called in the case indirect eval.
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
IndirectEval(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Performs a direct eval of |v| (a string containing code, or another value
|
||||
// that will be vacuously returned), which must correspond to the currently-
|
||||
// executing stack frame, which must be a script frame.
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
DirectEval(JSContext* cx, HandleValue v, MutableHandleValue vp);
|
||||
|
||||
// Performs a direct eval called from Ion code.
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
DirectEvalStringFromIon(JSContext* cx,
|
||||
HandleObject scopeObj, HandleScript callerScript,
|
||||
HandleValue newTargetValue, HandleString str,
|
||||
|
||||
+13
-13
@@ -38,7 +38,7 @@ InitIntlClass(JSContext* cx, HandleObject obj);
|
||||
*
|
||||
* Usage: collator = intl_Collator(locales, options)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_Collator(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ intl_Collator(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: availableLocales = intl_Collator_availableLocales()
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_Collator_availableLocales(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ intl_Collator_availableLocales(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: collations = intl_availableCollations(locale)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_availableCollations(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -73,7 +73,7 @@ intl_availableCollations(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: result = intl_CompareStrings(collator, x, y)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_CompareStrings(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ intl_CompareStrings(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: numberFormat = intl_NumberFormat(locales, options)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_NumberFormat(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -97,7 +97,7 @@ intl_NumberFormat(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: availableLocales = intl_NumberFormat_availableLocales()
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_NumberFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ intl_NumberFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: defaultNumberingSystem = intl_numberingSystem(locale)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_numberingSystem(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -118,7 +118,7 @@ intl_numberingSystem(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: formatted = intl_FormatNumber(numberFormat, x)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_FormatNumber(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ intl_FormatNumber(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: dateTimeFormat = intl_DateTimeFormat(locales, options)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_DateTimeFormat(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -142,7 +142,7 @@ intl_DateTimeFormat(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: availableLocales = intl_DateTimeFormat_availableLocales()
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_DateTimeFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -153,7 +153,7 @@ intl_DateTimeFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: calendars = intl_availableCalendars(locale)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_availableCalendars(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -164,7 +164,7 @@ intl_availableCalendars(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: pattern = intl_patternForSkeleton(locale, skeleton)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_patternForSkeleton(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
@@ -176,7 +176,7 @@ intl_patternForSkeleton(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: formatted = intl_FormatDateTime(dateTimeFormat, x)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_FormatDateTime(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
|
||||
@@ -843,29 +843,6 @@ js::InitMapClass(JSContext* cx, HandleObject obj)
|
||||
|
||||
/*** SetIterator *********************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
class SetIteratorObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
enum { TargetSlot, KindSlot, RangeSlot, SlotCount };
|
||||
static const JSFunctionSpec methods[];
|
||||
static SetIteratorObject* create(JSContext* cx, HandleObject setobj, ValueSet* data,
|
||||
SetObject::IteratorKind kind);
|
||||
static bool next(JSContext* cx, unsigned argc, Value* vp);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
|
||||
private:
|
||||
static inline bool is(HandleValue v);
|
||||
inline ValueSet::Range* range();
|
||||
inline SetObject::IteratorKind kind() const;
|
||||
static bool next_impl(JSContext* cx, const CallArgs& args);
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
static const ClassOps SetIteratorObjectClassOps = {
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
|
||||
+75
-52
@@ -37,7 +37,7 @@ class HashableValue
|
||||
|
||||
HashableValue() : value(UndefinedValue()) {}
|
||||
|
||||
bool setValue(JSContext* cx, HandleValue v);
|
||||
MOZ_MUST_USE bool setValue(JSContext* cx, HandleValue v);
|
||||
HashNumber hash() const;
|
||||
bool operator==(const HashableValue& other) const;
|
||||
HashableValue mark(JSTracer* trc) const;
|
||||
@@ -51,7 +51,7 @@ class HashableValue
|
||||
template <>
|
||||
class RootedBase<HashableValue> {
|
||||
public:
|
||||
bool setValue(JSContext* cx, HandleValue v) {
|
||||
MOZ_MUST_USE bool setValue(JSContext* cx, HandleValue v) {
|
||||
return static_cast<JS::Rooted<HashableValue>*>(this)->get().setValue(cx, v);
|
||||
}
|
||||
Value value() const {
|
||||
@@ -88,25 +88,27 @@ class MapObject : public NativeObject {
|
||||
static JSObject* initClass(JSContext* cx, JSObject* obj);
|
||||
static const Class class_;
|
||||
|
||||
static bool getKeysAndValuesInterleaved(JSContext* cx, HandleObject obj,
|
||||
static MOZ_MUST_USE bool getKeysAndValuesInterleaved(JSContext* cx, HandleObject obj,
|
||||
JS::MutableHandle<GCVector<JS::Value>> entries);
|
||||
static bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MapObject* create(JSContext* cx, HandleObject proto = nullptr);
|
||||
|
||||
// Publicly exposed Map calls for JSAPI access (webidl maplike/setlike
|
||||
// interfaces, etc.)
|
||||
static uint32_t size(JSContext *cx, HandleObject obj);
|
||||
static bool get(JSContext *cx, HandleObject obj, HandleValue key, MutableHandleValue rval);
|
||||
static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static MOZ_MUST_USE bool get(JSContext *cx, HandleObject obj, HandleValue key,
|
||||
MutableHandleValue rval);
|
||||
static MOZ_MUST_USE bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static MOZ_MUST_USE bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
|
||||
// Set call for public JSAPI exposure. Does not actually return map object
|
||||
// as stated in spec, expects caller to return a value. for instance, with
|
||||
// webidl maplike/setlike, should return interface object.
|
||||
static bool set(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val);
|
||||
static bool clear(JSContext *cx, HandleObject obj);
|
||||
static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
|
||||
static MOZ_MUST_USE bool set(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val);
|
||||
static MOZ_MUST_USE bool clear(JSContext *cx, HandleObject obj);
|
||||
static MOZ_MUST_USE bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj,
|
||||
MutableHandleValue iter);
|
||||
|
||||
private:
|
||||
static const ClassOps classOps_;
|
||||
@@ -119,29 +121,29 @@ class MapObject : public NativeObject {
|
||||
static ValueMap & extract(CallReceiver call);
|
||||
static void mark(JSTracer* trc, JSObject* obj);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool is(HandleValue v);
|
||||
static bool is(HandleObject o);
|
||||
|
||||
static bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||
|
||||
static bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool get_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool get(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool set_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool set(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool keys_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool keys(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool get_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool get(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool set_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool set(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool keys_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool keys(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
class MapIteratorObject : public NativeObject
|
||||
@@ -163,8 +165,8 @@ class MapIteratorObject : public NativeObject
|
||||
MapObject::IteratorKind kind);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
|
||||
static bool next(JSContext* cx, Handle<MapIteratorObject*> mapIterator,
|
||||
HandleArrayObject resultPairObj);
|
||||
static MOZ_MUST_USE bool next(JSContext* cx, Handle<MapIteratorObject*> mapIterator,
|
||||
HandleArrayObject resultPairObj);
|
||||
|
||||
static JSObject* createResultPair(JSContext* cx);
|
||||
|
||||
@@ -178,19 +180,21 @@ class SetObject : public NativeObject {
|
||||
static JSObject* initClass(JSContext* cx, JSObject* obj);
|
||||
static const Class class_;
|
||||
|
||||
static bool keys(JSContext *cx, HandleObject obj, JS::MutableHandle<GCVector<JS::Value>> keys);
|
||||
static bool values(JSContext *cx, unsigned argc, Value *vp);
|
||||
static bool add(JSContext *cx, HandleObject obj, HandleValue key);
|
||||
static bool has(JSContext *cx, unsigned argc, Value *vp);
|
||||
static MOZ_MUST_USE bool keys(JSContext *cx, HandleObject obj,
|
||||
JS::MutableHandle<GCVector<JS::Value>> keys);
|
||||
static MOZ_MUST_USE bool values(JSContext *cx, unsigned argc, Value *vp);
|
||||
static MOZ_MUST_USE bool add(JSContext *cx, HandleObject obj, HandleValue key);
|
||||
static MOZ_MUST_USE bool has(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
// Publicly exposed Set calls for JSAPI access (webidl maplike/setlike
|
||||
// interfaces, etc.)
|
||||
static SetObject* create(JSContext *cx, HandleObject proto = nullptr);
|
||||
static uint32_t size(JSContext *cx, HandleObject obj);
|
||||
static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static bool clear(JSContext *cx, HandleObject obj);
|
||||
static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
|
||||
static bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
|
||||
static MOZ_MUST_USE bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static MOZ_MUST_USE bool clear(JSContext *cx, HandleObject obj);
|
||||
static MOZ_MUST_USE bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj,
|
||||
MutableHandleValue iter);
|
||||
static MOZ_MUST_USE bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
|
||||
|
||||
private:
|
||||
static const ClassOps classOps_;
|
||||
@@ -209,20 +213,39 @@ class SetObject : public NativeObject {
|
||||
static bool is(HandleValue v);
|
||||
static bool is(HandleObject o);
|
||||
|
||||
static bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||
|
||||
static bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool add_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool add(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool add_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool add(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
class SetIteratorObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
enum { TargetSlot, KindSlot, RangeSlot, SlotCount };
|
||||
static const JSFunctionSpec methods[];
|
||||
static SetIteratorObject* create(JSContext* cx, HandleObject setobj, ValueSet* data,
|
||||
SetObject::IteratorKind kind);
|
||||
static bool next(JSContext* cx, unsigned argc, Value* vp);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
|
||||
private:
|
||||
static inline bool is(HandleValue v);
|
||||
inline ValueSet::Range* range();
|
||||
inline SetObject::IteratorKind kind() const;
|
||||
static MOZ_MUST_USE bool next_impl(JSContext* cx, const CallArgs& args);
|
||||
};
|
||||
|
||||
extern bool
|
||||
|
||||
@@ -241,6 +241,7 @@ function ModuleDeclarationInstantiation()
|
||||
// Step 16.iv
|
||||
InstantiateModuleFunctionDeclarations(module);
|
||||
}
|
||||
_SetCanonicalName(ModuleDeclarationInstantiation, "ModuleDeclarationInstantiation");
|
||||
|
||||
// 15.2.1.16.5 ModuleEvaluation()
|
||||
function ModuleEvaluation()
|
||||
@@ -268,6 +269,7 @@ function ModuleEvaluation()
|
||||
|
||||
return EvaluateModule(module);
|
||||
}
|
||||
_SetCanonicalName(ModuleEvaluation, "ModuleEvaluation");
|
||||
|
||||
function ModuleNamespaceEnumerate()
|
||||
{
|
||||
|
||||
@@ -790,6 +790,18 @@ ModuleObject::evaluated() const
|
||||
return getReservedSlot(EvaluatedSlot).toBoolean();
|
||||
}
|
||||
|
||||
Value
|
||||
ModuleObject::hostDefinedField() const
|
||||
{
|
||||
return getReservedSlot(HostDefinedSlot);
|
||||
}
|
||||
|
||||
void
|
||||
ModuleObject::setHostDefinedField(JS::Value value)
|
||||
{
|
||||
setReservedSlot(HostDefinedSlot, value);
|
||||
}
|
||||
|
||||
ModuleEnvironmentObject&
|
||||
ModuleObject::initialEnvironment() const
|
||||
{
|
||||
@@ -920,6 +932,29 @@ ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObje
|
||||
return ns;
|
||||
}
|
||||
|
||||
static bool
|
||||
InvokeSelfHostedMethod(JSContext* cx, HandleModuleObject self, HandlePropertyName name)
|
||||
{
|
||||
RootedValue fval(cx);
|
||||
if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), name, name, 0, &fval))
|
||||
return false;
|
||||
|
||||
RootedValue ignored(cx);
|
||||
return Call(cx, fval, self, &ignored);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ModuleObject::DeclarationInstantiation(JSContext* cx, HandleModuleObject self)
|
||||
{
|
||||
return InvokeSelfHostedMethod(cx, self, cx->names().ModuleDeclarationInstantiation);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ModuleObject::Evaluation(JSContext* cx, HandleModuleObject self)
|
||||
{
|
||||
return InvokeSelfHostedMethod(cx, self, cx->names().ModuleEvaluation);
|
||||
}
|
||||
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, NamespaceSlot)
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluated, EvaluatedSlot)
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
|
||||
@@ -961,15 +996,6 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::InitModuleClasses(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
return GlobalObject::initModuleProto(cx, global) &&
|
||||
GlobalObject::initImportEntryProto(cx, global) &&
|
||||
GlobalObject::initExportEntryProto(cx, global);
|
||||
}
|
||||
|
||||
#undef DEFINE_GETTER_FUNCTIONS
|
||||
#undef DEFINE_STRING_ACCESSOR_METHOD
|
||||
#undef DEFINE_ARRAY_SLOT_ACCESSOR
|
||||
|
||||
@@ -211,6 +211,7 @@ class ModuleObject : public NativeObject
|
||||
EnvironmentSlot,
|
||||
NamespaceSlot,
|
||||
EvaluatedSlot,
|
||||
HostDefinedSlot,
|
||||
RequestedModulesSlot,
|
||||
ImportEntriesSlot,
|
||||
LocalExportEntriesSlot,
|
||||
@@ -245,6 +246,7 @@ class ModuleObject : public NativeObject
|
||||
ModuleEnvironmentObject* environment() const;
|
||||
ModuleNamespaceObject* namespace_();
|
||||
bool evaluated() const;
|
||||
Value hostDefinedField() const;
|
||||
ArrayObject& requestedModules() const;
|
||||
ArrayObject& importEntries() const;
|
||||
ArrayObject& localExportEntries() const;
|
||||
@@ -254,14 +256,27 @@ class ModuleObject : public NativeObject
|
||||
JSObject* namespaceExports();
|
||||
IndirectBindingMap* namespaceBindings();
|
||||
|
||||
static bool DeclarationInstantiation(JSContext* cx, HandleModuleObject self);
|
||||
static bool Evaluation(JSContext* cx, HandleModuleObject self);
|
||||
|
||||
void setHostDefinedField(JS::Value value);
|
||||
|
||||
// For intrinsic_CreateModuleEnvironment.
|
||||
void createEnvironment();
|
||||
|
||||
// For BytecodeEmitter.
|
||||
bool noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun);
|
||||
|
||||
// For intrinsic_InstantiateModuleFunctionDeclarations.
|
||||
static bool instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self);
|
||||
|
||||
// For intrinsic_SetModuleEvaluated.
|
||||
void setEvaluated();
|
||||
|
||||
// For intrinsic_EvaluateModule.
|
||||
static bool evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValue rval);
|
||||
|
||||
// For intrinsic_NewModuleNamespace.
|
||||
static ModuleNamespaceObject* createNamespace(JSContext* cx, HandleModuleObject self,
|
||||
HandleObject exports);
|
||||
|
||||
@@ -326,8 +341,6 @@ class MOZ_STACK_CLASS ModuleBuilder
|
||||
ArrayObject* createArray(const GCVector<T>& vector);
|
||||
};
|
||||
|
||||
bool InitModuleClasses(JSContext* cx, HandleObject obj);
|
||||
|
||||
} // namespace js
|
||||
|
||||
template<>
|
||||
|
||||
+14
-14
@@ -19,13 +19,13 @@ class Value;
|
||||
namespace js {
|
||||
|
||||
// Object constructor native. Exposed only so the JIT can know its address.
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_valueOf(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
PlainObject*
|
||||
@@ -36,32 +36,32 @@ PlainObject*
|
||||
ObjectCreateWithTemplate(JSContext* cx, HandlePlainObject templateObj);
|
||||
|
||||
// Object methods exposed so they can be installed in the self-hosting global.
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_create(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_defineProperty(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_getOwnPropertyNames(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_getOwnPropertyDescriptor(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_getPrototypeOf(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_hasOwnProperty(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_isExtensible(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
obj_toString(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
// Exposed so SelfHosting.cpp can use it in the OwnPropertyKeys intrinsic
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
GetOwnPropertyKeys(JSContext* cx, const JS::CallArgs& args, unsigned flags);
|
||||
|
||||
/*
|
||||
@@ -69,7 +69,7 @@ GetOwnPropertyKeys(JSContext* cx, const JS::CallArgs& args, unsigned flags);
|
||||
* exposing a jsid to script for Object.getOwnProperty{Names,Symbols}
|
||||
* or scriptable proxy traps.
|
||||
*/
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
IdToStringOrSymbol(JSContext* cx, JS::HandleId id, JS::MutableHandleValue result);
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
@@ -78,7 +78,7 @@ JSString*
|
||||
ObjectToSource(JSContext* cx, JS::HandleObject obj);
|
||||
#endif // JS_HAS_TOSOURCE
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
WatchHandler(JSContext* cx, JSObject* obj, jsid id, JS::Value old,
|
||||
JS::Value* nvp, void* closure);
|
||||
|
||||
|
||||
+10
-10
@@ -30,21 +30,21 @@ typedef int pid_t;
|
||||
*
|
||||
* Returns true if no profilers fail to start.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API(bool)
|
||||
JS_StartProfiling(const char* profileName, pid_t pid);
|
||||
|
||||
/**
|
||||
* Stop any profilers that were previously started with JS_StartProfiling.
|
||||
* Returns true if no profilers fail to stop.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API(bool)
|
||||
JS_StopProfiling(const char* profileName);
|
||||
|
||||
/**
|
||||
* Write the current profile data to the given file, if applicable to whatever
|
||||
* profiler is being used.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API(bool)
|
||||
JS_DumpProfile(const char* outfile, const char* profileName);
|
||||
|
||||
/**
|
||||
@@ -52,13 +52,13 @@ JS_DumpProfile(const char* outfile, const char* profileName);
|
||||
* whether any profilers failed to pause. (Profilers that do not support
|
||||
* pause/resume do not count.)
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API(bool)
|
||||
JS_PauseProfilers(const char* profileName);
|
||||
|
||||
/**
|
||||
* Resume suspended profilers
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API(bool)
|
||||
JS_ResumeProfilers(const char* profileName);
|
||||
|
||||
/**
|
||||
@@ -71,23 +71,23 @@ JS_UnsafeGetLastProfilingError();
|
||||
|
||||
#ifdef MOZ_CALLGRIND
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
extern MOZ_MUST_USE JS_FRIEND_API(bool)
|
||||
js_StopCallgrind();
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
extern MOZ_MUST_USE JS_FRIEND_API(bool)
|
||||
js_StartCallgrind();
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
extern MOZ_MUST_USE JS_FRIEND_API(bool)
|
||||
js_DumpCallgrind(const char* outfile);
|
||||
|
||||
#endif /* MOZ_CALLGRIND */
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
extern MOZ_MUST_USE JS_FRIEND_API(bool)
|
||||
js_StartPerf();
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
extern MOZ_MUST_USE JS_FRIEND_API(bool)
|
||||
js_StopPerf();
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
@@ -39,8 +39,8 @@ class PromiseObject : public NativeObject
|
||||
return getFixedSlot(PROMISE_RESULT_SLOT);
|
||||
}
|
||||
|
||||
bool resolve(JSContext* cx, HandleValue resolutionValue);
|
||||
bool reject(JSContext* cx, HandleValue rejectionValue);
|
||||
MOZ_MUST_USE bool resolve(JSContext* cx, HandleValue resolutionValue);
|
||||
MOZ_MUST_USE bool reject(JSContext* cx, HandleValue rejectionValue);
|
||||
|
||||
double allocationTime() { return getFixedSlot(PROMISE_ALLOCATION_TIME_SLOT).toNumber(); }
|
||||
double resolutionTime() { return getFixedSlot(PROMISE_RESOLUTION_TIME_SLOT).toNumber(); }
|
||||
@@ -54,7 +54,7 @@ class PromiseObject : public NativeObject
|
||||
MOZ_ASSERT(state() != JS::PromiseState::Pending);
|
||||
return resolutionTime() - allocationTime();
|
||||
}
|
||||
bool dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> values);
|
||||
MOZ_MUST_USE bool dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> values);
|
||||
double getID();
|
||||
};
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ InitReflect(JSContext* cx, js::HandleObject obj);
|
||||
|
||||
namespace js {
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
Reflect_isExtensible(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
}
|
||||
|
||||
@@ -3747,6 +3747,9 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
|
||||
if (!pn)
|
||||
return false;
|
||||
} else {
|
||||
if (!GlobalObject::ensureModulePrototypesCreated(cx, cx->global()))
|
||||
return false;
|
||||
|
||||
Rooted<ModuleObject*> module(cx, ModuleObject::create(cx, nullptr));
|
||||
if (!module)
|
||||
return false;
|
||||
|
||||
+28
-28
@@ -30,41 +30,41 @@ enum RegExpStaticsUpdate { UpdateRegExpStatics, DontUpdateRegExpStatics };
|
||||
* |input| may be nullptr if there is no JSString corresponding to
|
||||
* |chars| and |length|.
|
||||
*/
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
|
||||
HandleLinearString input, size_t* lastIndex, bool test,
|
||||
MutableHandleValue rval);
|
||||
|
||||
/* Translation from MatchPairs to a JS array in regexp_exec()'s output format. */
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
CreateRegExpMatchResult(JSContext* cx, HandleString input, const MatchPairs& matches,
|
||||
MutableHandleValue rval);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpMatcher(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
|
||||
int32_t lastIndex, MatchPairs* maybeMatches, MutableHandleValue output);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpSearcher(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpSearcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
|
||||
int32_t lastIndex, MatchPairs* maybeMatches, int32_t* result);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpTester(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpTesterRaw(JSContext* cx, HandleObject regexp, HandleString input,
|
||||
int32_t lastIndex, int32_t* endIndex);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intrinsic_GetElemBaseForLambda(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
intrinsic_GetStringDataProperty(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
@@ -76,7 +76,7 @@ intrinsic_GetStringDataProperty(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: match = regexp_exec_no_statics(regexp, string)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_exec_no_statics(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
@@ -84,7 +84,7 @@ regexp_exec_no_statics(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: does_match = regexp_test_no_statics(regexp, string)
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_test_no_statics(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
@@ -104,58 +104,58 @@ regexp_construct_self_hosting(JSContext* cx, unsigned argc, Value* vp);
|
||||
* Dedicated function for RegExp.prototype.split optimized path.
|
||||
* sticky flag is ignored.
|
||||
*/
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_construct_no_sticky(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
IsRegExp(JSContext* cx, HandleValue value, bool* result);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpCreate(JSContext* cx, HandleValue pattern, HandleValue flags, MutableHandleValue rval);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto, uint8_t* result);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpInstanceOptimizable(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* rx, JSObject* proto, uint8_t* result);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
RegExpGetSubstitution(JSContext* cx, HandleLinearString matched, HandleLinearString string,
|
||||
size_t position, HandleObject capturesObj, HandleLinearString replacement,
|
||||
size_t firstDollarIndex, MutableHandleValue rval);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
GetFirstDollarIndex(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
GetFirstDollarIndexRaw(JSContext* cx, HandleString str, int32_t* index);
|
||||
|
||||
extern int32_t
|
||||
GetFirstDollarIndexRawFlat(JSLinearString* text);
|
||||
|
||||
// RegExp ClassSpec members used in RegExpObject.cpp.
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
extern const JSPropertySpec regexp_static_props[];
|
||||
extern const JSPropertySpec regexp_properties[];
|
||||
extern const JSFunctionSpec regexp_methods[];
|
||||
|
||||
// Used in RegExpObject::isOriginalFlagGetter.
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_global(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_ignoreCase(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
extern bool
|
||||
extern MOZ_MUST_USE bool
|
||||
regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
+28
-27
@@ -916,8 +916,9 @@ class SimdObject : public JSObject
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
static bool toString(JSContext* cx, unsigned int argc, Value* vp);
|
||||
static bool resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId, bool* resolved);
|
||||
static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
|
||||
static MOZ_MUST_USE bool resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId,
|
||||
bool* resolved);
|
||||
};
|
||||
|
||||
// These classes implement the concept containing the following constraints:
|
||||
@@ -941,7 +942,7 @@ struct Float32x4 {
|
||||
typedef float Elem;
|
||||
static const unsigned lanes = 4;
|
||||
static const SimdType type = SimdType::Float32x4;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
double d;
|
||||
if (!ToNumber(cx, v, &d))
|
||||
return false;
|
||||
@@ -957,7 +958,7 @@ struct Float64x2 {
|
||||
typedef double Elem;
|
||||
static const unsigned lanes = 2;
|
||||
static const SimdType type = SimdType::Float64x2;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToNumber(cx, v, out);
|
||||
}
|
||||
static Value ToValue(Elem value) {
|
||||
@@ -969,7 +970,7 @@ struct Int8x16 {
|
||||
typedef int8_t Elem;
|
||||
static const unsigned lanes = 16;
|
||||
static const SimdType type = SimdType::Int8x16;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToInt8(cx, v, out);
|
||||
}
|
||||
static Value ToValue(Elem value) {
|
||||
@@ -981,7 +982,7 @@ struct Int16x8 {
|
||||
typedef int16_t Elem;
|
||||
static const unsigned lanes = 8;
|
||||
static const SimdType type = SimdType::Int16x8;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToInt16(cx, v, out);
|
||||
}
|
||||
static Value ToValue(Elem value) {
|
||||
@@ -993,7 +994,7 @@ struct Int32x4 {
|
||||
typedef int32_t Elem;
|
||||
static const unsigned lanes = 4;
|
||||
static const SimdType type = SimdType::Int32x4;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToInt32(cx, v, out);
|
||||
}
|
||||
static Value ToValue(Elem value) {
|
||||
@@ -1005,7 +1006,7 @@ struct Uint8x16 {
|
||||
typedef uint8_t Elem;
|
||||
static const unsigned lanes = 16;
|
||||
static const SimdType type = SimdType::Uint8x16;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToUint8(cx, v, out);
|
||||
}
|
||||
static Value ToValue(Elem value) {
|
||||
@@ -1017,7 +1018,7 @@ struct Uint16x8 {
|
||||
typedef uint16_t Elem;
|
||||
static const unsigned lanes = 8;
|
||||
static const SimdType type = SimdType::Uint16x8;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToUint16(cx, v, out);
|
||||
}
|
||||
static Value ToValue(Elem value) {
|
||||
@@ -1029,7 +1030,7 @@ struct Uint32x4 {
|
||||
typedef uint32_t Elem;
|
||||
static const unsigned lanes = 4;
|
||||
static const SimdType type = SimdType::Uint32x4;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToUint32(cx, v, out);
|
||||
}
|
||||
static Value ToValue(Elem value) {
|
||||
@@ -1041,7 +1042,7 @@ struct Bool8x16 {
|
||||
typedef int8_t Elem;
|
||||
static const unsigned lanes = 16;
|
||||
static const SimdType type = SimdType::Bool8x16;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
*out = ToBoolean(v) ? -1 : 0;
|
||||
return true;
|
||||
}
|
||||
@@ -1054,7 +1055,7 @@ struct Bool16x8 {
|
||||
typedef int16_t Elem;
|
||||
static const unsigned lanes = 8;
|
||||
static const SimdType type = SimdType::Bool16x8;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
*out = ToBoolean(v) ? -1 : 0;
|
||||
return true;
|
||||
}
|
||||
@@ -1067,7 +1068,7 @@ struct Bool32x4 {
|
||||
typedef int32_t Elem;
|
||||
static const unsigned lanes = 4;
|
||||
static const SimdType type = SimdType::Bool32x4;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
*out = ToBoolean(v) ? -1 : 0;
|
||||
return true;
|
||||
}
|
||||
@@ -1080,7 +1081,7 @@ struct Bool64x2 {
|
||||
typedef int64_t Elem;
|
||||
static const unsigned lanes = 2;
|
||||
static const SimdType type = SimdType::Bool64x2;
|
||||
static bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
*out = ToBoolean(v) ? -1 : 0;
|
||||
return true;
|
||||
}
|
||||
@@ -1105,7 +1106,7 @@ template<typename V>
|
||||
bool IsVectorObject(HandleValue v);
|
||||
|
||||
template<typename V>
|
||||
bool ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out);
|
||||
MOZ_MUST_USE bool ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out);
|
||||
|
||||
JSObject*
|
||||
InitSimdClass(JSContext* cx, HandleObject obj);
|
||||
@@ -1118,73 +1119,73 @@ extern const JSJitInfo JitInfo_SimdFloat32x4_extractLane;
|
||||
} // namespace jit
|
||||
|
||||
#define DECLARE_SIMD_FLOAT32X4_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_float32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
FLOAT32X4_FUNCTION_LIST(DECLARE_SIMD_FLOAT32X4_FUNCTION)
|
||||
#undef DECLARE_SIMD_FLOAT32X4_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_FLOAT64X2_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_float64x2_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
FLOAT64X2_FUNCTION_LIST(DECLARE_SIMD_FLOAT64X2_FUNCTION)
|
||||
#undef DECLARE_SIMD_FLOAT64X2_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_INT8X16_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_int8x16_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
INT8X16_FUNCTION_LIST(DECLARE_SIMD_INT8X16_FUNCTION)
|
||||
#undef DECLARE_SIMD_INT8X16_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_INT16X8_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_int16x8_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
INT16X8_FUNCTION_LIST(DECLARE_SIMD_INT16X8_FUNCTION)
|
||||
#undef DECLARE_SIMD_INT16X8_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_INT32x4_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_int32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
INT32X4_FUNCTION_LIST(DECLARE_SIMD_INT32x4_FUNCTION)
|
||||
#undef DECLARE_SIMD_INT32x4_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_UINT8X16_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_uint8x16_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
UINT8X16_FUNCTION_LIST(DECLARE_SIMD_UINT8X16_FUNCTION)
|
||||
#undef DECLARE_SIMD_UINT8X16_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_UINT16X8_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_uint16x8_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
UINT16X8_FUNCTION_LIST(DECLARE_SIMD_UINT16X8_FUNCTION)
|
||||
#undef DECLARE_SIMD_UINT16X8_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_UINT32x4_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_uint32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
UINT32X4_FUNCTION_LIST(DECLARE_SIMD_UINT32x4_FUNCTION)
|
||||
#undef DECLARE_SIMD_UINT32x4_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_BOOL8X16_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_bool8x16_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
BOOL8X16_FUNCTION_LIST(DECLARE_SIMD_BOOL8X16_FUNCTION)
|
||||
#undef DECLARE_SIMD_BOOL8X16_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_BOOL16X8_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_bool16x8_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
BOOL16X8_FUNCTION_LIST(DECLARE_SIMD_BOOL16X8_FUNCTION)
|
||||
#undef DECLARE_SIMD_BOOL16X8_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_BOOL32X4_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_bool32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
BOOL32X4_FUNCTION_LIST(DECLARE_SIMD_BOOL32X4_FUNCTION)
|
||||
#undef DECLARE_SIMD_BOOL32X4_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_BOOL64x2_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
extern MOZ_MUST_USE bool \
|
||||
simd_bool64x2_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
BOOL64X2_FUNCTION_LIST(DECLARE_SIMD_BOOL64x2_FUNCTION)
|
||||
#undef DECLARE_SIMD_BOOL64x2_FUNCTION
|
||||
|
||||
@@ -39,18 +39,18 @@ class SymbolObject : public NativeObject
|
||||
setFixedSlot(PRIMITIVE_VALUE_SLOT, SymbolValue(symbol));
|
||||
}
|
||||
|
||||
static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Static methods.
|
||||
static bool for_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool keyFor(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool for_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool keyFor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Methods defined on Symbol.prototype.
|
||||
static bool toString_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool toString(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool valueOf_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool valueOf(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool toPrimitive(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool toString_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool toString(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool valueOf_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool valueOf(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool toPrimitive(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static const JSPropertySpec properties[];
|
||||
static const JSFunctionSpec methods[];
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
DefineTestingFunctions(JSContext* cx, HandleObject obj, bool fuzzingSafe, bool disableOOMFunctions);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
testingFunc_assertFloat32(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
testingFunc_assertRecoveredOnBailout(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
@@ -175,7 +175,7 @@ class TypeDescr : public NativeObject
|
||||
}
|
||||
|
||||
// Whether id is an 'own' property of objects with this descriptor.
|
||||
bool hasProperty(const JSAtomState& names, jsid id);
|
||||
MOZ_MUST_USE bool hasProperty(const JSAtomState& names, jsid id);
|
||||
|
||||
// Type descriptors may contain a list of their references for use during
|
||||
// scanning. Marking code is optimized to use this list to mark inline
|
||||
@@ -187,7 +187,7 @@ class TypeDescr : public NativeObject
|
||||
// The list is three consecutive arrays of int32_t offsets, with each array
|
||||
// terminated by -1. The arrays store offsets of string, object, and value
|
||||
// references in the descriptor, in that order.
|
||||
bool hasTraceList() const {
|
||||
MOZ_MUST_USE bool hasTraceList() const {
|
||||
return !getFixedSlot(JS_DESCR_SLOT_TRACE_LIST).isUndefined();
|
||||
}
|
||||
const int32_t* traceList() const {
|
||||
@@ -256,7 +256,7 @@ class ScalarTypeDescr : public SimpleTypeDescr
|
||||
return Type(getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32());
|
||||
}
|
||||
|
||||
static bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
// Enumerates the cases of ScalarTypeDescr::Type which have
|
||||
@@ -307,7 +307,7 @@ class ReferenceTypeDescr : public SimpleTypeDescr
|
||||
return typeName(type());
|
||||
}
|
||||
|
||||
static bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
#define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \
|
||||
@@ -340,7 +340,7 @@ class SimdTypeDescr : public ComplexTypeDescr
|
||||
static const Class class_;
|
||||
static int32_t size(SimdType t);
|
||||
static int32_t alignment(SimdType t);
|
||||
static bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool is(const Value& v);
|
||||
|
||||
SimdType type() const;
|
||||
@@ -349,7 +349,7 @@ class SimdTypeDescr : public ComplexTypeDescr
|
||||
bool IsTypedObjectClass(const Class* clasp); // Defined below
|
||||
bool IsTypedObjectArray(JSObject& obj);
|
||||
|
||||
bool CreateUserSizeAndAlignmentProperties(JSContext* cx, HandleTypeDescr obj);
|
||||
MOZ_MUST_USE bool CreateUserSizeAndAlignmentProperties(JSContext* cx, HandleTypeDescr obj);
|
||||
|
||||
class ArrayTypeDescr;
|
||||
|
||||
@@ -387,7 +387,7 @@ class ArrayMetaTypeDescr : public NativeObject
|
||||
|
||||
// This is the function that gets called when the user
|
||||
// does `new ArrayType(elem)`. It produces an array type object.
|
||||
static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -436,7 +436,7 @@ class StructMetaTypeDescr : public NativeObject
|
||||
|
||||
// This is the function that gets called when the user
|
||||
// does `new StructType(...)`. It produces a struct type object.
|
||||
static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
class StructTypeDescr : public ComplexTypeDescr
|
||||
@@ -449,7 +449,7 @@ class StructTypeDescr : public ComplexTypeDescr
|
||||
|
||||
// Set `*out` to the index of the field named `id` and returns true,
|
||||
// or return false if no such field exists.
|
||||
bool fieldIndex(jsid id, size_t* out) const;
|
||||
MOZ_MUST_USE bool fieldIndex(jsid id, size_t* out) const;
|
||||
|
||||
// Return the name of the field at index `index`.
|
||||
JSAtom& fieldName(size_t index) const;
|
||||
@@ -489,44 +489,47 @@ class TypedObject : public JSObject
|
||||
{
|
||||
static const bool IsTypedObjectClass = true;
|
||||
|
||||
static bool obj_getArrayElement(JSContext* cx,
|
||||
Handle<TypedObject*> typedObj,
|
||||
Handle<TypeDescr*> typeDescr,
|
||||
uint32_t index,
|
||||
MutableHandleValue vp);
|
||||
static MOZ_MUST_USE bool obj_getArrayElement(JSContext* cx,
|
||||
Handle<TypedObject*> typedObj,
|
||||
Handle<TypeDescr*> typeDescr,
|
||||
uint32_t index,
|
||||
MutableHandleValue vp);
|
||||
|
||||
protected:
|
||||
static const ObjectOps objectOps_;
|
||||
|
||||
HeapPtrShape shape_;
|
||||
|
||||
static bool obj_lookupProperty(JSContext* cx, HandleObject obj,
|
||||
HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp);
|
||||
static MOZ_MUST_USE bool obj_lookupProperty(JSContext* cx, HandleObject obj,
|
||||
HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp);
|
||||
|
||||
static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
ObjectOpResult& result);
|
||||
static MOZ_MUST_USE bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
ObjectOpResult& result);
|
||||
|
||||
static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
|
||||
static MOZ_MUST_USE bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
bool* foundp);
|
||||
|
||||
static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp);
|
||||
static MOZ_MUST_USE bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp);
|
||||
|
||||
static bool obj_getElement(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
static MOZ_MUST_USE bool obj_getElement(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
|
||||
static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result);
|
||||
static MOZ_MUST_USE bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
HandleValue v, HandleValue receiver,
|
||||
ObjectOpResult& result);
|
||||
|
||||
static bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc);
|
||||
static MOZ_MUST_USE bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj,
|
||||
HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc);
|
||||
|
||||
static bool obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
ObjectOpResult& result);
|
||||
static MOZ_MUST_USE bool obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
ObjectOpResult& result);
|
||||
|
||||
static bool obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
|
||||
bool enumerableOnly);
|
||||
static MOZ_MUST_USE bool obj_enumerate(JSContext* cx, HandleObject obj,
|
||||
AutoIdVector& properties, bool enumerableOnly);
|
||||
|
||||
public:
|
||||
TypedProto& typedProto() const {
|
||||
@@ -558,7 +561,7 @@ class TypedObject : public JSObject
|
||||
return typedMem() + offset;
|
||||
}
|
||||
|
||||
inline bool opaque() const;
|
||||
inline MOZ_MUST_USE bool opaque() const;
|
||||
|
||||
// Creates a new typed object whose memory is freshly allocated and
|
||||
// initialized with zeroes (or, in the case of references, an appropriate
|
||||
@@ -568,11 +571,11 @@ class TypedObject : public JSObject
|
||||
|
||||
// User-accessible constructor (`new TypeDescriptor(...)`). Note that the
|
||||
// callee here is the type descriptor.
|
||||
static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/* Accessors for self hosted code. */
|
||||
static bool GetBuffer(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool GetByteOffset(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool GetBuffer(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool GetByteOffset(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
Shape** addressOfShapeFromGC() { return shape_.unsafeUnbarrieredForTracing(); }
|
||||
};
|
||||
@@ -723,14 +726,14 @@ class InlineOpaqueTypedObject : public InlineTypedObject
|
||||
*
|
||||
* Constructs a new, unattached instance of `Handle`.
|
||||
*/
|
||||
bool NewOpaqueTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool NewOpaqueTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: NewDerivedTypedObject(typeObj, owner, offset)
|
||||
*
|
||||
* Constructs a new, unattached instance of `Handle`.
|
||||
*/
|
||||
bool NewDerivedTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool NewDerivedTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: AttachTypedObject(typedObj, newDatum, newOffset)
|
||||
@@ -738,7 +741,7 @@ bool NewDerivedTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
* Moves `typedObj` to point at the memory referenced by `newDatum` with
|
||||
* the offset `newOffset`.
|
||||
*/
|
||||
bool AttachTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool AttachTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: SetTypedObjectOffset(typedObj, offset)
|
||||
@@ -746,41 +749,41 @@ bool AttachTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
* Changes the offset for `typedObj` within its buffer to `offset`.
|
||||
* `typedObj` must already be attached.
|
||||
*/
|
||||
bool SetTypedObjectOffset(JSContext*, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool SetTypedObjectOffset(JSContext*, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: ObjectIsTypeDescr(obj)
|
||||
*
|
||||
* True if `obj` is a type object.
|
||||
*/
|
||||
bool ObjectIsTypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool ObjectIsTypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: ObjectIsTypedObject(obj)
|
||||
*
|
||||
* True if `obj` is a transparent or opaque typed object.
|
||||
*/
|
||||
bool ObjectIsTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool ObjectIsTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: ObjectIsOpaqueTypedObject(obj)
|
||||
*
|
||||
* True if `obj` is an opaque typed object.
|
||||
*/
|
||||
bool ObjectIsOpaqueTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool ObjectIsOpaqueTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: ObjectIsTransparentTypedObject(obj)
|
||||
*
|
||||
* True if `obj` is a transparent typed object.
|
||||
*/
|
||||
bool ObjectIsTransparentTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool ObjectIsTransparentTypedObject(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/* Predicates on type descriptor objects. In all cases, 'obj' must be a type descriptor. */
|
||||
|
||||
bool TypeDescrIsSimpleType(JSContext*, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool TypeDescrIsSimpleType(JSContext*, unsigned argc, Value* vp);
|
||||
|
||||
bool TypeDescrIsArrayType(JSContext*, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool TypeDescrIsArrayType(JSContext*, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: TypedObjectIsAttached(obj)
|
||||
@@ -788,21 +791,21 @@ bool TypeDescrIsArrayType(JSContext*, unsigned argc, Value* vp);
|
||||
* Given a TypedObject `obj`, returns true if `obj` is
|
||||
* "attached" (i.e., its data pointer is nullptr).
|
||||
*/
|
||||
bool TypedObjectIsAttached(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool TypedObjectIsAttached(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: TypedObjectTypeDescr(obj)
|
||||
*
|
||||
* Given a TypedObject `obj`, returns the object's type descriptor.
|
||||
*/
|
||||
bool TypedObjectTypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool TypedObjectTypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: ClampToUint8(v)
|
||||
*
|
||||
* Same as the C function ClampDoubleToUint8. `v` must be a number.
|
||||
*/
|
||||
bool ClampToUint8(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool ClampToUint8(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: GetTypedObjectModule()
|
||||
@@ -813,7 +816,7 @@ bool ClampToUint8(JSContext* cx, unsigned argc, Value* vp);
|
||||
* to access them; eventually this should be linked into the module
|
||||
* system.
|
||||
*/
|
||||
bool GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: GetSimdTypeDescr(simdTypeRepr)
|
||||
@@ -823,7 +826,7 @@ bool GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* The SIMD pseudo-module must have been initialized for this to be safe.
|
||||
*/
|
||||
bool GetSimdTypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool GetSimdTypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: Store_int8(targetDatum, targetOffset, value)
|
||||
@@ -844,7 +847,7 @@ bool GetSimdTypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
#define JS_STORE_SCALAR_CLASS_DEFN(_constant, T, _name) \
|
||||
class StoreScalar##T { \
|
||||
public: \
|
||||
static bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static const JSJitInfo JitInfo; \
|
||||
};
|
||||
|
||||
@@ -864,11 +867,11 @@ class StoreScalar##T { \
|
||||
#define JS_STORE_REFERENCE_CLASS_DEFN(_constant, T, _name) \
|
||||
class StoreReference##T { \
|
||||
private: \
|
||||
static bool store(JSContext* cx, T* heap, const Value& v, \
|
||||
TypedObject* obj, jsid id); \
|
||||
static MOZ_MUST_USE bool store(JSContext* cx, T* heap, const Value& v, \
|
||||
TypedObject* obj, jsid id); \
|
||||
\
|
||||
public: \
|
||||
static bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static const JSJitInfo JitInfo; \
|
||||
};
|
||||
|
||||
@@ -883,7 +886,7 @@ class StoreReference##T { \
|
||||
#define JS_LOAD_SCALAR_CLASS_DEFN(_constant, T, _name) \
|
||||
class LoadScalar##T { \
|
||||
public: \
|
||||
static bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static const JSJitInfo JitInfo; \
|
||||
};
|
||||
|
||||
@@ -901,7 +904,7 @@ class LoadReference##T { \
|
||||
static void load(T* heap, MutableHandleValue v); \
|
||||
\
|
||||
public: \
|
||||
static bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp); \
|
||||
static const JSJitInfo JitInfo; \
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class WeakSetObject : public NativeObject
|
||||
static const JSFunctionSpec methods[];
|
||||
|
||||
static WeakSetObject* create(JSContext* cx, HandleObject proto = nullptr);
|
||||
static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
extern JSObject*
|
||||
|
||||
@@ -177,7 +177,7 @@ GetDeflatedUTF8StringLength(JSContext* maybecx, const CharT* chars,
|
||||
size_t charsLength);
|
||||
|
||||
template <typename CharT>
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
DeflateStringToUTF8Buffer(JSContext* maybecx, const CharT* src, size_t srclen,
|
||||
char* dst, size_t* dstlenp);
|
||||
|
||||
@@ -454,7 +454,7 @@ namespace CType {
|
||||
TypeCode GetTypeCode(JSObject* typeObj);
|
||||
bool TypesEqual(JSObject* t1, JSObject* t2);
|
||||
size_t GetSize(JSObject* obj);
|
||||
bool GetSafeSize(JSObject* obj, size_t* result);
|
||||
MOZ_MUST_USE bool GetSafeSize(JSObject* obj, size_t* result);
|
||||
bool IsSizeDefined(JSObject* obj);
|
||||
size_t GetAlignment(JSObject* obj);
|
||||
ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
|
||||
@@ -478,12 +478,12 @@ namespace ArrayType {
|
||||
|
||||
JSObject* GetBaseType(JSObject* obj);
|
||||
size_t GetLength(JSObject* obj);
|
||||
bool GetSafeLength(JSObject* obj, size_t* result);
|
||||
MOZ_MUST_USE bool GetSafeLength(JSObject* obj, size_t* result);
|
||||
UniquePtrFFIType BuildFFIType(JSContext* cx, JSObject* obj);
|
||||
} // namespace ArrayType
|
||||
|
||||
namespace StructType {
|
||||
bool DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj);
|
||||
MOZ_MUST_USE bool DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj);
|
||||
|
||||
const FieldInfoHash* GetFieldInfo(JSObject* obj);
|
||||
const FieldInfo* LookupField(JSContext* cx, JSObject* obj, JSFlatString* name);
|
||||
@@ -519,9 +519,9 @@ namespace CData {
|
||||
bool IsCDataProto(JSObject* obj);
|
||||
|
||||
// Attached by JSAPI as the function 'ctypes.cast'
|
||||
bool Cast(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool Cast(JSContext* cx, unsigned argc, Value* vp);
|
||||
// Attached by JSAPI as the function 'ctypes.getRuntime'
|
||||
bool GetRuntime(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool GetRuntime(JSContext* cx, unsigned argc, Value* vp);
|
||||
} // namespace CData
|
||||
|
||||
namespace Int64 {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef ctypes_Library_h
|
||||
#define ctypes_Library_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
struct JSCTypesCallbacks;
|
||||
@@ -21,14 +23,14 @@ enum LibrarySlot {
|
||||
|
||||
namespace Library
|
||||
{
|
||||
bool Name(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
MOZ_MUST_USE bool Name(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
JSObject* Create(JSContext* cx, JS::Value path, const JSCTypesCallbacks* callbacks);
|
||||
|
||||
bool IsLibrary(JSObject* obj);
|
||||
PRLibrary* GetLibrary(JSObject* obj);
|
||||
|
||||
bool Open(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
MOZ_MUST_USE bool Open(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
} // namespace Library
|
||||
|
||||
} // namespace ctypes
|
||||
|
||||
@@ -55,6 +55,11 @@ if [ ! -f "$ABSDIR/variants/$VARIANT" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$VARIANT" = "nonunified" ]]; then
|
||||
# Hack the moz.build files to turn off unified compilation.
|
||||
find "$SOURCE/js/src" -name moz.build -exec sed -i 's/UNIFIED_SOURCES/SOURCES/' '{}' ';'
|
||||
fi
|
||||
|
||||
(cd "$SOURCE/js/src"; autoconf-2.13 || autoconf2.13 || autoconf213)
|
||||
|
||||
TRY_OVERRIDE=$SOURCE/js/src/config.try
|
||||
@@ -177,6 +182,7 @@ fi
|
||||
RUN_JSTESTS=true
|
||||
RUN_JITTEST=true
|
||||
RUN_JSAPITESTS=true
|
||||
RUN_CHECK_STYLE_ONLY=false
|
||||
|
||||
PARENT=$$
|
||||
|
||||
@@ -216,6 +222,10 @@ elif [[ "$VARIANT" = "arm-sim" ||
|
||||
"$VARIANT" = "arm-sim-osx" ||
|
||||
"$VARIANT" = "plaindebug" ]]; then
|
||||
export JSTESTS_EXTRA_ARGS=--jitflags=debug
|
||||
elif [[ "$VARIANT" = "nonunified" ]]; then
|
||||
RUN_JSTESTS=false
|
||||
RUN_JITTEST=false
|
||||
RUN_CHECK_STYLE_ONLY=true
|
||||
elif [[ "$VARIANT" = arm64* ]]; then
|
||||
# The ARM64 simulator is slow, so some tests are timing out.
|
||||
# Run a reduced set of test cases so this doesn't take hours.
|
||||
@@ -223,7 +233,11 @@ elif [[ "$VARIANT" = arm64* ]]; then
|
||||
export JITTEST_EXTRA_ARGS="--jitflags=none --args=--baseline-eager -x ion/ -x asm.js/"
|
||||
fi
|
||||
|
||||
$COMMAND_PREFIX $MAKE check || exit 1
|
||||
if $RUN_CHECK_STYLE_ONLY; then
|
||||
$COMMAND_PREFIX $MAKE check-style || exit 1
|
||||
else
|
||||
$COMMAND_PREFIX $MAKE check || exit 1
|
||||
fi
|
||||
|
||||
RESULT=0
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
--enable-debug
|
||||
@@ -768,10 +768,7 @@ frontend::CompileModule(ExclusiveContext* cx, const ReadOnlyCompileOptions& opti
|
||||
ScriptSourceObject** sourceObjectOut /* = nullptr */)
|
||||
{
|
||||
MOZ_ASSERT(srcBuf.get());
|
||||
MOZ_ASSERT(cx->isJSContext() == (alloc == nullptr));
|
||||
|
||||
if (!alloc)
|
||||
alloc = &cx->asJSContext()->tempLifoAlloc();
|
||||
MOZ_ASSERT(alloc);
|
||||
MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);
|
||||
|
||||
CompileOptions options(cx, optionsInput);
|
||||
@@ -781,19 +778,32 @@ frontend::CompileModule(ExclusiveContext* cx, const ReadOnlyCompileOptions& opti
|
||||
Rooted<StaticScope*> staticScope(cx, &cx->global()->lexicalScope().staticBlock());
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, staticScope,
|
||||
TraceLogger_ParserCompileModule);
|
||||
RootedModuleObject module(cx, compiler.compileModule());
|
||||
ModuleObject* module = compiler.compileModule();
|
||||
|
||||
// See the comment about sourceObjectOut above.
|
||||
if (sourceObjectOut)
|
||||
*sourceObjectOut = compiler.sourceObjectPtr();
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
ModuleObject*
|
||||
frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf)
|
||||
{
|
||||
if (!GlobalObject::ensureModulePrototypesCreated(cx, cx->global()))
|
||||
return nullptr;
|
||||
|
||||
LifoAlloc* alloc = &cx->asJSContext()->tempLifoAlloc();
|
||||
RootedModuleObject module(cx, CompileModule(cx, options, srcBuf, alloc));
|
||||
if (!module)
|
||||
return nullptr;
|
||||
|
||||
// This happens in GlobalHelperThreadState::finishModuleParseTask() when a
|
||||
// module is compiled off main thread.
|
||||
if (cx->isJSContext() && !ModuleObject::FreezeArrayProperties(cx->asJSContext(), module))
|
||||
if (!ModuleObject::FreezeArrayProperties(cx->asJSContext(), module))
|
||||
return nullptr;
|
||||
|
||||
// See the comment about sourceObjectOut above.
|
||||
if (sourceObjectOut)
|
||||
*sourceObjectOut = compiler.sourceObjectPtr();
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,18 +33,22 @@ CompileScript(ExclusiveContext* cx, LifoAlloc* alloc,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
|
||||
ModuleObject*
|
||||
CompileModule(ExclusiveContext *cx, const ReadOnlyCompileOptions &options,
|
||||
SourceBufferHolder &srcBuf, LifoAlloc* alloc = nullptr,
|
||||
CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf);
|
||||
|
||||
ModuleObject*
|
||||
CompileModule(ExclusiveContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, LifoAlloc* alloc,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
|
||||
|
||||
/*
|
||||
* enclosingStaticScope is a static enclosing scope (e.g. a StaticWithScope).
|
||||
* Must be null if the enclosing scope is a global.
|
||||
*/
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf,
|
||||
@@ -52,12 +56,12 @@ CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
|
||||
|
||||
// As above, but defaults to the global lexical scope as the enclosing static
|
||||
// scope.
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf);
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
CompileStarGeneratorBody(JSContext* cx, MutableHandleFunction fun,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf);
|
||||
|
||||
@@ -1938,7 +1938,8 @@ BytecodeEmitter::bindNameToSlotHelper(ParseNode* pn)
|
||||
// translated on dn.
|
||||
if (IsAliasedVarOp(op)) {
|
||||
MOZ_ASSERT(dn->isKnownAliased());
|
||||
pn->pn_scopecoord.setSlot(parser->tokenStream, dn->pn_scopecoord.slot());
|
||||
if (!pn->pn_scopecoord.setSlot(parser->tokenStream, dn->pn_scopecoord.slot()))
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!pn->isOp(op));
|
||||
|
||||
+180
-172
@@ -37,7 +37,10 @@ class CGConstList {
|
||||
Vector<Value> list;
|
||||
public:
|
||||
explicit CGConstList(ExclusiveContext* cx) : list(cx) {}
|
||||
bool append(Value v) { MOZ_ASSERT_IF(v.isString(), v.toString()->isAtom()); return list.append(v); }
|
||||
MOZ_MUST_USE bool append(Value v) {
|
||||
MOZ_ASSERT_IF(v.isString(), v.toString()->isAtom());
|
||||
return list.append(v);
|
||||
}
|
||||
size_t length() const { return list.length(); }
|
||||
void finish(ConstArray* array);
|
||||
};
|
||||
@@ -58,7 +61,7 @@ struct CGTryNoteList {
|
||||
Vector<JSTryNote> list;
|
||||
explicit CGTryNoteList(ExclusiveContext* cx) : list(cx) {}
|
||||
|
||||
bool append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
|
||||
MOZ_MUST_USE bool append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
|
||||
size_t length() const { return list.length(); }
|
||||
void finish(TryNoteArray* array);
|
||||
};
|
||||
@@ -80,7 +83,8 @@ struct CGBlockScopeList {
|
||||
Vector<CGBlockScopeNote> list;
|
||||
explicit CGBlockScopeList(ExclusiveContext* cx) : list(cx) {}
|
||||
|
||||
bool append(uint32_t scopeObjectIndex, uint32_t offset, bool inPrologue, uint32_t parent);
|
||||
MOZ_MUST_USE bool append(uint32_t scopeObjectIndex, uint32_t offset, bool inPrologue,
|
||||
uint32_t parent);
|
||||
uint32_t findEnclosingScope(uint32_t index);
|
||||
void recordEnd(uint32_t index, uint32_t offset, bool inPrologue);
|
||||
size_t length() const { return list.length(); }
|
||||
@@ -91,7 +95,7 @@ struct CGYieldOffsetList {
|
||||
Vector<uint32_t> list;
|
||||
explicit CGYieldOffsetList(ExclusiveContext* cx) : list(cx) {}
|
||||
|
||||
bool append(uint32_t offset) { return list.append(offset); }
|
||||
MOZ_MUST_USE bool append(uint32_t offset) { return list.append(offset); }
|
||||
size_t length() const { return list.length(); }
|
||||
void finish(YieldOffsetArray& array, uint32_t prologueLength);
|
||||
};
|
||||
@@ -255,8 +259,8 @@ struct BytecodeEmitter
|
||||
bool insideEval, HandleScript evalCaller,
|
||||
bool insideNonGlobalEval, TokenPos bodyPosition, EmitterMode emitterMode = Normal);
|
||||
|
||||
bool init();
|
||||
bool updateLocalsToFrameSlots();
|
||||
MOZ_MUST_USE bool init();
|
||||
MOZ_MUST_USE bool updateLocalsToFrameSlots();
|
||||
|
||||
StmtInfoBCE* innermostStmt() const { return stmtStack.innermost(); }
|
||||
StmtInfoBCE* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); }
|
||||
@@ -271,10 +275,10 @@ struct BytecodeEmitter
|
||||
}
|
||||
uint32_t computeHops(ParseNode* pn, BytecodeEmitter** bceOfDefOut);
|
||||
bool isAliasedName(BytecodeEmitter* bceOfDef, ParseNode* pn);
|
||||
bool computeDefinitionIsAliased(BytecodeEmitter* bceOfDef, Definition* dn, JSOp* op);
|
||||
MOZ_MUST_USE bool computeDefinitionIsAliased(BytecodeEmitter* bceOfDef, Definition* dn, JSOp* op);
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
bool makeAtomIndex(JSAtom* atom, jsatomid* indexp) {
|
||||
MOZ_MUST_USE bool makeAtomIndex(JSAtom* atom, jsatomid* indexp) {
|
||||
AtomIndexAddPtr p = atomIndices->lookupForAdd(atom);
|
||||
if (p) {
|
||||
*indexp = p.value();
|
||||
@@ -290,11 +294,11 @@ struct BytecodeEmitter
|
||||
}
|
||||
|
||||
bool isInLoop();
|
||||
bool checkSingletonContext();
|
||||
MOZ_MUST_USE bool checkSingletonContext();
|
||||
|
||||
// Check whether our function is in a run-once context (a toplevel
|
||||
// run-one script or a run-once lambda).
|
||||
bool checkRunOnceContext();
|
||||
MOZ_MUST_USE bool checkRunOnceContext();
|
||||
|
||||
bool needsImplicitThis();
|
||||
|
||||
@@ -334,29 +338,29 @@ struct BytecodeEmitter
|
||||
// statement, we define useless code as code with no side effects, because
|
||||
// the main effect, the value left on the stack after the code executes,
|
||||
// will be discarded by a pop bytecode.
|
||||
bool checkSideEffects(ParseNode* pn, bool* answer);
|
||||
MOZ_MUST_USE bool checkSideEffects(ParseNode* pn, bool* answer);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool checkStrictOrSloppy(JSOp op);
|
||||
MOZ_MUST_USE bool checkStrictOrSloppy(JSOp op);
|
||||
#endif
|
||||
|
||||
// Append a new source note of the given type (and therefore size) to the
|
||||
// notes dynamic array, updating noteCount. Return the new note's index
|
||||
// within the array pointed at by current->notes as outparam.
|
||||
bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr);
|
||||
bool newSrcNote2(SrcNoteType type, ptrdiff_t offset, unsigned* indexp = nullptr);
|
||||
bool newSrcNote3(SrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2,
|
||||
unsigned* indexp = nullptr);
|
||||
MOZ_MUST_USE bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr);
|
||||
MOZ_MUST_USE bool newSrcNote2(SrcNoteType type, ptrdiff_t offset, unsigned* indexp = nullptr);
|
||||
MOZ_MUST_USE bool newSrcNote3(SrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2,
|
||||
unsigned* indexp = nullptr);
|
||||
|
||||
void copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes);
|
||||
bool setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset);
|
||||
MOZ_MUST_USE bool setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset);
|
||||
|
||||
// NB: this function can add at most one extra extended delta note.
|
||||
bool addToSrcNoteDelta(jssrcnote* sn, ptrdiff_t delta);
|
||||
MOZ_MUST_USE bool addToSrcNoteDelta(jssrcnote* sn, ptrdiff_t delta);
|
||||
|
||||
// Finish taking source notes in cx's notePool. If successful, the final
|
||||
// source note count is stored in the out outparam.
|
||||
bool finishTakingSrcNotes(uint32_t* out);
|
||||
MOZ_MUST_USE bool finishTakingSrcNotes(uint32_t* out);
|
||||
|
||||
void setJumpOffsetAt(ptrdiff_t off);
|
||||
|
||||
@@ -367,46 +371,46 @@ struct BytecodeEmitter
|
||||
};
|
||||
|
||||
// Emit code for the tree rooted at pn.
|
||||
bool emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||
MOZ_MUST_USE bool emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||
|
||||
// Emit function code for the tree rooted at body.
|
||||
bool emitFunctionScript(ParseNode* body);
|
||||
MOZ_MUST_USE bool emitFunctionScript(ParseNode* body);
|
||||
|
||||
// Emit module code for the tree rooted at body.
|
||||
bool emitModuleScript(ParseNode* body);
|
||||
MOZ_MUST_USE bool emitModuleScript(ParseNode* body);
|
||||
|
||||
// If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
|
||||
// reserve a type set to store its result.
|
||||
void checkTypeSet(JSOp op);
|
||||
|
||||
void updateDepth(ptrdiff_t target);
|
||||
bool updateLineNumberNotes(uint32_t offset);
|
||||
bool updateSourceCoordNotes(uint32_t offset);
|
||||
MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
|
||||
MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
|
||||
|
||||
bool bindNameToSlot(ParseNode* pn);
|
||||
bool bindNameToSlotHelper(ParseNode* pn);
|
||||
MOZ_MUST_USE bool bindNameToSlot(ParseNode* pn);
|
||||
MOZ_MUST_USE bool bindNameToSlotHelper(ParseNode* pn);
|
||||
|
||||
void strictifySetNameNode(ParseNode* pn);
|
||||
JSOp strictifySetNameOp(JSOp op);
|
||||
|
||||
bool tryConvertFreeName(ParseNode* pn);
|
||||
MOZ_MUST_USE bool tryConvertFreeName(ParseNode* pn);
|
||||
|
||||
void popStatement();
|
||||
void pushStatement(StmtInfoBCE* stmt, StmtType type, ptrdiff_t top);
|
||||
void pushStatementInner(StmtInfoBCE* stmt, StmtType type, ptrdiff_t top);
|
||||
void pushLoopStatement(LoopStmtInfo* stmt, StmtType type, ptrdiff_t top);
|
||||
|
||||
bool enterNestedScope(StmtInfoBCE* stmt, ObjectBox* objbox, StmtType stmtType);
|
||||
bool leaveNestedScope(StmtInfoBCE* stmt);
|
||||
MOZ_MUST_USE bool enterNestedScope(StmtInfoBCE* stmt, ObjectBox* objbox, StmtType stmtType);
|
||||
MOZ_MUST_USE bool leaveNestedScope(StmtInfoBCE* stmt);
|
||||
|
||||
bool enterBlockScope(StmtInfoBCE* stmtInfo, ObjectBox* objbox, JSOp initialValueOp,
|
||||
unsigned alreadyPushed = 0);
|
||||
MOZ_MUST_USE bool enterBlockScope(StmtInfoBCE* stmtInfo, ObjectBox* objbox, JSOp initialValueOp,
|
||||
unsigned alreadyPushed = 0);
|
||||
|
||||
bool computeAliasedSlots(Handle<StaticBlockScope*> blockScope);
|
||||
MOZ_MUST_USE bool computeAliasedSlots(Handle<StaticBlockScope*> blockScope);
|
||||
|
||||
bool lookupAliasedName(HandleScript script, PropertyName* name, uint32_t* pslot,
|
||||
ParseNode* pn = nullptr);
|
||||
bool lookupAliasedNameSlot(PropertyName* name, ScopeCoordinate* sc);
|
||||
MOZ_MUST_USE bool lookupAliasedName(HandleScript script, PropertyName* name, uint32_t* pslot,
|
||||
ParseNode* pn = nullptr);
|
||||
MOZ_MUST_USE bool lookupAliasedNameSlot(PropertyName* name, ScopeCoordinate* sc);
|
||||
|
||||
// In a function, block-scoped locals go after the vars, and form part of the
|
||||
// fixed part of a stack frame. Outside a function, there are no fixed vars,
|
||||
@@ -414,145 +418,147 @@ struct BytecodeEmitter
|
||||
// and are thus addressable via GETLOCAL and friends.
|
||||
void computeLocalOffset(Handle<StaticBlockScope*> blockScope);
|
||||
|
||||
bool flushPops(int* npops);
|
||||
MOZ_MUST_USE bool flushPops(int* npops);
|
||||
|
||||
bool emitCheck(ptrdiff_t delta, ptrdiff_t* offset);
|
||||
MOZ_MUST_USE bool emitCheck(ptrdiff_t delta, ptrdiff_t* offset);
|
||||
|
||||
// Emit one bytecode.
|
||||
bool emit1(JSOp op);
|
||||
MOZ_MUST_USE bool emit1(JSOp op);
|
||||
|
||||
// Emit two bytecodes, an opcode (op) with a byte of immediate operand
|
||||
// (op1).
|
||||
bool emit2(JSOp op, uint8_t op1);
|
||||
MOZ_MUST_USE bool emit2(JSOp op, uint8_t op1);
|
||||
|
||||
// Emit three bytecodes, an opcode with two bytes of immediate operands.
|
||||
bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
|
||||
MOZ_MUST_USE bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
|
||||
|
||||
// Helper to emit JSOP_DUPAT. The argument is the value's depth on the
|
||||
// JS stack, as measured from the top.
|
||||
bool emitDupAt(unsigned slotFromTop);
|
||||
MOZ_MUST_USE bool emitDupAt(unsigned slotFromTop);
|
||||
|
||||
// Emit a bytecode followed by an uint16 immediate operand stored in
|
||||
// big-endian order.
|
||||
bool emitUint16Operand(JSOp op, uint32_t operand);
|
||||
MOZ_MUST_USE bool emitUint16Operand(JSOp op, uint32_t operand);
|
||||
|
||||
// Emit a bytecode followed by an uint32 immediate operand.
|
||||
bool emitUint32Operand(JSOp op, uint32_t operand);
|
||||
MOZ_MUST_USE bool emitUint32Operand(JSOp op, uint32_t operand);
|
||||
|
||||
// Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
|
||||
bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr);
|
||||
MOZ_MUST_USE bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr);
|
||||
|
||||
bool emitNumberOp(double dval);
|
||||
MOZ_MUST_USE bool emitNumberOp(double dval);
|
||||
|
||||
bool emitThisLiteral(ParseNode* pn);
|
||||
bool emitCreateFunctionThis();
|
||||
bool emitGetFunctionThis(ParseNode* pn);
|
||||
bool emitGetThisForSuperBase(ParseNode* pn);
|
||||
bool emitSetThis(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitThisLiteral(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitCreateFunctionThis();
|
||||
MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitGetThisForSuperBase(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSetThis(ParseNode* pn);
|
||||
|
||||
// These functions are used to emit GETLOCAL/GETALIASEDVAR or
|
||||
// SETLOCAL/SETALIASEDVAR for a particular binding on a function's
|
||||
// CallObject.
|
||||
bool emitLoadFromEnclosingFunctionScope(BindingIter& bi);
|
||||
bool emitStoreToEnclosingFunctionScope(BindingIter& bi);
|
||||
MOZ_MUST_USE bool emitLoadFromEnclosingFunctionScope(BindingIter& bi);
|
||||
MOZ_MUST_USE bool emitStoreToEnclosingFunctionScope(BindingIter& bi);
|
||||
|
||||
uint32_t computeHopsToEnclosingFunction();
|
||||
|
||||
bool emitJump(JSOp op, ptrdiff_t off, ptrdiff_t* jumpOffset = nullptr);
|
||||
bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
|
||||
MOZ_MUST_USE bool emitJump(JSOp op, ptrdiff_t off, ptrdiff_t* jumpOffset = nullptr);
|
||||
MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
|
||||
|
||||
bool emitLoopHead(ParseNode* nextpn);
|
||||
bool emitLoopEntry(ParseNode* nextpn);
|
||||
MOZ_MUST_USE bool emitLoopHead(ParseNode* nextpn);
|
||||
MOZ_MUST_USE bool emitLoopEntry(ParseNode* nextpn);
|
||||
|
||||
// Emit a backpatch op with offset pointing to the previous jump of this
|
||||
// type, so that we can walk back up the chain fixing up the op and jump
|
||||
// offset.
|
||||
bool emitBackPatchOp(ptrdiff_t* lastp);
|
||||
MOZ_MUST_USE bool emitBackPatchOp(ptrdiff_t* lastp);
|
||||
void backPatch(ptrdiff_t last, jsbytecode* target, jsbytecode op);
|
||||
|
||||
bool emitGoto(StmtInfoBCE* toStmt, ptrdiff_t* lastp, SrcNoteType noteType = SRC_NULL);
|
||||
MOZ_MUST_USE bool emitGoto(StmtInfoBCE* toStmt, ptrdiff_t* lastp,
|
||||
SrcNoteType noteType = SRC_NULL);
|
||||
|
||||
bool emitIndex32(JSOp op, uint32_t index);
|
||||
bool emitIndexOp(JSOp op, uint32_t index);
|
||||
MOZ_MUST_USE bool emitIndex32(JSOp op, uint32_t index);
|
||||
MOZ_MUST_USE bool emitIndexOp(JSOp op, uint32_t index);
|
||||
|
||||
bool emitAtomOp(JSAtom* atom, JSOp op);
|
||||
bool emitAtomOp(ParseNode* pn, JSOp op);
|
||||
MOZ_MUST_USE bool emitAtomOp(JSAtom* atom, JSOp op);
|
||||
MOZ_MUST_USE bool emitAtomOp(ParseNode* pn, JSOp op);
|
||||
|
||||
bool emitArrayLiteral(ParseNode* pn);
|
||||
bool emitArray(ParseNode* pn, uint32_t count, JSOp op);
|
||||
bool emitArrayComp(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitArrayLiteral(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count, JSOp op);
|
||||
MOZ_MUST_USE bool emitArrayComp(ParseNode* pn);
|
||||
|
||||
bool emitInternedObjectOp(uint32_t index, JSOp op);
|
||||
bool emitObjectOp(ObjectBox* objbox, JSOp op);
|
||||
bool emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2, JSOp op);
|
||||
bool emitRegExp(uint32_t index);
|
||||
MOZ_MUST_USE bool emitInternedObjectOp(uint32_t index, JSOp op);
|
||||
MOZ_MUST_USE bool emitObjectOp(ObjectBox* objbox, JSOp op);
|
||||
MOZ_MUST_USE bool emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2, JSOp op);
|
||||
MOZ_MUST_USE bool emitRegExp(uint32_t index);
|
||||
|
||||
MOZ_NEVER_INLINE bool emitFunction(ParseNode* pn, bool needsProto = false);
|
||||
MOZ_NEVER_INLINE bool emitObject(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitFunction(ParseNode* pn, bool needsProto = false);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ParseNode* pn);
|
||||
|
||||
bool emitHoistedFunctionsInList(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitHoistedFunctionsInList(ParseNode* pn);
|
||||
|
||||
bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp, PropListType type);
|
||||
MOZ_MUST_USE bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
||||
PropListType type);
|
||||
|
||||
// To catch accidental misuse, emitUint16Operand/emit3 assert that they are
|
||||
// not used to unconditionally emit JSOP_GETLOCAL. Variable access should
|
||||
// instead be emitted using EmitVarOp. In special cases, when the caller
|
||||
// definitely knows that a given local slot is unaliased, this function may be
|
||||
// used as a non-asserting version of emitUint16Operand.
|
||||
bool emitLocalOp(JSOp op, uint32_t slot);
|
||||
MOZ_MUST_USE bool emitLocalOp(JSOp op, uint32_t slot);
|
||||
|
||||
bool emitScopeCoordOp(JSOp op, ScopeCoordinate sc);
|
||||
bool emitAliasedVarOp(JSOp op, ParseNode* pn);
|
||||
bool emitAliasedVarOp(JSOp op, ScopeCoordinate sc, MaybeCheckLexical checkLexical);
|
||||
bool emitUnaliasedVarOp(JSOp op, uint32_t slot, MaybeCheckLexical checkLexical);
|
||||
MOZ_MUST_USE bool emitScopeCoordOp(JSOp op, ScopeCoordinate sc);
|
||||
MOZ_MUST_USE bool emitAliasedVarOp(JSOp op, ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitAliasedVarOp(JSOp op, ScopeCoordinate sc, MaybeCheckLexical checkLexical);
|
||||
MOZ_MUST_USE bool emitUnaliasedVarOp(JSOp op, uint32_t slot, MaybeCheckLexical checkLexical);
|
||||
|
||||
bool emitVarOp(ParseNode* pn, JSOp op);
|
||||
bool emitVarIncDec(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitVarOp(ParseNode* pn, JSOp op);
|
||||
MOZ_MUST_USE bool emitVarIncDec(ParseNode* pn);
|
||||
|
||||
bool emitNameOp(ParseNode* pn, bool callContext);
|
||||
bool emitNameIncDec(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitNameOp(ParseNode* pn, bool callContext);
|
||||
MOZ_MUST_USE bool emitNameIncDec(ParseNode* pn);
|
||||
|
||||
bool maybeEmitVarDecl(JSOp prologueOp, ParseNode* pn, jsatomid* result);
|
||||
bool emitVariables(ParseNode* pn, VarEmitOption emitOption);
|
||||
bool emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode* initializer,
|
||||
VarEmitOption emitOption);
|
||||
MOZ_MUST_USE bool maybeEmitVarDecl(JSOp prologueOp, ParseNode* pn, jsatomid* result);
|
||||
MOZ_MUST_USE bool emitVariables(ParseNode* pn, VarEmitOption emitOption);
|
||||
MOZ_MUST_USE bool emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode* initializer,
|
||||
VarEmitOption emitOption);
|
||||
|
||||
bool emitNewInit(JSProtoKey key);
|
||||
bool emitSingletonInitialiser(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitNewInit(JSProtoKey key);
|
||||
MOZ_MUST_USE bool emitSingletonInitialiser(ParseNode* pn);
|
||||
|
||||
bool emitPrepareIteratorResult();
|
||||
bool emitFinishIteratorResult(bool done);
|
||||
bool iteratorResultShape(unsigned* shape);
|
||||
MOZ_MUST_USE bool emitPrepareIteratorResult();
|
||||
MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
|
||||
MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
|
||||
|
||||
bool emitYield(ParseNode* pn);
|
||||
bool emitYieldOp(JSOp op);
|
||||
bool emitYieldStar(ParseNode* iter, ParseNode* gen);
|
||||
MOZ_MUST_USE bool emitYield(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitYieldOp(JSOp op);
|
||||
MOZ_MUST_USE bool emitYieldStar(ParseNode* iter, ParseNode* gen);
|
||||
|
||||
bool emitPropLHS(ParseNode* pn);
|
||||
bool emitPropOp(ParseNode* pn, JSOp op);
|
||||
bool emitPropIncDec(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitPropLHS(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitPropOp(ParseNode* pn, JSOp op);
|
||||
MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn);
|
||||
|
||||
bool emitComputedPropertyName(ParseNode* computedPropName);
|
||||
MOZ_MUST_USE bool emitComputedPropertyName(ParseNode* computedPropName);
|
||||
|
||||
// Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
|
||||
// opcode onto the stack in the right order. In the case of SETELEM, the
|
||||
// value to be assigned must already be pushed.
|
||||
enum class EmitElemOption { Get, Set, Call, IncDec, CompoundAssign };
|
||||
bool emitElemOperands(ParseNode* pn, EmitElemOption opts);
|
||||
MOZ_MUST_USE bool emitElemOperands(ParseNode* pn, EmitElemOption opts);
|
||||
|
||||
bool emitElemOpBase(JSOp op);
|
||||
bool emitElemOp(ParseNode* pn, JSOp op);
|
||||
bool emitElemIncDec(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitElemOpBase(JSOp op);
|
||||
MOZ_MUST_USE bool emitElemOp(ParseNode* pn, JSOp op);
|
||||
MOZ_MUST_USE bool emitElemIncDec(ParseNode* pn);
|
||||
|
||||
bool emitCatch(ParseNode* pn);
|
||||
bool emitIf(ParseNode* pn);
|
||||
bool emitWith(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitCatch(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitIf(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitWith(ParseNode* pn);
|
||||
|
||||
MOZ_NEVER_INLINE bool emitLabeledStatement(const LabeledStatement* pn);
|
||||
MOZ_NEVER_INLINE bool emitLetBlock(ParseNode* pnLet);
|
||||
MOZ_NEVER_INLINE bool emitLexicalScope(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE bool emitSwitch(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE bool emitTry(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLetBlock(ParseNode* pnLet);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(ParseNode* pn);
|
||||
|
||||
// EmitDestructuringLHS assumes the to-be-destructured value has been pushed on
|
||||
// the stack and emits code to destructure a single lhs expression (either a
|
||||
@@ -564,98 +570,99 @@ struct BytecodeEmitter
|
||||
// If emitOption is PushInitialValues, the to-be-destructured value is replaced
|
||||
// with the initial values of the N (where 0 <= N) variables assigned in the
|
||||
// lhs expression. (Same post-condition as EmitDestructuringOpsHelper)
|
||||
bool emitDestructuringLHS(ParseNode* target, VarEmitOption emitOption);
|
||||
MOZ_MUST_USE bool emitDestructuringLHS(ParseNode* target, VarEmitOption emitOption);
|
||||
|
||||
bool emitDestructuringOps(ParseNode* pattern, bool isLet = false);
|
||||
bool emitDestructuringOpsHelper(ParseNode* pattern, VarEmitOption emitOption);
|
||||
bool emitDestructuringOpsArrayHelper(ParseNode* pattern, VarEmitOption emitOption);
|
||||
bool emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOption emitOption);
|
||||
MOZ_MUST_USE bool emitDestructuringOps(ParseNode* pattern, bool isLet = false);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsHelper(ParseNode* pattern, VarEmitOption emitOption);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsArrayHelper(ParseNode* pattern, VarEmitOption emitOption);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsObjectHelper(ParseNode* pattern,
|
||||
VarEmitOption emitOption);
|
||||
|
||||
typedef bool
|
||||
(*DestructuringDeclEmitter)(BytecodeEmitter* bce, JSOp prologueOp, ParseNode* pn);
|
||||
|
||||
template <DestructuringDeclEmitter EmitName>
|
||||
bool emitDestructuringDeclsWithEmitter(JSOp prologueOp, ParseNode* pattern);
|
||||
MOZ_MUST_USE bool emitDestructuringDeclsWithEmitter(JSOp prologueOp, ParseNode* pattern);
|
||||
|
||||
bool emitDestructuringDecls(JSOp prologueOp, ParseNode* pattern);
|
||||
MOZ_MUST_USE bool emitDestructuringDecls(JSOp prologueOp, ParseNode* pattern);
|
||||
|
||||
// Emit code to initialize all destructured names to the value on the top of
|
||||
// the stack.
|
||||
bool emitInitializeDestructuringDecls(JSOp prologueOp, ParseNode* pattern);
|
||||
MOZ_MUST_USE bool emitInitializeDestructuringDecls(JSOp prologueOp, ParseNode* pattern);
|
||||
|
||||
// Throw a TypeError if the value atop the stack isn't convertible to an
|
||||
// object, with no overall effect on the stack.
|
||||
bool emitRequireObjectCoercible();
|
||||
MOZ_MUST_USE bool emitRequireObjectCoercible();
|
||||
|
||||
// emitIterator expects the iterable to already be on the stack.
|
||||
// It will replace that stack value with the corresponding iterator
|
||||
bool emitIterator();
|
||||
MOZ_MUST_USE bool emitIterator();
|
||||
|
||||
// Pops iterator from the top of the stack. Pushes the result of |.next()|
|
||||
// onto the stack.
|
||||
bool emitIteratorNext(ParseNode* pn, bool allowSelfHosted = false);
|
||||
MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, bool allowSelfHosted = false);
|
||||
|
||||
// Check if the value on top of the stack is "undefined". If so, replace
|
||||
// that value on the stack with the value defined by |defaultExpr|.
|
||||
bool emitDefault(ParseNode* defaultExpr);
|
||||
MOZ_MUST_USE bool emitDefault(ParseNode* defaultExpr);
|
||||
|
||||
bool emitCallSiteObject(ParseNode* pn);
|
||||
bool emitTemplateString(ParseNode* pn);
|
||||
bool emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs);
|
||||
MOZ_MUST_USE bool emitCallSiteObject(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitTemplateString(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs);
|
||||
|
||||
bool emitReturn(ParseNode* pn);
|
||||
bool emitStatement(ParseNode* pn);
|
||||
bool emitStatementList(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitReturn(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitStatement(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitStatementList(ParseNode* pn);
|
||||
|
||||
bool emitDeleteName(ParseNode* pn);
|
||||
bool emitDeleteProperty(ParseNode* pn);
|
||||
bool emitDeleteElement(ParseNode* pn);
|
||||
bool emitDeleteExpression(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDeleteName(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDeleteProperty(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDeleteElement(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDeleteExpression(ParseNode* pn);
|
||||
|
||||
// |op| must be JSOP_TYPEOF or JSOP_TYPEOFEXPR.
|
||||
bool emitTypeof(ParseNode* node, JSOp op);
|
||||
MOZ_MUST_USE bool emitTypeof(ParseNode* node, JSOp op);
|
||||
|
||||
bool emitUnary(ParseNode* pn);
|
||||
bool emitRightAssociative(ParseNode* pn);
|
||||
bool emitLeftAssociative(ParseNode* pn);
|
||||
bool emitLogical(ParseNode* pn);
|
||||
bool emitSequenceExpr(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitUnary(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitRightAssociative(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLeftAssociative(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLogical(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSequenceExpr(ParseNode* pn);
|
||||
|
||||
MOZ_NEVER_INLINE bool emitIncOrDec(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(ParseNode* pn);
|
||||
|
||||
bool emitConditionalExpression(ConditionalExpression& conditional);
|
||||
MOZ_MUST_USE bool emitConditionalExpression(ConditionalExpression& conditional);
|
||||
|
||||
bool isRestParameter(ParseNode* pn, bool* result);
|
||||
bool emitOptimizeSpread(ParseNode* arg0, ptrdiff_t* jmp, bool* emitted);
|
||||
MOZ_MUST_USE bool isRestParameter(ParseNode* pn, bool* result);
|
||||
MOZ_MUST_USE bool emitOptimizeSpread(ParseNode* arg0, ptrdiff_t* jmp, bool* emitted);
|
||||
|
||||
bool emitCallOrNew(ParseNode* pn);
|
||||
bool emitDebugOnlyCheckSelfHosted();
|
||||
bool emitSelfHostedCallFunction(ParseNode* pn);
|
||||
bool emitSelfHostedResumeGenerator(ParseNode* pn);
|
||||
bool emitSelfHostedForceInterpreter(ParseNode* pn);
|
||||
bool emitSelfHostedAllowContentSpread(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDebugOnlyCheckSelfHosted();
|
||||
MOZ_MUST_USE bool emitSelfHostedCallFunction(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedResumeGenerator(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedForceInterpreter(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedAllowContentSpread(ParseNode* pn);
|
||||
|
||||
bool emitComprehensionFor(ParseNode* compFor);
|
||||
bool emitComprehensionForIn(ParseNode* pn);
|
||||
bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letBlockScope);
|
||||
bool emitComprehensionForOf(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitComprehensionFor(ParseNode* compFor);
|
||||
MOZ_MUST_USE bool emitComprehensionForIn(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letBlockScope);
|
||||
MOZ_MUST_USE bool emitComprehensionForOf(ParseNode* pn);
|
||||
|
||||
bool emitDo(ParseNode* pn);
|
||||
bool emitFor(ParseNode* pn);
|
||||
bool emitForIn(ParseNode* pn);
|
||||
bool emitForInOrOfVariables(ParseNode* pn);
|
||||
bool emitCStyleFor(ParseNode* pn);
|
||||
bool emitWhile(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDo(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitFor(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitForIn(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitForInOrOfVariables(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitCStyleFor(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitWhile(ParseNode* pn);
|
||||
|
||||
bool emitBreak(PropertyName* label);
|
||||
bool emitContinue(PropertyName* label);
|
||||
MOZ_MUST_USE bool emitBreak(PropertyName* label);
|
||||
MOZ_MUST_USE bool emitContinue(PropertyName* label);
|
||||
|
||||
bool emitArgsBody(ParseNode* pn);
|
||||
bool emitDefaultsAndDestructuring(ParseNode* pn);
|
||||
bool emitLexicalInitialization(ParseNode* pn, JSOp globalDefOp);
|
||||
MOZ_MUST_USE bool emitArgsBody(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDefaultsAndDestructuring(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLexicalInitialization(ParseNode* pn, JSOp globalDefOp);
|
||||
|
||||
bool pushInitialConstants(JSOp op, unsigned n);
|
||||
bool initializeBlockScopedLocalsFromStack(Handle<StaticBlockScope*> blockScope);
|
||||
MOZ_MUST_USE bool pushInitialConstants(JSOp op, unsigned n);
|
||||
MOZ_MUST_USE bool initializeBlockScopedLocalsFromStack(Handle<StaticBlockScope*> blockScope);
|
||||
|
||||
// Emit bytecode for the spread operator.
|
||||
//
|
||||
@@ -665,17 +672,18 @@ struct BytecodeEmitter
|
||||
// |.next()| and put the results into the I-th element of array with
|
||||
// incrementing I, then push the result I (it will be original I +
|
||||
// iteration count). The stack after iteration will look like |ARRAY INDEX|.
|
||||
bool emitSpread(bool allowSelfHosted = false);
|
||||
MOZ_MUST_USE bool emitSpread(bool allowSelfHosted = false);
|
||||
|
||||
// Emit bytecode for a for-of loop. pn should be PNK_FOR, and pn->pn_left
|
||||
// should be PNK_FOROF.
|
||||
bool emitForOf(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitForOf(ParseNode* pn);
|
||||
|
||||
bool emitClass(ParseNode* pn);
|
||||
bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);
|
||||
bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||
bool emitSuperElemOperands(ParseNode* pn, EmitElemOption opts = EmitElemOption::Get);
|
||||
bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||
MOZ_MUST_USE bool emitClass(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);
|
||||
MOZ_MUST_USE bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||
MOZ_MUST_USE bool emitSuperElemOperands(ParseNode* pn,
|
||||
EmitElemOption opts = EmitElemOption::Get);
|
||||
MOZ_MUST_USE bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||
};
|
||||
|
||||
} /* namespace frontend */
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace frontend {
|
||||
// return false;
|
||||
// if (!FoldConstants(cx, &pn, parser))
|
||||
// return false;
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
FoldConstants(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>* parser);
|
||||
|
||||
inline bool
|
||||
inline MOZ_MUST_USE bool
|
||||
FoldConstants(ExclusiveContext* cx, SyntaxParseHandler::Node* pnp,
|
||||
Parser<SyntaxParseHandler>* parser)
|
||||
{
|
||||
|
||||
@@ -173,7 +173,7 @@ class FullParseHandler
|
||||
return callSite;
|
||||
}
|
||||
|
||||
bool addToCallSiteObject(ParseNode* callSiteObj, ParseNode* rawNode, ParseNode* cookedNode) {
|
||||
void addToCallSiteObject(ParseNode* callSiteObj, ParseNode* rawNode, ParseNode* cookedNode) {
|
||||
MOZ_ASSERT(callSiteObj->isKind(PNK_CALLSITEOBJ));
|
||||
|
||||
addArrayElement(callSiteObj, cookedNode);
|
||||
@@ -184,7 +184,6 @@ class FullParseHandler
|
||||
* don't want to deal with this outside this method
|
||||
*/
|
||||
setEndPosition(callSiteObj, callSiteObj->pn_head);
|
||||
return true;
|
||||
}
|
||||
|
||||
ParseNode* newThisLiteral(const TokenPos& pos, ParseNode* thisName) {
|
||||
@@ -290,7 +289,7 @@ class FullParseHandler
|
||||
return literal;
|
||||
}
|
||||
|
||||
bool addElision(ParseNode* literal, const TokenPos& pos) {
|
||||
MOZ_MUST_USE bool addElision(ParseNode* literal, const TokenPos& pos) {
|
||||
ParseNode* elision = new_<NullaryNode>(PNK_ELISION, pos);
|
||||
if (!elision)
|
||||
return false;
|
||||
@@ -299,7 +298,7 @@ class FullParseHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) {
|
||||
MOZ_MUST_USE bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) {
|
||||
TokenPos pos(begin, inner->pn_pos.end);
|
||||
ParseNode* spread = new_<UnaryNode>(PNK_SPREAD, JSOP_NOP, pos, inner);
|
||||
if (!spread)
|
||||
@@ -350,7 +349,7 @@ class FullParseHandler
|
||||
return new_<UnaryNode>(PNK_SUPERBASE, JSOP_NOP, pos, thisName);
|
||||
}
|
||||
|
||||
bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {
|
||||
MOZ_MUST_USE bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {
|
||||
// Object literals with mutated [[Prototype]] are non-constant so that
|
||||
// singleton objects will have Object.prototype as their [[Prototype]].
|
||||
setListFlag(literal, PNX_NONCONST);
|
||||
@@ -362,7 +361,7 @@ class FullParseHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addPropertyDefinition(ParseNode* literal, ParseNode* key, ParseNode* val) {
|
||||
MOZ_MUST_USE bool addPropertyDefinition(ParseNode* literal, ParseNode* key, ParseNode* val) {
|
||||
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
|
||||
@@ -377,7 +376,7 @@ class FullParseHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addShorthand(ParseNode* literal, ParseNode* name, ParseNode* expr) {
|
||||
MOZ_MUST_USE bool addShorthand(ParseNode* literal, ParseNode* name, ParseNode* expr) {
|
||||
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
MOZ_ASSERT(name->isKind(PNK_OBJECT_PROPERTY_NAME));
|
||||
@@ -392,7 +391,8 @@ class FullParseHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addObjectMethodDefinition(ParseNode* literal, ParseNode* key, ParseNode* fn, JSOp op)
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(ParseNode* literal, ParseNode* key, ParseNode* fn,
|
||||
JSOp op)
|
||||
{
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
|
||||
@@ -408,8 +408,8 @@ class FullParseHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addClassMethodDefinition(ParseNode* methodList, ParseNode* key, ParseNode* fn, JSOp op,
|
||||
bool isStatic)
|
||||
MOZ_MUST_USE bool addClassMethodDefinition(ParseNode* methodList, ParseNode* key, ParseNode* fn,
|
||||
JSOp op, bool isStatic)
|
||||
{
|
||||
MOZ_ASSERT(methodList->isKind(PNK_CLASSMETHODLIST));
|
||||
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
|
||||
@@ -445,7 +445,7 @@ class FullParseHandler
|
||||
}
|
||||
|
||||
template <typename PC>
|
||||
bool isFunctionStmt(ParseNode* stmt, PC* pc) {
|
||||
MOZ_MUST_USE bool isFunctionStmt(ParseNode* stmt, PC* pc) {
|
||||
if (!pc->sc->strict()) {
|
||||
while (stmt->isKind(PNK_LABEL))
|
||||
stmt = stmt->as<LabeledStatement>().statement();
|
||||
@@ -480,7 +480,7 @@ class FullParseHandler
|
||||
list->pn_xflags |= PNX_FUNCDEFS;
|
||||
}
|
||||
|
||||
bool prependInitialYield(ParseNode* stmtList, ParseNode* genName) {
|
||||
MOZ_MUST_USE bool prependInitialYield(ParseNode* stmtList, ParseNode* genName) {
|
||||
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
|
||||
@@ -669,10 +669,11 @@ class FullParseHandler
|
||||
return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
|
||||
}
|
||||
|
||||
inline bool addCatchBlock(ParseNode* catchList, ParseNode* letBlock,
|
||||
ParseNode* catchName, ParseNode* catchGuard, ParseNode* catchBody);
|
||||
inline MOZ_MUST_USE bool addCatchBlock(ParseNode* catchList, ParseNode* letBlock,
|
||||
ParseNode* catchName, ParseNode* catchGuard,
|
||||
ParseNode* catchBody);
|
||||
|
||||
inline bool setLastFunctionArgumentDefault(ParseNode* funcpn, ParseNode* pn);
|
||||
inline MOZ_MUST_USE bool setLastFunctionArgumentDefault(ParseNode* funcpn, ParseNode* pn);
|
||||
inline void setLastFunctionArgumentDestructuring(ParseNode* funcpn, ParseNode* pn);
|
||||
|
||||
ParseNode* newFunctionDefinition() {
|
||||
@@ -761,7 +762,7 @@ class FullParseHandler
|
||||
return node->isKind(PNK_SUPERBASE);
|
||||
}
|
||||
|
||||
inline bool finishInitializerAssignment(ParseNode* pn, ParseNode* init);
|
||||
inline MOZ_MUST_USE bool finishInitializerAssignment(ParseNode* pn, ParseNode* init);
|
||||
inline void setLexicalDeclarationOp(ParseNode* pn, JSOp op);
|
||||
|
||||
void setBeginPosition(ParseNode* pn, ParseNode* oth) {
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace frontend {
|
||||
|
||||
class ParseNode;
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE bool
|
||||
NameFunctions(ExclusiveContext* cx, ParseNode* pn);
|
||||
|
||||
} /* namespace frontend */
|
||||
|
||||
+10
-10
@@ -134,7 +134,7 @@ struct AtomThingMapPtr
|
||||
|
||||
void init() { clearMap(); }
|
||||
|
||||
bool ensureMap(ExclusiveContext* cx);
|
||||
MOZ_MUST_USE bool ensureMap(ExclusiveContext* cx);
|
||||
void releaseMap(ExclusiveContext* cx);
|
||||
|
||||
bool hasMap() const { return map_; }
|
||||
@@ -332,7 +332,7 @@ class DefinitionList
|
||||
* return true. Otherwise there is exactly one Definition in the list; do
|
||||
* nothing and return false.
|
||||
*/
|
||||
bool popFront() {
|
||||
MOZ_MUST_USE bool popFront() {
|
||||
if (!isMultiple())
|
||||
return false;
|
||||
|
||||
@@ -351,8 +351,8 @@ class DefinitionList
|
||||
* Return true on success. On OOM, report on cx and return false.
|
||||
*/
|
||||
template <typename ParseHandler>
|
||||
bool pushFront(ExclusiveContext* cx, LifoAlloc& alloc,
|
||||
typename ParseHandler::DefinitionNode defn) {
|
||||
MOZ_MUST_USE bool pushFront(ExclusiveContext* cx, LifoAlloc& alloc,
|
||||
typename ParseHandler::DefinitionNode defn) {
|
||||
Node* tail;
|
||||
if (isMultiple()) {
|
||||
tail = firstNode();
|
||||
@@ -370,8 +370,8 @@ class DefinitionList
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool appendBack(ExclusiveContext* cx, LifoAlloc& alloc,
|
||||
typename ParseHandler::DefinitionNode defn)
|
||||
MOZ_MUST_USE bool appendBack(ExclusiveContext* cx, LifoAlloc& alloc,
|
||||
typename ParseHandler::DefinitionNode defn)
|
||||
{
|
||||
Node* last = allocNode(cx, alloc, ParseHandler::definitionToBits(defn), nullptr);
|
||||
if (!last)
|
||||
@@ -454,7 +454,7 @@ class AtomDecls
|
||||
|
||||
~AtomDecls();
|
||||
|
||||
bool init();
|
||||
MOZ_MUST_USE bool init();
|
||||
|
||||
void clear() {
|
||||
map->clear();
|
||||
@@ -490,7 +490,7 @@ class AtomDecls
|
||||
}
|
||||
|
||||
/* Add-or-update a known-unique definition for |atom|. */
|
||||
bool addUnique(JSAtom* atom, DefinitionNode defn) {
|
||||
MOZ_MUST_USE bool addUnique(JSAtom* atom, DefinitionNode defn) {
|
||||
MOZ_ASSERT(map);
|
||||
AtomDefnListAddPtr p = map->lookupForAdd(atom);
|
||||
if (!p)
|
||||
@@ -500,8 +500,8 @@ class AtomDecls
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addShadow(JSAtom* atom, DefinitionNode defn);
|
||||
bool addShadowedForAnnexB(JSAtom* atom, DefinitionNode defn);
|
||||
MOZ_MUST_USE bool addShadow(JSAtom* atom, DefinitionNode defn);
|
||||
MOZ_MUST_USE bool addShadowedForAnnexB(JSAtom* atom, DefinitionNode defn);
|
||||
|
||||
/* Updating the definition for an entry that is known to exist is infallible. */
|
||||
void updateFirst(JSAtom* atom, DefinitionNode defn) {
|
||||
|
||||
@@ -59,21 +59,21 @@ class PackedScopeCoordinate
|
||||
uint32_t hops() const { MOZ_ASSERT(!isFree()); return hops_; }
|
||||
uint32_t slot() const { MOZ_ASSERT(!isFree()); return slot_; }
|
||||
|
||||
bool setSlot(TokenStream& ts, uint32_t newSlot) {
|
||||
MOZ_MUST_USE bool setSlot(TokenStream& ts, uint32_t newSlot) {
|
||||
if (newSlot >= UNKNOWN_SLOT)
|
||||
return ts.reportError(JSMSG_TOO_MANY_LOCALS);
|
||||
slot_ = newSlot;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setHops(TokenStream& ts, uint32_t newHops) {
|
||||
MOZ_MUST_USE bool setHops(TokenStream& ts, uint32_t newHops) {
|
||||
if (newHops >= UNKNOWN_HOPS)
|
||||
return ts.reportError(JSMSG_TOO_DEEP, js_function_str);
|
||||
hops_ = newHops;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set(TokenStream& ts, uint32_t newHops, uint32_t newSlot) {
|
||||
MOZ_MUST_USE bool set(TokenStream& ts, uint32_t newHops, uint32_t newSlot) {
|
||||
return setHops(ts, newHops) && setSlot(ts, newSlot);
|
||||
}
|
||||
|
||||
@@ -919,9 +919,9 @@ class ParseNode
|
||||
ForCopyOnWriteArray
|
||||
};
|
||||
|
||||
bool getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObjects, MutableHandleValue vp,
|
||||
Value* compare = nullptr, size_t ncompare = 0,
|
||||
NewObjectKind newKind = TenuredObject);
|
||||
MOZ_MUST_USE bool getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObjects,
|
||||
MutableHandleValue vp, Value* compare = nullptr,
|
||||
size_t ncompare = 0, NewObjectKind newKind = TenuredObject);
|
||||
inline bool isConstant();
|
||||
|
||||
template <class NodeType>
|
||||
@@ -1391,7 +1391,7 @@ struct CallSiteNode : public ListNode {
|
||||
return node.isKind(PNK_CALLSITEOBJ);
|
||||
}
|
||||
|
||||
bool getRawArrayValue(ExclusiveContext* cx, MutableHandleValue vp) {
|
||||
MOZ_MUST_USE bool getRawArrayValue(ExclusiveContext* cx, MutableHandleValue vp) {
|
||||
return pn_head->getConstantValue(cx, AllowObjects, vp);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -400,7 +400,7 @@ ParseContext<ParseHandler>::prepareToAddDuplicateArg(HandlePropertyName name, De
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
void
|
||||
bool
|
||||
ParseContext<ParseHandler>::updateDecl(TokenStream& ts, JSAtom* atom, Node pn)
|
||||
{
|
||||
Definition* oldDecl = decls_.lookupFirst(atom);
|
||||
@@ -424,7 +424,7 @@ ParseContext<ParseHandler>::updateDecl(TokenStream& ts, JSAtom* atom, Node pn)
|
||||
newDecl->pn_scopecoord = oldDecl->pn_scopecoord;
|
||||
newDecl->pn_dflags |= PND_BOUND;
|
||||
newDecl->setOp(JSOP_INITLEXICAL);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sc->isGlobalContext() || oldDecl->isDeoptimized()) {
|
||||
@@ -444,14 +444,16 @@ ParseContext<ParseHandler>::updateDecl(TokenStream& ts, JSAtom* atom, Node pn)
|
||||
!sc->isGlobalContext())
|
||||
{
|
||||
newDecl->pn_dflags |= PND_BOUND;
|
||||
newDecl->pn_scopecoord.setSlot(ts, i);
|
||||
if (!newDecl->pn_scopecoord.setSlot(ts, i)) {
|
||||
return false;
|
||||
}
|
||||
newDecl->setOp(JSOP_GETLOCAL);
|
||||
}
|
||||
vars_[i] = newDecl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(oldDecl->isBound());
|
||||
@@ -468,6 +470,7 @@ ParseContext<ParseHandler>::updateDecl(TokenStream& ts, JSAtom* atom, Node pn)
|
||||
MOZ_ASSERT(vars_[oldDecl->pn_scopecoord.slot()] == oldDecl);
|
||||
vars_[oldDecl->pn_scopecoord.slot()] = newDecl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
@@ -1442,7 +1445,8 @@ bool
|
||||
Parser<FullParseHandler>::makeDefIntoUse(Definition* dn, ParseNode* pn, HandleAtom atom)
|
||||
{
|
||||
/* Turn pn into a definition. */
|
||||
pc->updateDecl(tokenStream, atom, pn);
|
||||
if (!pc->updateDecl(tokenStream, atom, pn))
|
||||
return false;
|
||||
|
||||
/* Change all uses of dn to be uses of pn. */
|
||||
for (ParseNode* pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
|
||||
@@ -3007,7 +3011,8 @@ Parser<FullParseHandler>::functionArgsAndBody(InHandling inHandling, ParseNode*
|
||||
return true;
|
||||
} while (false);
|
||||
|
||||
blockScopes.resize(oldBlockScopesLength);
|
||||
if (!blockScopes.resize(oldBlockScopesLength))
|
||||
return false;
|
||||
|
||||
// Continue doing a full parse for this inner function.
|
||||
ParseContext<FullParseHandler> funpc(this, pc, pn, funbox, newDirectives);
|
||||
@@ -3079,7 +3084,8 @@ Parser<ParseHandler>::appendToCallSiteObj(Node callSiteObj)
|
||||
if (!rawNode)
|
||||
return false;
|
||||
|
||||
return handler.addToCallSiteObject(callSiteObj, rawNode, cookedNode);
|
||||
handler.addToCallSiteObject(callSiteObj, rawNode, cookedNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
||||
@@ -82,10 +82,6 @@ struct GenericParseContext
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
GenerateBlockId(TokenStream& ts, ParseContext<ParseHandler>* pc, uint32_t& blockid);
|
||||
|
||||
/*
|
||||
* The struct ParseContext stores information about the current parsing context,
|
||||
* which is part of the parser state (see the field Parser::pc). The current
|
||||
@@ -201,7 +197,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
||||
void prepareToAddDuplicateArg(HandlePropertyName name, DefinitionNode prevDecl);
|
||||
|
||||
/* See the sad story in MakeDefIntoUse. */
|
||||
void updateDecl(TokenStream& ts, JSAtom* atom, Node newDecl);
|
||||
MOZ_MUST_USE bool updateDecl(TokenStream& ts, JSAtom* atom, Node newDecl);
|
||||
|
||||
// After a script has been parsed, the parser generates the code's
|
||||
// "bindings". Bindings are a data-structure, ultimately stored in the
|
||||
@@ -288,7 +284,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
||||
|
||||
~ParseContext();
|
||||
|
||||
bool init(Parser<ParseHandler>& parser);
|
||||
MOZ_MUST_USE bool init(Parser<ParseHandler>& parser);
|
||||
|
||||
unsigned blockid() { return stmtStack.innermost() ? stmtStack.innermost()->blockid : bodyid; }
|
||||
|
||||
|
||||
@@ -213,9 +213,7 @@ class SyntaxParseHandler
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
bool addToCallSiteObject(Node callSiteObj, Node rawNode, Node cookedNode) {
|
||||
return true;
|
||||
}
|
||||
void addToCallSiteObject(Node callSiteObj, Node rawNode, Node cookedNode) {}
|
||||
|
||||
Node newThisLiteral(const TokenPos& pos, Node thisName) { return NodeGeneric; }
|
||||
Node newNullLiteral(const TokenPos& pos) { return NodeGeneric; }
|
||||
@@ -261,8 +259,8 @@ class SyntaxParseHandler
|
||||
|
||||
Node newArrayComprehension(Node body, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newArrayLiteral(uint32_t begin) { return NodeUnparenthesizedArray; }
|
||||
bool addElision(Node literal, const TokenPos& pos) { return true; }
|
||||
bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
|
||||
MOZ_MUST_USE bool addElision(Node literal, const TokenPos& pos) { return true; }
|
||||
MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
|
||||
void addArrayElement(Node literal, Node element) { }
|
||||
|
||||
Node newCall() { return NodeFunctionCall; }
|
||||
@@ -275,11 +273,11 @@ class SyntaxParseHandler
|
||||
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; }
|
||||
|
||||
bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
||||
bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
|
||||
bool addShorthand(Node literal, Node name, Node expr) { return true; }
|
||||
bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
||||
bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
|
||||
MOZ_MUST_USE bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addShorthand(Node literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
||||
MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
|
||||
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
|
||||
Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
|
||||
|
||||
@@ -288,7 +286,7 @@ class SyntaxParseHandler
|
||||
Node newStatementList(unsigned blockid, const TokenPos& pos) { return NodeGeneric; }
|
||||
void addStatementToList(Node list, Node stmt, ParseContext<SyntaxParseHandler>* pc) {}
|
||||
void addCaseStatementToList(Node list, Node stmt, ParseContext<SyntaxParseHandler>* pc) {}
|
||||
bool prependInitialYield(Node stmtList, Node gen) { return true; }
|
||||
MOZ_MUST_USE bool prependInitialYield(Node stmtList, Node gen) { return true; }
|
||||
Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; }
|
||||
|
||||
Node newSetThis(Node thisName, Node value) { return value; }
|
||||
@@ -323,10 +321,10 @@ class SyntaxParseHandler
|
||||
|
||||
Node newPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeElement; }
|
||||
|
||||
bool addCatchBlock(Node catchList, Node letBlock,
|
||||
Node catchName, Node catchGuard, Node catchBody) { return true; }
|
||||
MOZ_MUST_USE bool addCatchBlock(Node catchList, Node letBlock, Node catchName,
|
||||
Node catchGuard, Node catchBody) { return true; }
|
||||
|
||||
bool setLastFunctionArgumentDefault(Node funcpn, Node pn) { return true; }
|
||||
MOZ_MUST_USE bool setLastFunctionArgumentDefault(Node funcpn, Node pn) { return true; }
|
||||
void setLastFunctionArgumentDestructuring(Node funcpn, Node pn) {}
|
||||
Node newFunctionDefinition() { return NodeFunctionDefinition; }
|
||||
void setFunctionBody(Node pn, Node kid) {}
|
||||
@@ -366,7 +364,7 @@ class SyntaxParseHandler
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
bool finishInitializerAssignment(Node pn, Node init) { return true; }
|
||||
MOZ_MUST_USE bool finishInitializerAssignment(Node pn, Node init) { return true; }
|
||||
void setLexicalDeclarationOp(Node pn, JSOp op) {}
|
||||
|
||||
void setBeginPosition(Node pn, Node oth) {}
|
||||
|
||||
@@ -343,7 +343,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
|
||||
~TokenStream();
|
||||
|
||||
bool checkOptions();
|
||||
MOZ_MUST_USE bool checkOptions();
|
||||
|
||||
// Accessors.
|
||||
const Token& currentToken() const { return tokens[cursor]; }
|
||||
@@ -436,7 +436,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
bool strictMode() const { return strictModeGetter && strictModeGetter->strictMode(); }
|
||||
|
||||
static JSAtom* atomize(ExclusiveContext* cx, CharBuffer& cb);
|
||||
bool putIdentInTokenbuf(const char16_t* identStart);
|
||||
MOZ_MUST_USE bool putIdentInTokenbuf(const char16_t* identStart);
|
||||
|
||||
struct Flags
|
||||
{
|
||||
@@ -536,7 +536,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
|
||||
// Advance to the next token. If the token stream encountered an error,
|
||||
// return false. Otherwise return true and store the token kind in |*ttp|.
|
||||
bool getToken(TokenKind* ttp, Modifier modifier = None) {
|
||||
MOZ_MUST_USE bool getToken(TokenKind* ttp, Modifier modifier = None) {
|
||||
// Check for a pushed-back token resulting from mismatching lookahead.
|
||||
if (lookahead != 0) {
|
||||
MOZ_ASSERT(!flags.hadError);
|
||||
@@ -559,7 +559,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
cursor = (cursor - 1) & ntokensMask;
|
||||
}
|
||||
|
||||
bool peekToken(TokenKind* ttp, Modifier modifier = None) {
|
||||
MOZ_MUST_USE bool peekToken(TokenKind* ttp, Modifier modifier = None) {
|
||||
if (lookahead > 0) {
|
||||
MOZ_ASSERT(!flags.hadError);
|
||||
verifyConsistentModifier(modifier, nextToken());
|
||||
@@ -572,7 +572,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peekTokenPos(TokenPos* posp, Modifier modifier = None) {
|
||||
MOZ_MUST_USE bool peekTokenPos(TokenPos* posp, Modifier modifier = None) {
|
||||
if (lookahead == 0) {
|
||||
TokenKind tt;
|
||||
if (!getTokenInternal(&tt, modifier))
|
||||
@@ -593,7 +593,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
// TOK_EOL is actually created, just a TOK_EOL TokenKind is returned, and
|
||||
// currentToken() shouldn't be consulted. (This is the only place TOK_EOL
|
||||
// is produced.)
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
MOZ_ALWAYS_INLINE MOZ_MUST_USE bool
|
||||
peekTokenSameLine(TokenKind* ttp, Modifier modifier = None) {
|
||||
const Token& curr = currentToken();
|
||||
|
||||
@@ -634,7 +634,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
}
|
||||
|
||||
// Get the next token from the stream if its kind is |tt|.
|
||||
bool matchToken(bool* matchedp, TokenKind tt, Modifier modifier = None) {
|
||||
MOZ_MUST_USE bool matchToken(bool* matchedp, TokenKind tt, Modifier modifier = None) {
|
||||
TokenKind token;
|
||||
if (!getToken(&token, modifier))
|
||||
return false;
|
||||
@@ -664,8 +664,8 @@ class MOZ_STACK_CLASS TokenStream
|
||||
// on a new line is the start of an ExpressionStatement, not a continuation
|
||||
// of a StatementListItem (or ImportDeclaration or ExportDeclaration, in
|
||||
// modules).
|
||||
bool matchContextualKeyword(bool* matchedp, Handle<PropertyName*> keyword,
|
||||
Modifier modifier = None)
|
||||
MOZ_MUST_USE bool matchContextualKeyword(bool* matchedp, Handle<PropertyName*> keyword,
|
||||
Modifier modifier = None)
|
||||
{
|
||||
TokenKind token;
|
||||
if (!getToken(&token, modifier))
|
||||
@@ -684,7 +684,7 @@ class MOZ_STACK_CLASS TokenStream
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextTokenEndsExpr(bool* endsExpr) {
|
||||
MOZ_MUST_USE bool nextTokenEndsExpr(bool* endsExpr) {
|
||||
TokenKind tt;
|
||||
if (!peekToken(&tt))
|
||||
return false;
|
||||
@@ -715,10 +715,10 @@ class MOZ_STACK_CLASS TokenStream
|
||||
Token lookaheadTokens[maxLookahead];
|
||||
};
|
||||
|
||||
bool advance(size_t position);
|
||||
MOZ_MUST_USE bool advance(size_t position);
|
||||
void tell(Position*);
|
||||
void seek(const Position& pos);
|
||||
bool seek(const Position& pos, const TokenStream& other);
|
||||
MOZ_MUST_USE bool seek(const Position& pos, const TokenStream& other);
|
||||
#ifdef DEBUG
|
||||
inline bool debugHasNoLookahead() const {
|
||||
return lookahead == 0;
|
||||
@@ -759,10 +759,10 @@ class MOZ_STACK_CLASS TokenStream
|
||||
// null, report a SyntaxError ("if is a reserved identifier") and return
|
||||
// false. If ttp is non-null, return true with the keyword's TokenKind in
|
||||
// *ttp.
|
||||
bool checkForKeyword(JSAtom* atom, TokenKind* ttp);
|
||||
MOZ_MUST_USE bool checkForKeyword(JSAtom* atom, TokenKind* ttp);
|
||||
|
||||
// Same semantics as above, but for the provided keyword.
|
||||
bool checkForKeyword(const KeywordInfo* kw, TokenKind* ttp);
|
||||
MOZ_MUST_USE bool checkForKeyword(const KeywordInfo* kw, TokenKind* ttp);
|
||||
|
||||
// This class maps a userbuf offset (which is 0-indexed) to a line number
|
||||
// (which is 1-indexed) and a column index (which is 0-indexed).
|
||||
@@ -817,8 +817,8 @@ class MOZ_STACK_CLASS TokenStream
|
||||
public:
|
||||
SourceCoords(ExclusiveContext* cx, uint32_t ln);
|
||||
|
||||
bool add(uint32_t lineNum, uint32_t lineStartOffset);
|
||||
bool fill(const SourceCoords& other);
|
||||
MOZ_MUST_USE bool add(uint32_t lineNum, uint32_t lineStartOffset);
|
||||
MOZ_MUST_USE bool fill(const SourceCoords& other);
|
||||
|
||||
bool isOnThisLine(uint32_t offset, uint32_t lineNum, bool* onThisLine) const {
|
||||
uint32_t lineIndex = lineNumToIndex(lineNum);
|
||||
@@ -957,10 +957,10 @@ class MOZ_STACK_CLASS TokenStream
|
||||
const char16_t* ptr; // next char to get
|
||||
};
|
||||
|
||||
bool getTokenInternal(TokenKind* ttp, Modifier modifier);
|
||||
MOZ_MUST_USE bool getTokenInternal(TokenKind* ttp, Modifier modifier);
|
||||
|
||||
bool getBracedUnicode(uint32_t* code);
|
||||
bool getStringOrTemplateToken(int untilChar, Token** tp);
|
||||
MOZ_MUST_USE bool getBracedUnicode(uint32_t* code);
|
||||
MOZ_MUST_USE bool getStringOrTemplateToken(int untilChar, Token** tp);
|
||||
|
||||
int32_t getChar();
|
||||
int32_t getCharIgnoreEOL();
|
||||
@@ -972,13 +972,13 @@ class MOZ_STACK_CLASS TokenStream
|
||||
bool matchUnicodeEscapeIdent(int32_t* c);
|
||||
bool peekChars(int n, char16_t* cp);
|
||||
|
||||
bool getDirectives(bool isMultiline, bool shouldWarnDeprecated);
|
||||
bool getDirective(bool isMultiline, bool shouldWarnDeprecated,
|
||||
const char* directive, int directiveLength,
|
||||
const char* errorMsgPragma,
|
||||
UniquePtr<char16_t[], JS::FreePolicy>* destination);
|
||||
bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated);
|
||||
bool getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated);
|
||||
MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated);
|
||||
MOZ_MUST_USE bool getDirective(bool isMultiline, bool shouldWarnDeprecated,
|
||||
const char* directive, int directiveLength,
|
||||
const char* errorMsgPragma,
|
||||
UniquePtr<char16_t[], JS::FreePolicy>* destination);
|
||||
MOZ_MUST_USE bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated);
|
||||
MOZ_MUST_USE bool getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated);
|
||||
|
||||
// |expect| cannot be an EOL char.
|
||||
bool matchChar(int32_t expect) {
|
||||
|
||||
+2
-15
@@ -217,23 +217,10 @@ js::Allocate(ExclusiveContext* cx)
|
||||
return GCRuntime::tryNewTenuredThing<T, allowGC>(cx, kind, thingSize);
|
||||
}
|
||||
|
||||
#define FOR_ALL_NON_OBJECT_GC_LAYOUTS(macro) \
|
||||
macro(JS::Symbol) \
|
||||
macro(JSExternalString) \
|
||||
macro(JSFatInlineString) \
|
||||
macro(JSScript) \
|
||||
macro(JSString) \
|
||||
macro(js::AccessorShape) \
|
||||
macro(js::BaseShape) \
|
||||
macro(js::LazyScript) \
|
||||
macro(js::ObjectGroup) \
|
||||
macro(js::Shape) \
|
||||
macro(js::jit::JitCode)
|
||||
|
||||
#define DECL_ALLOCATOR_INSTANCES(type) \
|
||||
#define DECL_ALLOCATOR_INSTANCES(allocKind, traceKind, type, sizedType) \
|
||||
template type* js::Allocate<type, NoGC>(ExclusiveContext* cx);\
|
||||
template type* js::Allocate<type, CanGC>(ExclusiveContext* cx);
|
||||
FOR_ALL_NON_OBJECT_GC_LAYOUTS(DECL_ALLOCATOR_INSTANCES)
|
||||
FOR_EACH_NONOBJECT_ALLOCKIND(DECL_ALLOCATOR_INSTANCES)
|
||||
#undef DECL_ALLOCATOR_INSTANCES
|
||||
|
||||
template <typename T, AllowGC allowGC>
|
||||
|
||||
@@ -85,7 +85,12 @@ class MOZ_RAII AutoStopVerifyingBarriers
|
||||
AutoStopVerifyingBarriers(JSRuntime* rt, bool isShutdown)
|
||||
: gc(&rt->gc)
|
||||
{
|
||||
restartPreVerifier = gc->endVerifyPreBarriers() && !isShutdown;
|
||||
if (gc->isVerifyPreBarriersEnabled()) {
|
||||
gc->endVerifyPreBarriers();
|
||||
restartPreVerifier = !isShutdown;
|
||||
} else {
|
||||
restartPreVerifier = false;
|
||||
}
|
||||
}
|
||||
|
||||
~AutoStopVerifyingBarriers() {
|
||||
@@ -115,8 +120,8 @@ struct MOZ_RAII AutoStopVerifyingBarriers
|
||||
#endif /* JS_GC_ZEAL */
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
void
|
||||
CheckHashTablesAfterMovingGC(JSRuntime* rt);
|
||||
void CheckHashTablesAfterMovingGC(JSRuntime* rt);
|
||||
void CheckHeapAfterMovingGC(JSRuntime* rt);
|
||||
#endif
|
||||
|
||||
struct MovingTracer : JS::CallbackTracer
|
||||
|
||||
+27
-22
@@ -194,7 +194,7 @@ class GCSchedulingTunables
|
||||
unsigned minEmptyChunkCount(const AutoLockGC&) const { return minEmptyChunkCount_; }
|
||||
unsigned maxEmptyChunkCount() const { return maxEmptyChunkCount_; }
|
||||
|
||||
bool setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock);
|
||||
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -584,7 +584,7 @@ class GCRuntime
|
||||
{
|
||||
public:
|
||||
explicit GCRuntime(JSRuntime* rt);
|
||||
bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
|
||||
MOZ_MUST_USE bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
|
||||
void finishRoots();
|
||||
void finish();
|
||||
|
||||
@@ -593,17 +593,18 @@ class GCRuntime
|
||||
inline bool upcomingZealousGC();
|
||||
inline bool needZealousGC();
|
||||
|
||||
bool addRoot(Value* vp, const char* name);
|
||||
MOZ_MUST_USE bool addRoot(Value* vp, const char* name);
|
||||
void removeRoot(Value* vp);
|
||||
void setMarkStackLimit(size_t limit, AutoLockGC& lock);
|
||||
|
||||
bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
|
||||
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
|
||||
uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock);
|
||||
|
||||
bool triggerGC(JS::gcreason::Reason reason);
|
||||
MOZ_MUST_USE bool triggerGC(JS::gcreason::Reason reason);
|
||||
void maybeAllocTriggerZoneGC(Zone* zone, const AutoLockGC& lock);
|
||||
// The return value indicates if we were able to do the GC.
|
||||
bool triggerZoneGC(Zone* zone, JS::gcreason::Reason reason);
|
||||
bool maybeGC(Zone* zone);
|
||||
MOZ_MUST_USE bool maybeGC(Zone* zone);
|
||||
void maybePeriodicFullGC();
|
||||
void minorGC(JS::gcreason::Reason reason) {
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
|
||||
@@ -614,6 +615,7 @@ class GCRuntime
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_EVICT_NURSERY);
|
||||
minorGCImpl(reason, nullptr);
|
||||
}
|
||||
// The return value indicates whether a major GC was performed.
|
||||
bool gcIfRequested(JSContext* cx = nullptr);
|
||||
void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason);
|
||||
void startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0);
|
||||
@@ -626,7 +628,7 @@ class GCRuntime
|
||||
void triggerFullGCForAtoms() {
|
||||
MOZ_ASSERT(fullGCForAtomsRequested_);
|
||||
fullGCForAtomsRequested_ = false;
|
||||
triggerGC(JS::gcreason::ALLOC_TRIGGER);
|
||||
MOZ_RELEASE_ASSERT(triggerGC(JS::gcreason::ALLOC_TRIGGER));
|
||||
}
|
||||
|
||||
void runDebugGC();
|
||||
@@ -755,7 +757,7 @@ class GCRuntime
|
||||
bool isCompactingGCEnabled() const;
|
||||
|
||||
void setGrayRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||
bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||
MOZ_MUST_USE bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||
void removeBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||
|
||||
void setMaxMallocBytes(size_t value);
|
||||
@@ -770,11 +772,13 @@ class GCRuntime
|
||||
void setObjectsTenuredCallback(JSObjectsTenuredCallback callback,
|
||||
void* data);
|
||||
void callObjectsTenuredCallback();
|
||||
bool addFinalizeCallback(JSFinalizeCallback callback, void* data);
|
||||
MOZ_MUST_USE bool addFinalizeCallback(JSFinalizeCallback callback, void* data);
|
||||
void removeFinalizeCallback(JSFinalizeCallback func);
|
||||
bool addWeakPointerZoneGroupCallback(JSWeakPointerZoneGroupCallback callback, void* data);
|
||||
MOZ_MUST_USE bool addWeakPointerZoneGroupCallback(JSWeakPointerZoneGroupCallback callback,
|
||||
void* data);
|
||||
void removeWeakPointerZoneGroupCallback(JSWeakPointerZoneGroupCallback callback);
|
||||
bool addWeakPointerCompartmentCallback(JSWeakPointerCompartmentCallback callback, void* data);
|
||||
MOZ_MUST_USE bool addWeakPointerCompartmentCallback(JSWeakPointerCompartmentCallback callback,
|
||||
void* data);
|
||||
void removeWeakPointerCompartmentCallback(JSWeakPointerCompartmentCallback callback);
|
||||
JS::GCSliceCallback setSliceCallback(JS::GCSliceCallback callback);
|
||||
JS::GCNurseryCollectionCallback setNurseryCollectionCallback(
|
||||
@@ -807,8 +811,6 @@ class GCRuntime
|
||||
bool isFullGc() const { return isFull; }
|
||||
bool isCompactingGc() const { return isCompacting; }
|
||||
|
||||
bool shouldCleanUpEverything() { return cleanUpEverything; }
|
||||
|
||||
bool areGrayBitsValid() const { return grayBitsValid; }
|
||||
void setGrayBitsInvalid() { grayBitsValid = false; }
|
||||
|
||||
@@ -843,7 +845,7 @@ class GCRuntime
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
void startVerifyPreBarriers();
|
||||
bool endVerifyPreBarriers();
|
||||
void endVerifyPreBarriers();
|
||||
void finishVerifier();
|
||||
bool isVerifyPreBarriersEnabled() const { return !!verifyPreData; }
|
||||
#else
|
||||
@@ -862,7 +864,7 @@ class GCRuntime
|
||||
|
||||
// Allocator
|
||||
template <AllowGC allowGC>
|
||||
bool checkAllocatorState(JSContext* cx, AllocKind kind);
|
||||
MOZ_MUST_USE bool checkAllocatorState(JSContext* cx, AllocKind kind);
|
||||
template <AllowGC allowGC>
|
||||
JSObject* tryNewNurseryObject(JSContext* cx, size_t thingSize, size_t nDynamicSlots,
|
||||
const Class* clasp);
|
||||
@@ -890,7 +892,7 @@ class GCRuntime
|
||||
void arenaAllocatedDuringGC(JS::Zone* zone, Arena* arena);
|
||||
|
||||
// Allocator internals
|
||||
bool gcIfNeededPerAllocation(JSContext* cx);
|
||||
MOZ_MUST_USE bool gcIfNeededPerAllocation(JSContext* cx);
|
||||
template <typename T>
|
||||
static void checkIncrementalZoneState(ExclusiveContext* cx, T* t);
|
||||
static void* refillFreeListFromAnyThread(ExclusiveContext* cx, AllocKind thingKind,
|
||||
@@ -923,16 +925,17 @@ class GCRuntime
|
||||
|
||||
// Check if the system state is such that GC has been supressed
|
||||
// or otherwise delayed.
|
||||
bool checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason);
|
||||
MOZ_MUST_USE bool checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason);
|
||||
|
||||
gcstats::ZoneGCStats scanZonesBeforeGC();
|
||||
void collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::Reason reason) JS_HAZ_GC_CALL;
|
||||
bool gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::Reason reason);
|
||||
MOZ_MUST_USE bool gcCycle(bool nonincrementalByAPI, SliceBudget& budget,
|
||||
JS::gcreason::Reason reason);
|
||||
void incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason reason);
|
||||
|
||||
void pushZealSelectedObjects();
|
||||
void purgeRuntime();
|
||||
bool beginMarkPhase(JS::gcreason::Reason reason);
|
||||
MOZ_MUST_USE bool beginMarkPhase(JS::gcreason::Reason reason);
|
||||
bool shouldPreserveJITCode(JSCompartment* comp, int64_t currentTime,
|
||||
JS::gcreason::Reason reason);
|
||||
void bufferGrayRoots();
|
||||
@@ -948,7 +951,7 @@ class GCRuntime
|
||||
|
||||
void beginSweepPhase(bool lastGC);
|
||||
void findZoneGroups();
|
||||
bool findZoneEdgesForWeakMaps();
|
||||
MOZ_MUST_USE bool findZoneEdgesForWeakMaps();
|
||||
void getNextZoneGroup();
|
||||
void endMarkingZoneGroup();
|
||||
void beginSweepingZoneGroup();
|
||||
@@ -969,8 +972,8 @@ class GCRuntime
|
||||
void endCompactPhase(JS::gcreason::Reason reason);
|
||||
void sweepTypesAfterCompacting(Zone* zone);
|
||||
void sweepZoneAfterCompacting(Zone* zone);
|
||||
bool relocateArenas(Zone* zone, JS::gcreason::Reason reason, Arena*& relocatedListOut,
|
||||
SliceBudget& sliceBudget);
|
||||
MOZ_MUST_USE bool relocateArenas(Zone* zone, JS::gcreason::Reason reason,
|
||||
Arena*& relocatedListOut, SliceBudget& sliceBudget);
|
||||
void updateTypeDescrObjects(MovingTracer* trc, Zone* zone);
|
||||
void updateCellPointers(MovingTracer* trc, Zone* zone, AllocKinds kinds, size_t bgTaskCount);
|
||||
void updateAllCellPointers(MovingTracer* trc, Zone* zone);
|
||||
@@ -1049,6 +1052,8 @@ class GCRuntime
|
||||
*/
|
||||
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> numArenasFreeCommitted;
|
||||
VerifyPreTracer* verifyPreData;
|
||||
|
||||
private:
|
||||
bool chunkAllocationSinceLastGC;
|
||||
int64_t nextFullGCTime;
|
||||
int64_t lastGCTime;
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ namespace gc {
|
||||
|
||||
#ifdef JS_GC_TRACE
|
||||
|
||||
extern bool InitTrace(GCRuntime& gc);
|
||||
extern MOZ_MUST_USE bool InitTrace(GCRuntime& gc);
|
||||
extern void FinishTrace();
|
||||
extern bool TraceEnabled();
|
||||
extern void TraceNurseryAlloc(Cell* thing, size_t size);
|
||||
@@ -33,7 +33,7 @@ extern void TraceTypeNewScript(js::ObjectGroup* group);
|
||||
|
||||
#else
|
||||
|
||||
inline bool InitTrace(GCRuntime& gc) { return true; }
|
||||
inline MOZ_MUST_USE bool InitTrace(GCRuntime& gc) { return true; }
|
||||
inline void FinishTrace() {}
|
||||
inline bool TraceEnabled() { return false; }
|
||||
inline void TraceNurseryAlloc(Cell* thing, size_t size) {}
|
||||
|
||||
+60
-37
@@ -53,6 +53,7 @@ extern bool
|
||||
CurrentThreadIsIonCompiling();
|
||||
#endif
|
||||
|
||||
// The return value indicates if anything was unmarked.
|
||||
extern bool
|
||||
UnmarkGrayCellRecursively(gc::Cell* cell, JS::TraceKind kind);
|
||||
|
||||
@@ -113,11 +114,60 @@ enum class AllocKind {
|
||||
LAST = LIMIT - 1
|
||||
};
|
||||
|
||||
// Macro to enumerate the different allocation kinds supplying information about
|
||||
// the trace kind, C++ type and allocation size.
|
||||
#define FOR_EACH_OBJECT_ALLOCKIND(D) \
|
||||
/* AllocKind TraceKind TypeName SizedType */ \
|
||||
D(FUNCTION, Object, JSObject, JSFunction) \
|
||||
D(FUNCTION_EXTENDED, Object, JSObject, FunctionExtended) \
|
||||
D(OBJECT0, Object, JSObject, JSObject_Slots0) \
|
||||
D(OBJECT0_BACKGROUND, Object, JSObject, JSObject_Slots0) \
|
||||
D(OBJECT2, Object, JSObject, JSObject_Slots2) \
|
||||
D(OBJECT2_BACKGROUND, Object, JSObject, JSObject_Slots2) \
|
||||
D(OBJECT4, Object, JSObject, JSObject_Slots4) \
|
||||
D(OBJECT4_BACKGROUND, Object, JSObject, JSObject_Slots4) \
|
||||
D(OBJECT8, Object, JSObject, JSObject_Slots8) \
|
||||
D(OBJECT8_BACKGROUND, Object, JSObject, JSObject_Slots8) \
|
||||
D(OBJECT12, Object, JSObject, JSObject_Slots12) \
|
||||
D(OBJECT12_BACKGROUND, Object, JSObject, JSObject_Slots12) \
|
||||
D(OBJECT16, Object, JSObject, JSObject_Slots16) \
|
||||
D(OBJECT16_BACKGROUND, Object, JSObject, JSObject_Slots16)
|
||||
|
||||
#define FOR_EACH_NONOBJECT_ALLOCKIND(D) \
|
||||
/* AllocKind TraceKind TypeName SizedType */ \
|
||||
D(SCRIPT, Script, JSScript, JSScript) \
|
||||
D(LAZY_SCRIPT, LazyScript, js::LazyScript, js::LazyScript) \
|
||||
D(SHAPE, Shape, js::Shape, js::Shape) \
|
||||
D(ACCESSOR_SHAPE, Shape, js::AccessorShape, js::AccessorShape) \
|
||||
D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape) \
|
||||
D(OBJECT_GROUP, ObjectGroup, js::ObjectGroup, js::ObjectGroup) \
|
||||
D(FAT_INLINE_STRING, String, JSFatInlineString, JSFatInlineString) \
|
||||
D(STRING, String, JSString, JSString) \
|
||||
D(EXTERNAL_STRING, String, JSExternalString, JSExternalString) \
|
||||
D(SYMBOL, Symbol, JS::Symbol, JS::Symbol) \
|
||||
D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode)
|
||||
|
||||
#define FOR_EACH_ALLOCKIND(D) \
|
||||
FOR_EACH_OBJECT_ALLOCKIND(D) \
|
||||
FOR_EACH_NONOBJECT_ALLOCKIND(D)
|
||||
|
||||
static_assert(int(AllocKind::FIRST) == 0, "Various places depend on AllocKind starting at 0, "
|
||||
"please audit them carefully!");
|
||||
static_assert(int(AllocKind::OBJECT_FIRST) == 0, "Various places depend on AllocKind::OBJECT_FIRST "
|
||||
"being 0, please audit them carefully!");
|
||||
|
||||
inline bool
|
||||
IsAllocKind(AllocKind kind)
|
||||
{
|
||||
return kind >= AllocKind::FIRST && kind <= AllocKind::LIMIT;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsValidAllocKind(AllocKind kind)
|
||||
{
|
||||
return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsObjectAllocKind(AllocKind kind)
|
||||
{
|
||||
@@ -130,17 +180,6 @@ IsShapeAllocKind(AllocKind kind)
|
||||
return kind == AllocKind::SHAPE || kind == AllocKind::ACCESSOR_SHAPE;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsValidAllocKind(AllocKind kind)
|
||||
{
|
||||
return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
|
||||
}
|
||||
|
||||
inline bool IsAllocKind(AllocKind kind)
|
||||
{
|
||||
return kind >= AllocKind::FIRST && kind <= AllocKind::LIMIT;
|
||||
}
|
||||
|
||||
// Returns a sequence for use in a range-based for loop,
|
||||
// to iterate over all alloc kinds.
|
||||
inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::FIRST, AllocKind::LIMIT))
|
||||
@@ -181,31 +220,10 @@ static inline JS::TraceKind
|
||||
MapAllocToTraceKind(AllocKind kind)
|
||||
{
|
||||
static const JS::TraceKind map[] = {
|
||||
JS::TraceKind::Object, /* AllocKind::FUNCTION */
|
||||
JS::TraceKind::Object, /* AllocKind::FUNCTION_EXTENDED */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT0 */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT0_BACKGROUND */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT2 */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT2_BACKGROUND */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT4 */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT4_BACKGROUND */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT8 */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT8_BACKGROUND */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT12 */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT12_BACKGROUND */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT16 */
|
||||
JS::TraceKind::Object, /* AllocKind::OBJECT16_BACKGROUND */
|
||||
JS::TraceKind::Script, /* AllocKind::SCRIPT */
|
||||
JS::TraceKind::LazyScript, /* AllocKind::LAZY_SCRIPT */
|
||||
JS::TraceKind::Shape, /* AllocKind::SHAPE */
|
||||
JS::TraceKind::Shape, /* AllocKind::ACCESSOR_SHAPE */
|
||||
JS::TraceKind::BaseShape, /* AllocKind::BASE_SHAPE */
|
||||
JS::TraceKind::ObjectGroup, /* AllocKind::OBJECT_GROUP */
|
||||
JS::TraceKind::String, /* AllocKind::FAT_INLINE_STRING */
|
||||
JS::TraceKind::String, /* AllocKind::STRING */
|
||||
JS::TraceKind::String, /* AllocKind::EXTERNAL_STRING */
|
||||
JS::TraceKind::Symbol, /* AllocKind::SYMBOL */
|
||||
JS::TraceKind::JitCode, /* AllocKind::JITCODE */
|
||||
#define EXPAND_ELEMENT(allocKind, traceKind, type, sizedType) \
|
||||
JS::TraceKind::traceKind,
|
||||
FOR_EACH_ALLOCKIND(EXPAND_ELEMENT)
|
||||
#undef EXPAND_ELEMENT
|
||||
};
|
||||
|
||||
static_assert(MOZ_ARRAY_LENGTH(map) == size_t(AllocKind::LIMIT),
|
||||
@@ -267,6 +285,7 @@ class TenuredCell : public Cell
|
||||
|
||||
// Mark bit management.
|
||||
MOZ_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const;
|
||||
// The return value indicates if the cell went from unmarked to marked.
|
||||
MOZ_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const;
|
||||
MOZ_ALWAYS_INLINE void unmark(uint32_t color) const;
|
||||
MOZ_ALWAYS_INLINE void copyMarkBitsFrom(const TenuredCell* src);
|
||||
@@ -296,6 +315,9 @@ class TenuredCell : public Cell
|
||||
static MOZ_ALWAYS_INLINE void writeBarrierPost(void* cellp, TenuredCell* prior,
|
||||
TenuredCell* next);
|
||||
|
||||
// Default implementation for kinds that don't require fixup.
|
||||
void fixupAfterMovingGC() {}
|
||||
|
||||
#ifdef DEBUG
|
||||
inline bool isAligned() const;
|
||||
#endif
|
||||
@@ -849,6 +871,7 @@ struct ChunkBitmap
|
||||
return *word & mask;
|
||||
}
|
||||
|
||||
// The return value indicates if the cell went from unmarked to marked.
|
||||
MOZ_ALWAYS_INLINE bool markIfUnmarked(const Cell* cell, uint32_t color) {
|
||||
uintptr_t* word, mask;
|
||||
getMarkWordAndMask(cell, BLACK, &word, &mask);
|
||||
@@ -967,7 +990,7 @@ struct Chunk
|
||||
void releaseArena(JSRuntime* rt, Arena* arena, const AutoLockGC& lock);
|
||||
void recycleArena(Arena* arena, SortedArenaList& dest, size_t thingsPerArena);
|
||||
|
||||
bool decommitOneFreeArena(JSRuntime* rt, AutoLockGC& lock);
|
||||
MOZ_MUST_USE bool decommitOneFreeArena(JSRuntime* rt, AutoLockGC& lock);
|
||||
void decommitAllArenasWithoutUnlocking(const AutoLockGC& lock);
|
||||
|
||||
static Chunk* allocate(JSRuntime* rt);
|
||||
|
||||
+13
-10
@@ -192,6 +192,9 @@ js::CheckTracedThing(JSTracer* trc, T* thing)
|
||||
MOZ_ASSERT(trc);
|
||||
MOZ_ASSERT(thing);
|
||||
|
||||
if (!trc->checkEdges())
|
||||
return;
|
||||
|
||||
thing = MaybeForwarded(thing);
|
||||
|
||||
/* This function uses data that's not available in the nursery. */
|
||||
@@ -358,6 +361,9 @@ AssertRootMarkingPhase(JSTracer* trc)
|
||||
// statically select the correct Cell layout for marking. Below, we instantiate
|
||||
// each override with a declaration of the most derived layout type.
|
||||
//
|
||||
// The use of TraceKind::Null for the case where the type is not matched
|
||||
// generates a compile error as no template instantiated for that kind.
|
||||
//
|
||||
// Usage:
|
||||
// BaseGCType<T>::type
|
||||
//
|
||||
@@ -365,16 +371,13 @@ AssertRootMarkingPhase(JSTracer* trc)
|
||||
// BaseGCType<JSFunction>::type => JSObject
|
||||
// BaseGCType<UnownedBaseShape>::type => BaseShape
|
||||
// etc.
|
||||
template <typename T,
|
||||
JS::TraceKind = IsBaseOf<JSObject, T>::value ? JS::TraceKind::Object
|
||||
: IsBaseOf<JSString, T>::value ? JS::TraceKind::String
|
||||
: IsBaseOf<JS::Symbol, T>::value ? JS::TraceKind::Symbol
|
||||
: IsBaseOf<JSScript, T>::value ? JS::TraceKind::Script
|
||||
: IsBaseOf<Shape, T>::value ? JS::TraceKind::Shape
|
||||
: IsBaseOf<BaseShape, T>::value ? JS::TraceKind::BaseShape
|
||||
: IsBaseOf<jit::JitCode, T>::value ? JS::TraceKind::JitCode
|
||||
: IsBaseOf<LazyScript, T>::value ? JS::TraceKind::LazyScript
|
||||
: JS::TraceKind::ObjectGroup>
|
||||
template <typename T, JS::TraceKind =
|
||||
#define EXPAND_MATCH_TYPE(name, type, _) \
|
||||
IsBaseOf<type, T>::value ? JS::TraceKind::name :
|
||||
JS_FOR_EACH_TRACEKIND(EXPAND_MATCH_TYPE)
|
||||
#undef EXPAND_MATCH_TYPE
|
||||
JS::TraceKind::Null>
|
||||
|
||||
struct BaseGCType;
|
||||
#define IMPL_BASE_GC_TYPE(name, type_, _) \
|
||||
template <typename T> struct BaseGCType<T, JS::TraceKind:: name> { typedef type_ type; };
|
||||
|
||||
+10
-9
@@ -87,13 +87,13 @@ class MarkStack
|
||||
end_ = stack + capacity;
|
||||
}
|
||||
|
||||
bool init(JSGCMode gcMode);
|
||||
MOZ_MUST_USE bool init(JSGCMode gcMode);
|
||||
|
||||
void setBaseCapacity(JSGCMode mode);
|
||||
size_t maxCapacity() const { return maxCapacity_; }
|
||||
void setMaxCapacity(size_t maxCapacity);
|
||||
|
||||
bool push(uintptr_t item) {
|
||||
MOZ_MUST_USE bool push(uintptr_t item) {
|
||||
if (tos_ == end_) {
|
||||
if (!enlarge(1))
|
||||
return false;
|
||||
@@ -103,7 +103,7 @@ class MarkStack
|
||||
return true;
|
||||
}
|
||||
|
||||
bool push(uintptr_t item1, uintptr_t item2, uintptr_t item3) {
|
||||
MOZ_MUST_USE bool push(uintptr_t item1, uintptr_t item2, uintptr_t item3) {
|
||||
uintptr_t* nextTos = tos_ + 3;
|
||||
if (nextTos > end_) {
|
||||
if (!enlarge(3))
|
||||
@@ -130,7 +130,7 @@ class MarkStack
|
||||
void reset();
|
||||
|
||||
/* Grow the stack, ensuring there is space for at least count elements. */
|
||||
bool enlarge(unsigned count);
|
||||
MOZ_MUST_USE bool enlarge(unsigned count);
|
||||
|
||||
void setGCMode(JSGCMode gcMode);
|
||||
|
||||
@@ -168,7 +168,7 @@ class GCMarker : public JSTracer
|
||||
{
|
||||
public:
|
||||
explicit GCMarker(JSRuntime* rt);
|
||||
bool init(JSGCMode gcMode);
|
||||
MOZ_MUST_USE bool init(JSGCMode gcMode);
|
||||
|
||||
void setMaxCapacity(size_t maxCap) { stack.setMaxCapacity(maxCap); }
|
||||
size_t maxCapacity() const { return stack.maxCapacity(); }
|
||||
@@ -216,7 +216,7 @@ class GCMarker : public JSTracer
|
||||
void delayMarkingArena(gc::Arena* arena);
|
||||
void delayMarkingChildren(const void* thing);
|
||||
void markDelayedChildren(gc::Arena* arena);
|
||||
bool markDelayedChildren(SliceBudget& budget);
|
||||
MOZ_MUST_USE bool markDelayedChildren(SliceBudget& budget);
|
||||
bool hasDelayedChildren() const {
|
||||
return !!unmarkedArenaStackTop;
|
||||
}
|
||||
@@ -225,7 +225,7 @@ class GCMarker : public JSTracer
|
||||
return isMarkStackEmpty() && !unmarkedArenaStackTop;
|
||||
}
|
||||
|
||||
bool drainMarkStack(SliceBudget& budget);
|
||||
MOZ_MUST_USE bool drainMarkStack(SliceBudget& budget);
|
||||
|
||||
void setGCMode(JSGCMode mode) { stack.setGCMode(mode); }
|
||||
|
||||
@@ -289,7 +289,7 @@ class GCMarker : public JSTracer
|
||||
// Mark the given GC thing, but do not trace its children. Return true
|
||||
// if the thing became marked.
|
||||
template <typename T>
|
||||
bool mark(T* thing);
|
||||
MOZ_MUST_USE bool mark(T* thing);
|
||||
|
||||
void pushTaggedPtr(StackTag tag, void* ptr) {
|
||||
checkZone(ptr);
|
||||
@@ -319,7 +319,7 @@ class GCMarker : public JSTracer
|
||||
return stack.isEmpty();
|
||||
}
|
||||
|
||||
bool restoreValueArray(JSObject* obj, void** vpp, void** endp);
|
||||
MOZ_MUST_USE bool restoreValueArray(JSObject* obj, void** vpp, void** endp);
|
||||
void saveValueRanges();
|
||||
inline void processMarkStackTop(SliceBudget& budget);
|
||||
|
||||
@@ -451,6 +451,7 @@ struct RewrapTaggedPointer<Value, T>
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
// The return value indicates if anything was unmarked.
|
||||
bool
|
||||
UnmarkGrayShapeRecursively(Shape* shape);
|
||||
|
||||
|
||||
@@ -262,14 +262,13 @@ MarkPagesUnused(void* p, size_t size)
|
||||
return p2 == p;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
MarkPagesInUse(void* p, size_t size)
|
||||
{
|
||||
if (!DecommitEnabled())
|
||||
return true;
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -320,7 +319,6 @@ bool
|
||||
MarkPagesInUse(void* p, size_t size)
|
||||
{
|
||||
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -399,10 +397,9 @@ bool
|
||||
MarkPagesInUse(void* p, size_t size)
|
||||
{
|
||||
if (!DecommitEnabled())
|
||||
return true;
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -667,14 +664,13 @@ MarkPagesUnused(void* p, size_t size)
|
||||
return result != -1;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
MarkPagesInUse(void* p, size_t size)
|
||||
{
|
||||
if (!DecommitEnabled())
|
||||
return true;
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ bool MarkPagesUnused(void* p, size_t size);
|
||||
// Undo |MarkPagesUnused|: tell the OS that the given pages are of interest
|
||||
// and should be paged in and out normally. This may be a no-op on some
|
||||
// platforms.
|
||||
bool MarkPagesInUse(void* p, size_t size);
|
||||
void MarkPagesInUse(void* p, size_t size);
|
||||
|
||||
// Returns #(hard faults) + #(soft faults)
|
||||
size_t GetPageFaultCount();
|
||||
|
||||
@@ -380,9 +380,7 @@ js::TenuringTracer::TenuringTracer(JSRuntime* rt, Nursery* nursery)
|
||||
void
|
||||
js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList* pretenureGroups)
|
||||
{
|
||||
if (rt->mainThread.suppressGC)
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(!rt->mainThread.suppressGC);
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
StoreBuffer& sb = rt->gc.storeBuffer;
|
||||
@@ -502,6 +500,13 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
|
||||
#endif
|
||||
TIME_END(checkHashTables);
|
||||
|
||||
TIME_START(checkHeap);
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (rt->hasZealMode(ZealMode::CheckHeapOnMovingGC))
|
||||
CheckHeapAfterMovingGC(rt);
|
||||
#endif
|
||||
TIME_END(checkHeap);
|
||||
|
||||
// Resize the nursery.
|
||||
TIME_START(resize);
|
||||
double promotionRate = mover.tenuredSize / double(allocationEnd() - start());
|
||||
@@ -548,6 +553,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
|
||||
{"mcWCll", TIME_TOTAL(traceWholeCells)},
|
||||
{"mkGnrc", TIME_TOTAL(traceGenericEntries)},
|
||||
{"ckTbls", TIME_TOTAL(checkHashTables)},
|
||||
{"ckHeap", TIME_TOTAL(checkHeap)},
|
||||
{"mkRntm", TIME_TOTAL(markRuntime)},
|
||||
{"mkDbgr", TIME_TOTAL(markDebugger)},
|
||||
{"clrNOC", TIME_TOTAL(clearNewObjectCache)},
|
||||
|
||||
+3
-3
@@ -110,7 +110,7 @@ class Nursery
|
||||
{}
|
||||
~Nursery();
|
||||
|
||||
bool init(uint32_t maxNurseryBytes);
|
||||
MOZ_MUST_USE bool init(uint32_t maxNurseryBytes);
|
||||
|
||||
bool exists() const { return numNurseryChunks_ != 0; }
|
||||
size_t numChunks() const { return numNurseryChunks_; }
|
||||
@@ -171,7 +171,7 @@ class Nursery
|
||||
* sets |*ref| to the new location of the object and returns true. Otherwise
|
||||
* returns false and leaves |*ref| unset.
|
||||
*/
|
||||
MOZ_ALWAYS_INLINE bool getForwardedPointer(JSObject** ref) const;
|
||||
MOZ_ALWAYS_INLINE MOZ_MUST_USE bool getForwardedPointer(JSObject** ref) const;
|
||||
|
||||
/* Forward a slots/elements pointer stored in an Ion frame. */
|
||||
void forwardBufferPointer(HeapSlot** pSlotsElems);
|
||||
@@ -188,7 +188,7 @@ class Nursery
|
||||
|
||||
void waitBackgroundFreeEnd();
|
||||
|
||||
bool addedUniqueIdToCell(gc::Cell* cell) {
|
||||
MOZ_MUST_USE bool addedUniqueIdToCell(gc::Cell* cell) {
|
||||
if (!IsInsideNursery(cell) || !isEnabled())
|
||||
return true;
|
||||
MOZ_ASSERT(cellsWithUid_.initialized());
|
||||
|
||||
@@ -160,7 +160,7 @@ struct Statistics
|
||||
/* Create a convenient type for referring to tables of phase times. */
|
||||
using PhaseTimeTable = int64_t[NumTimingArrays][PHASE_LIMIT];
|
||||
|
||||
static bool initialize();
|
||||
static MOZ_MUST_USE bool initialize();
|
||||
|
||||
explicit Statistics(JSRuntime* rt);
|
||||
~Statistics();
|
||||
@@ -174,8 +174,8 @@ struct Statistics
|
||||
void endSlice();
|
||||
void setSliceCycleCount(unsigned cycleCount);
|
||||
|
||||
bool startTimingMutator();
|
||||
bool stopTimingMutator(double& mutator_ms, double& gc_ms);
|
||||
MOZ_MUST_USE bool startTimingMutator();
|
||||
MOZ_MUST_USE bool stopTimingMutator(double& mutator_ms, double& gc_ms);
|
||||
|
||||
void reset(const char* reason) {
|
||||
if (!aborted)
|
||||
|
||||
@@ -66,11 +66,11 @@ StoreBuffer::disable()
|
||||
enabled_ = false;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
StoreBuffer::clear()
|
||||
{
|
||||
if (!enabled_)
|
||||
return true;
|
||||
return;
|
||||
|
||||
aboutToOverflow_ = false;
|
||||
cancelIonCompilations_ = false;
|
||||
@@ -80,8 +80,6 @@ StoreBuffer::clear()
|
||||
bufferSlot.clear();
|
||||
bufferWholeCell.clear();
|
||||
bufferGeneric.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -74,7 +74,7 @@ class StoreBuffer
|
||||
explicit MonoTypeBuffer() : last_(T()) {}
|
||||
~MonoTypeBuffer() { stores_.finish(); }
|
||||
|
||||
bool init() {
|
||||
MOZ_MUST_USE bool init() {
|
||||
if (!stores_.initialized() && !stores_.init())
|
||||
return false;
|
||||
clear();
|
||||
@@ -141,7 +141,7 @@ class StoreBuffer
|
||||
explicit GenericBuffer() : storage_(nullptr) {}
|
||||
~GenericBuffer() { js_delete(storage_); }
|
||||
|
||||
bool init() {
|
||||
MOZ_MUST_USE bool init() {
|
||||
if (!storage_)
|
||||
storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
|
||||
clear();
|
||||
@@ -409,7 +409,7 @@ class StoreBuffer
|
||||
void disable();
|
||||
bool isEnabled() const { return enabled_; }
|
||||
|
||||
bool clear();
|
||||
void clear();
|
||||
|
||||
/* Get the overflowed status. */
|
||||
bool isAboutToOverflow() const { return aboutToOverflow_; }
|
||||
|
||||
+24
-38
@@ -126,6 +126,27 @@ js::TraceChildren(JSTracer* trc, void* thing, JS::TraceKind kind)
|
||||
DispatchTraceKindTyped(f, kind, trc, thing);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct TraceIncomingFunctor {
|
||||
JSTracer* trc_;
|
||||
const JS::CompartmentSet& compartments_;
|
||||
TraceIncomingFunctor(JSTracer* trc, const JS::CompartmentSet& compartments)
|
||||
: trc_(trc), compartments_(compartments)
|
||||
{}
|
||||
using ReturnType = void;
|
||||
template <typename T>
|
||||
ReturnType operator()(T tp) {
|
||||
if (!compartments_.has((*tp)->compartment()))
|
||||
return;
|
||||
TraceManuallyBarrieredEdge(trc_, tp, "cross-compartment wrapper");
|
||||
}
|
||||
// StringWrappers are just used to avoid copying strings
|
||||
// across zones multiple times, and don't hold a strong
|
||||
// reference.
|
||||
ReturnType operator()(JSString** tp) {}
|
||||
};
|
||||
} // namespace (anonymous)
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::TraceIncomingCCWs(JSTracer* trc, const JS::CompartmentSet& compartments)
|
||||
{
|
||||
@@ -134,44 +155,9 @@ JS::TraceIncomingCCWs(JSTracer* trc, const JS::CompartmentSet& compartments)
|
||||
continue;
|
||||
|
||||
for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
|
||||
const CrossCompartmentKey& key = e.front().key();
|
||||
JSObject* obj;
|
||||
JSScript* script;
|
||||
|
||||
switch (key.kind) {
|
||||
case CrossCompartmentKey::StringWrapper:
|
||||
// StringWrappers are just used to avoid copying strings
|
||||
// across zones multiple times, and don't hold a strong
|
||||
// reference.
|
||||
continue;
|
||||
|
||||
case CrossCompartmentKey::ObjectWrapper:
|
||||
case CrossCompartmentKey::DebuggerObject:
|
||||
case CrossCompartmentKey::DebuggerSource:
|
||||
case CrossCompartmentKey::DebuggerEnvironment:
|
||||
case CrossCompartmentKey::DebuggerWasmScript:
|
||||
case CrossCompartmentKey::DebuggerWasmSource:
|
||||
obj = static_cast<JSObject*>(key.wrapped);
|
||||
// Ignore CCWs whose wrapped value doesn't live in our given
|
||||
// set of zones.
|
||||
if (!compartments.has(obj->compartment()))
|
||||
continue;
|
||||
|
||||
TraceManuallyBarrieredEdge(trc, &obj, "cross-compartment wrapper");
|
||||
MOZ_ASSERT(obj == key.wrapped);
|
||||
break;
|
||||
|
||||
case CrossCompartmentKey::DebuggerScript:
|
||||
script = static_cast<JSScript*>(key.wrapped);
|
||||
// Ignore CCWs whose wrapped value doesn't live in our given
|
||||
// set of compartments.
|
||||
if (!compartments.has(script->compartment()))
|
||||
continue;
|
||||
|
||||
TraceManuallyBarrieredEdge(trc, &script, "cross-compartment wrapper");
|
||||
MOZ_ASSERT(script == key.wrapped);
|
||||
break;
|
||||
}
|
||||
mozilla::DebugOnly<const CrossCompartmentKey> prior = e.front().key();
|
||||
e.front().mutableKey().applyToWrapped(TraceIncomingFunctor(trc, compartments));
|
||||
MOZ_ASSERT(e.front().key() == prior);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+124
-3
@@ -8,6 +8,8 @@
|
||||
# include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsprf.h"
|
||||
@@ -302,13 +304,13 @@ AssertMarkedOrAllocated(const EdgeValue& edge)
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
gc::GCRuntime::endVerifyPreBarriers()
|
||||
{
|
||||
VerifyPreTracer* trc = verifyPreData;
|
||||
|
||||
if (!trc)
|
||||
return false;
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(!JS::IsGenerationalGCEnabled(rt));
|
||||
|
||||
@@ -357,7 +359,6 @@ gc::GCRuntime::endVerifyPreBarriers()
|
||||
marker.stop();
|
||||
|
||||
js_delete(trc);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*** Barrier Verifier Scheduling ***/
|
||||
@@ -414,3 +415,123 @@ js::gc::GCRuntime::finishVerifier()
|
||||
}
|
||||
|
||||
#endif /* JS_GC_ZEAL */
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
|
||||
class CheckHeapTracer : public JS::CallbackTracer
|
||||
{
|
||||
public:
|
||||
explicit CheckHeapTracer(JSRuntime* rt);
|
||||
bool init();
|
||||
bool check();
|
||||
|
||||
private:
|
||||
void onChild(const JS::GCCellPtr& thing) override;
|
||||
|
||||
struct WorkItem {
|
||||
WorkItem(JS::GCCellPtr thing, const char* name, int parentIndex)
|
||||
: thing(thing), name(name), parentIndex(parentIndex), processed(false)
|
||||
{}
|
||||
|
||||
JS::GCCellPtr thing;
|
||||
const char* name;
|
||||
int parentIndex;
|
||||
bool processed;
|
||||
};
|
||||
|
||||
JSRuntime* rt;
|
||||
bool oom;
|
||||
size_t failures;
|
||||
HashSet<Cell*, DefaultHasher<Cell*>, SystemAllocPolicy> visited;
|
||||
Vector<WorkItem, 0, SystemAllocPolicy> stack;
|
||||
int parentIndex;
|
||||
};
|
||||
|
||||
CheckHeapTracer::CheckHeapTracer(JSRuntime* rt)
|
||||
: CallbackTracer(rt, TraceWeakMapKeysValues),
|
||||
rt(rt),
|
||||
oom(false),
|
||||
failures(0),
|
||||
parentIndex(-1)
|
||||
{
|
||||
setCheckEdges(false);
|
||||
}
|
||||
|
||||
bool
|
||||
CheckHeapTracer::init()
|
||||
{
|
||||
return visited.init();
|
||||
}
|
||||
|
||||
void
|
||||
CheckHeapTracer::onChild(const JS::GCCellPtr& thing)
|
||||
{
|
||||
Cell* cell = thing.asCell();
|
||||
if (visited.lookup(cell))
|
||||
return;
|
||||
|
||||
if (!visited.put(cell)) {
|
||||
oom = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsGCThingValidAfterMovingGC(cell)) {
|
||||
failures++;
|
||||
fprintf(stderr, "Stale pointer %p\n", cell);
|
||||
const char* name = contextName();
|
||||
for (int index = parentIndex; index != -1; index = stack[index].parentIndex) {
|
||||
const WorkItem& parent = stack[index];
|
||||
cell = parent.thing.asCell();
|
||||
fprintf(stderr, " from %s %p %s edge\n",
|
||||
GCTraceKindToAscii(cell->getTraceKind()), cell, name);
|
||||
name = parent.name;
|
||||
}
|
||||
fprintf(stderr, " from root %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
WorkItem item(thing, contextName(), parentIndex);
|
||||
if (!stack.append(item))
|
||||
oom = true;
|
||||
}
|
||||
|
||||
bool
|
||||
CheckHeapTracer::check()
|
||||
{
|
||||
// The analysis thinks that markRuntime might GC by calling a GC callback.
|
||||
JS::AutoSuppressGCAnalysis nogc(rt);
|
||||
rt->gc.markRuntime(this, GCRuntime::TraceRuntime);
|
||||
|
||||
while (!stack.empty()) {
|
||||
WorkItem item = stack.back();
|
||||
if (item.processed) {
|
||||
stack.popBack();
|
||||
} else {
|
||||
parentIndex = stack.length() - 1;
|
||||
TraceChildren(this, item.thing);
|
||||
stack.back().processed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (oom)
|
||||
return false;
|
||||
|
||||
if (failures) {
|
||||
fprintf(stderr, "Heap check: %zu failure(s) out of %" PRIu32 " pointers checked\n",
|
||||
failures, visited.count());
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(failures == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::CheckHeapAfterMovingGC(JSRuntime* rt)
|
||||
{
|
||||
MOZ_ASSERT(rt->isHeapCollecting());
|
||||
CheckHeapTracer tracer(rt);
|
||||
if (!tracer.init() || !tracer.check())
|
||||
fprintf(stderr, "OOM checking heap\n");
|
||||
}
|
||||
|
||||
#endif /* JSGC_HASH_TABLE_CHECKS */
|
||||
|
||||
+1
-1
@@ -672,7 +672,7 @@ class ZoneAllocPolicy
|
||||
void free_(void* p) { js_free(p); }
|
||||
void reportAllocOverflow() const {}
|
||||
|
||||
bool checkSimulatedOOM() const {
|
||||
MOZ_MUST_USE bool checkSimulatedOOM() const {
|
||||
return !js::oom::ShouldFailWithOOM();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ FRAGMENT(GCCellPtr, simple) {
|
||||
|
||||
JS::Rooted<JSObject*> glob(cx, JS::CurrentGlobalOrNull(cx));
|
||||
JS::Rooted<JSString*> empty(cx, JS_NewStringCopyN(cx, nullptr, 0));
|
||||
JS::Rooted<Symbol*> unique(cx, NewSymbol(cx, nullptr));
|
||||
JS::Rooted<JS::Symbol*> unique(cx, JS::NewSymbol(cx, nullptr));
|
||||
|
||||
JS::GCCellPtr object(glob.get());
|
||||
JS::GCCellPtr string(empty.get());
|
||||
|
||||
@@ -17,7 +17,7 @@ FRAGMENT(JSObject, simple) {
|
||||
JSObject* funcRaw = func;
|
||||
|
||||
static const JSClass cls = { "\xc7X" };
|
||||
RootedObject badClassName(cx, JS_NewObject(cx, &cls));
|
||||
JS::RootedObject badClassName(cx, JS_NewObject(cx, &cls));
|
||||
|
||||
breakpoint();
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include <string.h>
|
||||
|
||||
static bool
|
||||
Something(JSContext* cx, unsigned argc, Value* vp)
|
||||
Something(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setInt32(23);
|
||||
breakpoint();
|
||||
return true;
|
||||
|
||||
@@ -5,44 +5,58 @@ assertEq(wasmEvalText('(module (func (result i32) (i32.const -2147483648)) (expo
|
||||
assertEq(wasmEvalText('(module (func (result i32) (i32.const 4294967295)) (export "" 0))')(), -1);
|
||||
|
||||
function testUnary(type, opcode, op, expect) {
|
||||
assertEq(wasmEvalText('(module (func (param ' + type + ') (result ' + type + ') (' + type + '.' + opcode + ' (get_local 0))) (export "" 0))')(op), expect);
|
||||
assertEq(wasmEvalText(`(module (func (param ${type}) (result ${type}) (${type}.${opcode} (get_local 0))) (export "" 0))`)(op), expect);
|
||||
}
|
||||
|
||||
function testBinary(type, opcode, lhs, rhs, expect) {
|
||||
if (type === 'i64') {
|
||||
let lobj = createI64(lhs);
|
||||
let robj = createI64(rhs);
|
||||
expect = createI64(expect);
|
||||
function testBinary64(opcode, lhs, rhs, expect) {
|
||||
let lobj = createI64(lhs);
|
||||
let robj = createI64(rhs);
|
||||
expect = createI64(expect);
|
||||
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lobj, robj), expect);
|
||||
// The same, but now the RHS is a constant.
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (i64.const ${rhs}))) (export "" 0))`)(lobj, robj), expect);
|
||||
// LHS and RHS are constants.
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (i64.const ${lhs}) (i64.const ${rhs}))) (export "" 0))`)(lobj, robj), expect);
|
||||
} else {
|
||||
assertEq(wasmEvalText(`(module (func (param ${type}) (param ${type}) (result ${type}) (${type}.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lhs, rhs), expect);
|
||||
}
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lobj, robj), expect);
|
||||
// The same, but now the RHS is a constant.
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (result i64) (i64.${opcode} (get_local 0) (i64.const ${rhs}))) (export "" 0))`)(lobj), expect);
|
||||
// LHS and RHS are constants.
|
||||
assertEqI64(wasmEvalText(`(module (func (result i64) (i64.${opcode} (i64.const ${lhs}) (i64.const ${rhs}))) (export "" 0))`)(), expect);
|
||||
}
|
||||
|
||||
function testComparison(type, opcode, lhs, rhs, expect) {
|
||||
if (type === 'i64') {
|
||||
let lobj = createI64(lhs);
|
||||
let robj = createI64(rhs);
|
||||
function testBinary32(opcode, lhs, rhs, expect) {
|
||||
assertEq(wasmEvalText(`(module (func (param i32) (param i32) (result i32) (i32.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lhs, rhs), expect);
|
||||
// The same, but now the RHS is a constant.
|
||||
assertEq(wasmEvalText(`(module (func (param i32) (result i32) (i32.${opcode} (get_local 0) (i32.const ${rhs}))) (export "" 0))`)(lhs), expect);
|
||||
// LHS and RHS are constants.
|
||||
assertEq(wasmEvalText(`(module (func (result i32) (i32.${opcode} (i32.const ${lhs}) (i32.const ${rhs}))) (export "" 0))`)(), expect);
|
||||
}
|
||||
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32) (i64.${opcode} (get_local 0) (get_local 1)))
|
||||
(export "" 0))`)(lobj, robj), expect);
|
||||
function testComparison32(opcode, lhs, rhs, expect) {
|
||||
assertEq(wasmEvalText(`(module (func (param i32) (param i32) (result i32) (i32.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lhs, rhs), expect);
|
||||
}
|
||||
function testComparison64(opcode, lhs, rhs, expect) {
|
||||
let lobj = createI64(lhs);
|
||||
let robj = createI64(rhs);
|
||||
|
||||
// Also test if, for the compare-and-branch path.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32)
|
||||
(if (i64.${opcode} (get_local 0) (get_local 1))
|
||||
(i32.const 1)
|
||||
(i32.const 0)))
|
||||
(export "" 0))`)(lobj, robj), expect);
|
||||
} else {
|
||||
assertEq(wasmEvalText('(module (func (param ' + type + ') (param ' + type + ') (result i32) (' + type + '.' + opcode + ' (get_local 0) (get_local 1))) (export "" 0))')(lhs, rhs), expect);
|
||||
}
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32) (i64.${opcode} (get_local 0) (get_local 1)))
|
||||
(export "" 0))`)(lobj, robj), expect);
|
||||
|
||||
// Also test if, for the compare-and-branch path.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32)
|
||||
(if (i64.${opcode} (get_local 0) (get_local 1))
|
||||
(i32.const 1)
|
||||
(i32.const 0)))
|
||||
(export "" 0))`)(lobj, robj), expect);
|
||||
}
|
||||
|
||||
function testTrap64(opcode, lhs, rhs, expect) {
|
||||
let lobj = createI64(lhs);
|
||||
let robj = createI64(rhs);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lobj, robj), Error, expect);
|
||||
// The same, but now the RHS is a constant.
|
||||
assertErrorMessage(() => wasmEvalText(`(module (func (param i64) (result i64) (i64.${opcode} (get_local 0) (i64.const ${rhs}))) (export "" 0))`)(lobj), Error, expect);
|
||||
// LHS and RHS are constants.
|
||||
assertErrorMessage(wasmEvalText(`(module (func (result i64) (i64.${opcode} (i64.const ${lhs}) (i64.const ${rhs}))) (export "" 0))`), Error, expect);
|
||||
}
|
||||
|
||||
testUnary('i32', 'clz', 40, 26);
|
||||
@@ -58,32 +72,35 @@ testUnary('i32', 'eqz', 0, 1);
|
||||
testUnary('i32', 'eqz', 1, 0);
|
||||
testUnary('i32', 'eqz', 0xFFFFFFFF, 0);
|
||||
|
||||
testBinary('i32', 'add', 40, 2, 42);
|
||||
testBinary('i32', 'sub', 40, 2, 38);
|
||||
testBinary('i32', 'mul', 40, 2, 80);
|
||||
testBinary('i32', 'div_s', -40, 2, -20);
|
||||
testBinary('i32', 'div_u', -40, 2, 2147483628);
|
||||
testBinary('i32', 'rem_s', 40, -3, 1);
|
||||
testBinary('i32', 'rem_u', 40, -3, 40);
|
||||
testBinary('i32', 'and', 42, 6, 2);
|
||||
testBinary('i32', 'or', 42, 6, 46);
|
||||
testBinary('i32', 'xor', 42, 2, 40);
|
||||
testBinary('i32', 'shl', 40, 2, 160);
|
||||
testBinary('i32', 'shr_s', -40, 2, -10);
|
||||
testBinary('i32', 'shr_u', -40, 2, 1073741814);
|
||||
//testBinary('i32', 'rotl', 40, 2, 160); // NYI: rotate
|
||||
//testBinary('i32', 'rotr', 40, 2, 10); // NYI: rotate
|
||||
testBinary32('add', 40, 2, 42);
|
||||
testBinary32('sub', 40, 2, 38);
|
||||
testBinary32('mul', 40, 2, 80);
|
||||
testBinary32('div_s', -40, 2, -20);
|
||||
testBinary32('div_u', -40, 2, 2147483628);
|
||||
testBinary32('rem_s', 40, -3, 1);
|
||||
testBinary32('rem_u', 40, -3, 40);
|
||||
testBinary32('and', 42, 6, 2);
|
||||
testBinary32('or', 42, 6, 46);
|
||||
testBinary32('xor', 42, 2, 40);
|
||||
testBinary32('shl', 40, 2, 160);
|
||||
testBinary32('shr_s', -40, 2, -10);
|
||||
testBinary32('shr_u', -40, 2, 1073741814);
|
||||
|
||||
testComparison('i32', 'eq', 40, 40, 1);
|
||||
testComparison('i32', 'ne', 40, 40, 0);
|
||||
testComparison('i32', 'lt_s', 40, 40, 0);
|
||||
testComparison('i32', 'lt_u', 40, 40, 0);
|
||||
testComparison('i32', 'le_s', 40, 40, 1);
|
||||
testComparison('i32', 'le_u', 40, 40, 1);
|
||||
testComparison('i32', 'gt_s', 40, 40, 0);
|
||||
testComparison('i32', 'gt_u', 40, 40, 0);
|
||||
testComparison('i32', 'ge_s', 40, 40, 1);
|
||||
testComparison('i32', 'ge_u', 40, 40, 1);
|
||||
testBinary32('rotl', 40, 2, 160);
|
||||
testBinary32('rotl', 40, 34, 160);
|
||||
testBinary32('rotr', 40, 2, 10);
|
||||
testBinary32('rotr', 40, 34, 10);
|
||||
|
||||
testComparison32('eq', 40, 40, 1);
|
||||
testComparison32('ne', 40, 40, 0);
|
||||
testComparison32('lt_s', 40, 40, 0);
|
||||
testComparison32('lt_u', 40, 40, 0);
|
||||
testComparison32('le_s', 40, 40, 1);
|
||||
testComparison32('le_u', 40, 40, 1);
|
||||
testComparison32('gt_s', 40, 40, 0);
|
||||
testComparison32('gt_u', 40, 40, 0);
|
||||
testComparison32('ge_s', 40, 40, 1);
|
||||
testComparison32('ge_u', 40, 40, 1);
|
||||
|
||||
//testUnary('i64', 'clz', 40, 58); // TODO: NYI
|
||||
//testUnary('i64', 'ctz', 40, 0); // TODO: NYI
|
||||
@@ -94,82 +111,81 @@ if (hasI64()) {
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
|
||||
testBinary('i64', 'add', 40, 2, 42);
|
||||
testBinary('i64', 'add', "0x1234567887654321", -1, "0x1234567887654320");
|
||||
testBinary('i64', 'add', "0xffffffffffffffff", 1, 0);
|
||||
testBinary('i64', 'sub', 40, 2, 38);
|
||||
testBinary('i64', 'sub', "0x1234567887654321", "0x123456789", "0x12345677641fdb98");
|
||||
testBinary('i64', 'sub', 3, 5, -2);
|
||||
testBinary('i64', 'mul', 40, 2, 80);
|
||||
testBinary('i64', 'mul', -1, 2, -2);
|
||||
testBinary('i64', 'mul', 0x123456, "0x9876543210", "0xad77d2c5f941160");
|
||||
testBinary('i64', 'div_s', -40, 2, -20);
|
||||
testBinary('i64', 'div_s', "0x1234567887654321", 2, "0x91a2b3c43b2a190");
|
||||
testBinary('i64', 'div_s', "0x1234567887654321", "0x1000000000", "0x1234567");
|
||||
testBinary('i64', 'div_u', -40, 2, "0x7fffffffffffffec");
|
||||
testBinary('i64', 'div_u', "0x1234567887654321", 9, "0x205d0b80f0b4059");
|
||||
testBinary('i64', 'rem_s', 40, -3, 1);
|
||||
testBinary('i64', 'rem_s', "0x1234567887654321", "0x1000000000", "0x887654321");
|
||||
testBinary('i64', 'rem_s', "0x7fffffffffffffff", -1, 0);
|
||||
testBinary('i64', 'rem_s', "0x8000000000000001", 1000, -807);
|
||||
testBinary('i64', 'rem_s', "0x8000000000000000", -1, 0);
|
||||
testBinary('i64', 'rem_u', 40, -3, 40);
|
||||
testBinary('i64', 'rem_u', "0x1234567887654321", "0x1000000000", "0x887654321");
|
||||
testBinary('i64', 'rem_u', "0x8000000000000000", -1, "0x8000000000000000");
|
||||
testBinary('i64', 'rem_u', "0x8ff00ff00ff00ff0", "0x100000001", "0x80000001");
|
||||
testBinary64('add', 40, 2, 42);
|
||||
testBinary64('add', "0x1234567887654321", -1, "0x1234567887654320");
|
||||
testBinary64('add', "0xffffffffffffffff", 1, 0);
|
||||
testBinary64('sub', 40, 2, 38);
|
||||
testBinary64('sub', "0x1234567887654321", "0x123456789", "0x12345677641fdb98");
|
||||
testBinary64('sub', 3, 5, -2);
|
||||
testBinary64('mul', 40, 2, 80);
|
||||
testBinary64('mul', -1, 2, -2);
|
||||
testBinary64('mul', 0x123456, "0x9876543210", "0xad77d2c5f941160");
|
||||
testBinary64('div_s', -40, 2, -20);
|
||||
testBinary64('div_s', "0x1234567887654321", 2, "0x91a2b3c43b2a190");
|
||||
testBinary64('div_s', "0x1234567887654321", "0x1000000000", "0x1234567");
|
||||
testBinary64('div_u', -40, 2, "0x7fffffffffffffec");
|
||||
testBinary64('div_u', "0x1234567887654321", 9, "0x205d0b80f0b4059");
|
||||
testBinary64('rem_s', 40, -3, 1);
|
||||
testBinary64('rem_s', "0x1234567887654321", "0x1000000000", "0x887654321");
|
||||
testBinary64('rem_s', "0x7fffffffffffffff", -1, 0);
|
||||
testBinary64('rem_s', "0x8000000000000001", 1000, -807);
|
||||
testBinary64('rem_s', "0x8000000000000000", -1, 0);
|
||||
testBinary64('rem_u', 40, -3, 40);
|
||||
testBinary64('rem_u', "0x1234567887654321", "0x1000000000", "0x887654321");
|
||||
testBinary64('rem_u', "0x8000000000000000", -1, "0x8000000000000000");
|
||||
testBinary64('rem_u', "0x8ff00ff00ff00ff0", "0x100000001", "0x80000001");
|
||||
|
||||
// These should trap, but for now we match the i32 version.
|
||||
testBinary('i64', 'div_s', 10, 0, 0);
|
||||
testBinary('i64', 'div_s', "0x8000000000000000", -1, "0x8000000000000000");
|
||||
testBinary('i64', 'div_u', 0, 0, 0);
|
||||
testBinary('i64', 'rem_s', 10, 0, 0);
|
||||
testBinary('i64', 'rem_u', 10, 0, 0);
|
||||
testTrap64('div_s', 10, 0, /integer divide by zero/);
|
||||
testTrap64('div_s', "0x8000000000000000", -1, /integer overflow/);
|
||||
testTrap64('div_u', 0, 0, /integer divide by zero/);
|
||||
testTrap64('rem_s', 10, 0, /integer divide by zero/);
|
||||
testTrap64('rem_u', 10, 0, /integer divide by zero/);
|
||||
|
||||
testBinary('i64', 'and', 42, 6, 2);
|
||||
testBinary('i64', 'or', 42, 6, 46);
|
||||
testBinary('i64', 'xor', 42, 2, 40);
|
||||
testBinary('i64', 'and', "0x8765432112345678", "0xffff0000ffff0000", "0x8765000012340000");
|
||||
testBinary('i64', 'or', "0x8765432112345678", "0xffff0000ffff0000", "0xffff4321ffff5678");
|
||||
testBinary('i64', 'xor', "0x8765432112345678", "0xffff0000ffff0000", "0x789a4321edcb5678");
|
||||
testBinary('i64', 'shl', 40, 2, 160);
|
||||
testBinary('i64', 'shr_s', -40, 2, -10);
|
||||
testBinary('i64', 'shr_u', -40, 2, "0x3ffffffffffffff6");
|
||||
testBinary('i64', 'shl', 0xff00ff, 28, "0xff00ff0000000");
|
||||
testBinary('i64', 'shl', 1, 63, "0x8000000000000000");
|
||||
testBinary('i64', 'shl', 1, 64, 1);
|
||||
testBinary('i64', 'shr_s', "0xff00ff0000000", 28, 0xff00ff);
|
||||
testBinary('i64', 'shr_u', "0x8ffff00ff0000000", 56, 0x8f);
|
||||
//testBinary('i64', 'rotl', 40, 2, 160); // NYI: rotate
|
||||
//testBinary('i64', 'rotr', 40, 2, 10); // NYI: rotate
|
||||
testBinary64('and', 42, 6, 2);
|
||||
testBinary64('or', 42, 6, 46);
|
||||
testBinary64('xor', 42, 2, 40);
|
||||
testBinary64('and', "0x8765432112345678", "0xffff0000ffff0000", "0x8765000012340000");
|
||||
testBinary64('or', "0x8765432112345678", "0xffff0000ffff0000", "0xffff4321ffff5678");
|
||||
testBinary64('xor', "0x8765432112345678", "0xffff0000ffff0000", "0x789a4321edcb5678");
|
||||
testBinary64('shl', 40, 2, 160);
|
||||
testBinary64('shr_s', -40, 2, -10);
|
||||
testBinary64('shr_u', -40, 2, "0x3ffffffffffffff6");
|
||||
testBinary64('shl', 0xff00ff, 28, "0xff00ff0000000");
|
||||
testBinary64('shl', 1, 63, "0x8000000000000000");
|
||||
testBinary64('shl', 1, 64, 1);
|
||||
testBinary64('shr_s', "0xff00ff0000000", 28, 0xff00ff);
|
||||
testBinary64('shr_u', "0x8ffff00ff0000000", 56, 0x8f);
|
||||
testBinary64('rotl', 40, 2, 160);
|
||||
testBinary64('rotr', 40, 2, 10);
|
||||
|
||||
testComparison('i64', 'eq', 40, 40, 1);
|
||||
testComparison('i64', 'ne', 40, 40, 0);
|
||||
testComparison('i64', 'lt_s', 40, 40, 0);
|
||||
testComparison('i64', 'lt_u', 40, 40, 0);
|
||||
testComparison('i64', 'le_s', 40, 40, 1);
|
||||
testComparison('i64', 'le_u', 40, 40, 1);
|
||||
testComparison('i64', 'gt_s', 40, 40, 0);
|
||||
testComparison('i64', 'gt_u', 40, 40, 0);
|
||||
testComparison('i64', 'ge_s', 40, 40, 1);
|
||||
testComparison('i64', 'ge_u', 40, 40, 1);
|
||||
testComparison('i64', 'eq', "0x400012345678", "0x400012345678", 1);
|
||||
testComparison('i64', 'ne', "0x400012345678", "0x400012345678", 0);
|
||||
testComparison('i64', 'ne', "0x400012345678", "0x500012345678", 1);
|
||||
testComparison('i64', 'eq', "0xffffffffffffffff", -1, 1);
|
||||
testComparison('i64', 'lt_s', "0x8000000012345678", "0x1", 1);
|
||||
testComparison('i64', 'lt_u', "0x8000000012345678", "0x1", 0);
|
||||
testComparison('i64', 'le_s', -1, 0, 1);
|
||||
testComparison('i64', 'le_u', -1, -1, 1);
|
||||
testComparison('i64', 'gt_s', 1, "0x8000000000000000", 1);
|
||||
testComparison('i64', 'gt_u', 1, "0x8000000000000000", 0);
|
||||
testComparison('i64', 'ge_s', 1, "0x8000000000000000", 1);
|
||||
testComparison('i64', 'ge_u', 1, "0x8000000000000000", 0);
|
||||
testComparison64('eq', 40, 40, 1);
|
||||
testComparison64('ne', 40, 40, 0);
|
||||
testComparison64('lt_s', 40, 40, 0);
|
||||
testComparison64('lt_u', 40, 40, 0);
|
||||
testComparison64('le_s', 40, 40, 1);
|
||||
testComparison64('le_u', 40, 40, 1);
|
||||
testComparison64('gt_s', 40, 40, 0);
|
||||
testComparison64('gt_u', 40, 40, 0);
|
||||
testComparison64('ge_s', 40, 40, 1);
|
||||
testComparison64('ge_u', 40, 40, 1);
|
||||
testComparison64('eq', "0x400012345678", "0x400012345678", 1);
|
||||
testComparison64('ne', "0x400012345678", "0x400012345678", 0);
|
||||
testComparison64('ne', "0x400012345678", "0x500012345678", 1);
|
||||
testComparison64('eq', "0xffffffffffffffff", -1, 1);
|
||||
testComparison64('lt_s', "0x8000000012345678", "0x1", 1);
|
||||
testComparison64('lt_u', "0x8000000012345678", "0x1", 0);
|
||||
testComparison64('le_s', -1, 0, 1);
|
||||
testComparison64('le_u', -1, -1, 1);
|
||||
testComparison64('gt_s', 1, "0x8000000000000000", 1);
|
||||
testComparison64('gt_u', 1, "0x8000000000000000", 0);
|
||||
testComparison64('ge_s', 1, "0x8000000000000000", 1);
|
||||
testComparison64('ge_u', 1, "0x8000000000000000", 0);
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 0);
|
||||
} else {
|
||||
// Sleeper test: once i64 works on more platforms, remove this if-else.
|
||||
try {
|
||||
testComparison('i64', 'eq', 40, 40, 1);
|
||||
testComparison64('eq', 40, 40, 1);
|
||||
assertEq(0, 1);
|
||||
} catch(e) {
|
||||
assertEq(e.toString().indexOf("NYI on this platform") >= 0, true);
|
||||
|
||||
@@ -11203,7 +11203,7 @@ void
|
||||
CodeGenerator::visitAsmThrowUnreachable(LAsmThrowUnreachable* lir)
|
||||
{
|
||||
MOZ_ASSERT(gen->compilingAsmJS());
|
||||
masm.jump(wasm::JumpTarget::UnreachableTrap);
|
||||
masm.jump(wasm::JumpTarget::Unreachable);
|
||||
}
|
||||
|
||||
typedef bool (*RecompileFn)(JSContext*);
|
||||
|
||||
@@ -114,7 +114,6 @@ class JitCode : public gc::TenuredCell
|
||||
|
||||
void traceChildren(JSTracer* trc);
|
||||
void finalize(FreeOp* fop);
|
||||
void fixupAfterMovingGC() {}
|
||||
void setInvalidated() {
|
||||
invalidated_ = true;
|
||||
}
|
||||
|
||||
+23
-6
@@ -6875,6 +6875,7 @@ class MDiv : public MBinaryArithInstruction
|
||||
bool canBeDivideByZero_;
|
||||
bool canBeNegativeDividend_;
|
||||
bool unsigned_;
|
||||
bool trapOnError_;
|
||||
|
||||
MDiv(MDefinition* left, MDefinition* right, MIRType type)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
@@ -6882,7 +6883,8 @@ class MDiv : public MBinaryArithInstruction
|
||||
canBeNegativeOverflow_(true),
|
||||
canBeDivideByZero_(true),
|
||||
canBeNegativeDividend_(true),
|
||||
unsigned_(false)
|
||||
unsigned_(false),
|
||||
trapOnError_(false)
|
||||
{
|
||||
if (type != MIRType::Value)
|
||||
specialization_ = type;
|
||||
@@ -6898,10 +6900,11 @@ class MDiv : public MBinaryArithInstruction
|
||||
return new(alloc) MDiv(left, right, type);
|
||||
}
|
||||
static MDiv* NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
MIRType type, bool unsignd)
|
||||
MIRType type, bool unsignd, bool trapOnError = false)
|
||||
{
|
||||
MDiv* div = new(alloc) MDiv(left, right, type);
|
||||
div->unsigned_ = unsignd;
|
||||
div->trapOnError_ = trapOnError;
|
||||
if (type == MIRType::Int32)
|
||||
div->setTruncateKind(Truncate);
|
||||
return div;
|
||||
@@ -6965,6 +6968,10 @@ class MDiv : public MBinaryArithInstruction
|
||||
return isTruncated() || isTruncatedIndirectly();
|
||||
}
|
||||
|
||||
bool trapOnError() const {
|
||||
return trapOnError_;
|
||||
}
|
||||
|
||||
bool isFloat32Commutative() const override { return true; }
|
||||
|
||||
void computeRange(TempAllocator& alloc) override;
|
||||
@@ -6980,8 +6987,11 @@ class MDiv : public MBinaryArithInstruction
|
||||
}
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return MBinaryArithInstruction::congruentTo(ins) &&
|
||||
unsigned_ == ins->toDiv()->isUnsigned();
|
||||
if (!MBinaryArithInstruction::congruentTo(ins))
|
||||
return false;
|
||||
const MDiv* other = ins->toDiv();
|
||||
MOZ_ASSERT(other->trapOnError() == trapOnError_);
|
||||
return unsigned_ == other->isUnsigned();
|
||||
}
|
||||
|
||||
ALLOW_CLONE(MDiv)
|
||||
@@ -6993,13 +7003,15 @@ class MMod : public MBinaryArithInstruction
|
||||
bool canBeNegativeDividend_;
|
||||
bool canBePowerOfTwoDivisor_;
|
||||
bool canBeDivideByZero_;
|
||||
bool trapOnError_;
|
||||
|
||||
MMod(MDefinition* left, MDefinition* right, MIRType type)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
unsigned_(false),
|
||||
canBeNegativeDividend_(true),
|
||||
canBePowerOfTwoDivisor_(true),
|
||||
canBeDivideByZero_(true)
|
||||
canBeDivideByZero_(true),
|
||||
trapOnError_(false)
|
||||
{
|
||||
if (type != MIRType::Value)
|
||||
specialization_ = type;
|
||||
@@ -7012,10 +7024,11 @@ class MMod : public MBinaryArithInstruction
|
||||
return new(alloc) MMod(left, right, MIRType::Value);
|
||||
}
|
||||
static MMod* NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
MIRType type, bool unsignd)
|
||||
MIRType type, bool unsignd, bool trapOnError = false)
|
||||
{
|
||||
MMod* mod = new(alloc) MMod(left, right, type);
|
||||
mod->unsigned_ = unsignd;
|
||||
mod->trapOnError_ = trapOnError;
|
||||
if (type == MIRType::Int32)
|
||||
mod->setTruncateKind(Truncate);
|
||||
return mod;
|
||||
@@ -7049,6 +7062,10 @@ class MMod : public MBinaryArithInstruction
|
||||
return unsigned_;
|
||||
}
|
||||
|
||||
bool trapOnError() const {
|
||||
return trapOnError_;
|
||||
}
|
||||
|
||||
bool writeRecoverData(CompactBufferWriter& writer) const override;
|
||||
bool canRecoverOnBailout() const override {
|
||||
return specialization_ < MIRType::Object;
|
||||
|
||||
@@ -1919,7 +1919,8 @@ RangeAnalysis::analyzeLoop(MBasicBlock* header)
|
||||
#ifdef DEBUG
|
||||
if (JitSpewEnabled(JitSpew_Range)) {
|
||||
Sprinter sp(GetJitContext()->cx);
|
||||
sp.init();
|
||||
if (!sp.init())
|
||||
return false;
|
||||
iterationBound->boundSum.dump(sp);
|
||||
JitSpew(JitSpew_Range, "computed symbolic bound on backedges: %s",
|
||||
sp.string());
|
||||
|
||||
@@ -501,12 +501,16 @@ CodeGeneratorARM::divICommon(MDiv* mir, Register lhs, Register rhs, Register out
|
||||
// If EQ (LHS == INT32_MIN), sets EQ if rhs == -1.
|
||||
masm.ma_cmp(rhs, Imm32(-1), Assembler::Equal);
|
||||
if (mir->canTruncateOverflow()) {
|
||||
// (-INT32_MIN)|0 = INT32_MIN
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
masm.ma_mov(Imm32(INT32_MIN), output);
|
||||
masm.ma_b(&done);
|
||||
masm.bind(&skip);
|
||||
if (mir->trapOnError()) {
|
||||
masm.ma_b(wasm::JumpTarget::IntegerOverflow, Assembler::Equal);
|
||||
} else {
|
||||
// (-INT32_MIN)|0 = INT32_MIN
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
masm.ma_mov(Imm32(INT32_MIN), output);
|
||||
masm.ma_b(&done);
|
||||
masm.bind(&skip);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mir->fallible());
|
||||
bailoutIf(Assembler::Equal, snapshot);
|
||||
@@ -517,12 +521,16 @@ CodeGeneratorARM::divICommon(MDiv* mir, Register lhs, Register rhs, Register out
|
||||
if (mir->canBeDivideByZero()) {
|
||||
masm.ma_cmp(rhs, Imm32(0));
|
||||
if (mir->canTruncateInfinities()) {
|
||||
// Infinity|0 == 0
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
masm.ma_mov(Imm32(0), output);
|
||||
masm.ma_b(&done);
|
||||
masm.bind(&skip);
|
||||
if (mir->trapOnError()) {
|
||||
masm.ma_b(wasm::JumpTarget::IntegerDivideByZero, Assembler::Equal);
|
||||
} else {
|
||||
// Infinity|0 == 0
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
masm.ma_mov(Imm32(0), output);
|
||||
masm.ma_b(&done);
|
||||
masm.bind(&skip);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mir->fallible());
|
||||
bailoutIf(Assembler::Equal, snapshot);
|
||||
@@ -544,7 +552,6 @@ CodeGeneratorARM::divICommon(MDiv* mir, Register lhs, Register rhs, Register out
|
||||
void
|
||||
CodeGeneratorARM::visitDivI(LDivI* ins)
|
||||
{
|
||||
// Extract the registers from this instruction.
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
Register rhs = ToRegister(ins->rhs());
|
||||
Register temp = ToRegister(ins->getTemp(0));
|
||||
@@ -578,7 +585,6 @@ extern "C" {
|
||||
void
|
||||
CodeGeneratorARM::visitSoftDivI(LSoftDivI* ins)
|
||||
{
|
||||
// Extract the registers from this instruction.
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
Register rhs = ToRegister(ins->rhs());
|
||||
Register output = ToRegister(ins->output());
|
||||
@@ -673,12 +679,16 @@ CodeGeneratorARM::modICommon(MMod* mir, Register lhs, Register rhs, Register out
|
||||
masm.ma_cmp(rhs, Imm32(0));
|
||||
masm.ma_cmp(lhs, Imm32(0), Assembler::LessThan);
|
||||
if (mir->isTruncated()) {
|
||||
// NaN|0 == 0 and (0 % -X)|0 == 0
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
masm.ma_mov(Imm32(0), output);
|
||||
masm.ma_b(&done);
|
||||
masm.bind(&skip);
|
||||
if (mir->trapOnError()) {
|
||||
masm.ma_b(wasm::JumpTarget::IntegerDivideByZero, Assembler::Equal);
|
||||
} else {
|
||||
// NaN|0 == 0 and (0 % -X)|0 == 0
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
masm.ma_mov(Imm32(0), output);
|
||||
masm.ma_b(&done);
|
||||
masm.bind(&skip);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mir->fallible());
|
||||
bailoutIf(Assembler::Equal, snapshot);
|
||||
@@ -2648,12 +2658,16 @@ CodeGeneratorARM::generateUDivModZeroCheck(Register rhs, Register output, Label*
|
||||
if (mir->canBeDivideByZero()) {
|
||||
masm.ma_cmp(rhs, Imm32(0));
|
||||
if (mir->isTruncated()) {
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
// Infinity|0 == 0
|
||||
masm.ma_mov(Imm32(0), output);
|
||||
masm.ma_b(done);
|
||||
masm.bind(&skip);
|
||||
if (mir->trapOnError()) {
|
||||
masm.ma_b(wasm::JumpTarget::IntegerDivideByZero, Assembler::Equal);
|
||||
} else {
|
||||
Label skip;
|
||||
masm.ma_b(&skip, Assembler::NotEqual);
|
||||
// Infinity|0 == 0
|
||||
masm.ma_mov(Imm32(0), output);
|
||||
masm.ma_b(done);
|
||||
masm.bind(&skip);
|
||||
}
|
||||
} else {
|
||||
// Bailout for divide by zero
|
||||
MOZ_ASSERT(mir->fallible());
|
||||
@@ -2965,8 +2979,8 @@ CodeGeneratorARM::visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCheck* oo
|
||||
|
||||
// Handle errors.
|
||||
masm.bind(&fail);
|
||||
masm.jump(wasm::JumpTarget::IntegerOverflowTrap);
|
||||
masm.jump(wasm::JumpTarget::IntegerOverflow);
|
||||
|
||||
masm.bind(&inputIsNaN);
|
||||
masm.jump(wasm::JumpTarget::InvalidConversionToIntegerTrap);
|
||||
masm.jump(wasm::JumpTarget::InvalidConversionToInteger);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user