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:
2024-10-09 21:36:44 +08:00
parent ef3af9173b
commit 39770f3213
176 changed files with 6673 additions and 4031 deletions
+3 -1
View File
@@ -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;
+1 -1
View File
@@ -141,7 +141,7 @@ public:
IMPL_EVENT_HANDLER(load)
IMPL_EVENT_HANDLER(timeout)
IMPL_EVENT_HANDLER(loadend)
virtual void DisconnectFromOwner() override;
};
+9 -3
View File
@@ -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);
+71 -4
View File
@@ -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,
+134 -1
View File
@@ -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
+36 -29
View File
@@ -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";
+2 -8
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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.
-12
View File
@@ -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;
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
+26 -25
View File
@@ -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;
+11 -2
View File
@@ -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;
};
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+4 -9
View File
@@ -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
View File
@@ -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 {
+1 -2
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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);
+2 -2
View File
@@ -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
+9 -9
View File
@@ -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);
+1 -1
View File
@@ -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
+1 -2
View File
@@ -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
+27 -24
View File
@@ -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);
}
};
+10 -6
View File
@@ -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;
}
+1 -1
View File
@@ -150,7 +150,7 @@ class IonCompileTask
}
};
bool
MOZ_MUST_USE bool
IonCompileFunction(IonCompileTask* task);
} // namespace wasm
+14 -14
View File
@@ -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_;
+4 -4
View File
@@ -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_))
+1 -1
View File
@@ -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)
+43 -8
View File
@@ -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;
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
};
+16 -16
View File
@@ -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.
//
+3 -3
View File
@@ -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
View File
@@ -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);
/**
-23
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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()
{
+35 -9
View File
@@ -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
+15 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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__ */
+3 -3
View File
@@ -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();
};
+2 -2
View File
@@ -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);
}
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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
+8 -8
View File
@@ -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[];
+3 -3
View File
@@ -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 */
+61 -58
View File
@@ -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; \
};
+1 -1
View File
@@ -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*
+6 -6
View File
@@ -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 {
+4 -2
View File
@@ -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
+15 -1
View File
@@ -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
+20 -10
View File
@@ -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;
}
+10 -6
View File
@@ -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);
+2 -1
View File
@@ -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
View File
@@ -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 */
+2 -2
View File
@@ -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)
{
+17 -16
View File
@@ -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) {
+1 -1
View File
@@ -17,7 +17,7 @@ namespace frontend {
class ParseNode;
bool
MOZ_MUST_USE bool
NameFunctions(ExclusiveContext* cx, ParseNode* pn);
} /* namespace frontend */
+10 -10
View File
@@ -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) {
+7 -7
View File
@@ -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);
}
};
+13 -7
View File
@@ -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 <>
+2 -6
View File
@@ -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; }
+13 -15
View File
@@ -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) {}
+26 -26
View File
@@ -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
View File
@@ -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>
+8 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+5 -9
View File
@@ -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
View File
@@ -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();
+9 -3
View File
@@ -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
View File
@@ -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());
+3 -3
View File
@@ -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)
+2 -4
View File
@@ -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
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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();
}
};
+1 -1
View File
@@ -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());
+1 -1
View File
@@ -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();
+2 -2
View File
@@ -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;
+140 -124
View File
@@ -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);
+1 -1
View File
@@ -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*);
-1
View File
@@ -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
View File
@@ -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;
+2 -1
View File
@@ -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());
+42 -28
View File
@@ -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