Merge latest green b2g-inbound changeset and mozilla-central

This commit is contained in:
Ed Morley 2013-09-03 12:11:50 +01:00
Родитель 0493380e7e 24692768fa
Коммит f5a01c7e10
103 изменённых файлов: 1536 добавлений и 3578 удалений

Просмотреть файл

@ -223,7 +223,8 @@ if test "$GNU_CC"; then
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections" CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
fi fi
CXXFLAGS="$CXXFLAGS -fno-exceptions" CFLAGS="$CFLAGS -fno-math-errno"
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
fi fi
dnl ======================================================== dnl ========================================================

Просмотреть файл

@ -9227,19 +9227,32 @@ fi
dist=$MOZ_BUILD_ROOT/dist dist=$MOZ_BUILD_ROOT/dist
ac_configure_args="$_SUBDIR_CONFIG_ARGS" ac_configure_args="$_SUBDIR_CONFIG_ARGS"
ac_configure_args="$ac_configure_args --enable-threadsafe" ac_configure_args="$ac_configure_args --enable-threadsafe"
MOZ_ARG_WITH_STRING(intl-api,
[ --with-intl-api, --with-intl-api=build, --without-intl-api
Determine the status of the ECMAScript Internationalization API. The first
(or lack of any of these) builds and exposes the API. The second builds it
but doesn't use ICU or expose the API to script. The third doesn't build
ICU at all.],
WITH_INTL="--with-intl-api=$withval"
])
if test -z "$WITH_INTL"; then
if test "$NIGHTLY_BUILD" = "1" -a "$MOZ_BUILD_APP" = "browser"; then if test "$NIGHTLY_BUILD" = "1" -a "$MOZ_BUILD_APP" = "browser"; then
# In desktop nightlies the Internationalization API is disabled, but all # In desktop nightlies the Internationalization API is disabled, but all
# code for it is still built. Bug 853301 will remove this so that it's # code for it is still built. Bug 853301 will remove this so that it's
# built and the API is enabled. # built and the API is enabled.
ac_configure_args="$ac_configure_args --with-intl-api=build" WITH_INTL="--with-intl-api=build"
else else
# Internationalization isn't built or exposed by default in non-desktop and # Internationalization isn't built or exposed by default in non-desktop and
# non-nightly builds. Bugs to enable: # non-nightly builds. Bugs to enable:
# #
# Android: bug 864843 # Android: bug 864843
# B2G: bug 866301 # B2G: bug 866301
ac_configure_args="$ac_configure_args --without-intl-api" WITH_INTL="--without-intl-api"
fi fi
fi
ac_configure_args="$ac_configure_args $WITH_INTL"
if test "$BUILD_CTYPES"; then if test "$BUILD_CTYPES"; then
# Build js-ctypes on the platforms we can. # Build js-ctypes on the platforms we can.
ac_configure_args="$ac_configure_args --enable-ctypes" ac_configure_args="$ac_configure_args --enable-ctypes"

Просмотреть файл

@ -149,6 +149,7 @@ protected:
nsString mContentType; nsString mContentType;
nsString mName; nsString mName;
nsString mPath; // The path relative to a directory chosen by the user
uint64_t mStart; uint64_t mStart;
uint64_t mLength; uint64_t mLength;
@ -300,6 +301,8 @@ public:
NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE; NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE; NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
void SetPath(const nsAString& aFullPath);
protected: protected:
// Create slice // Create slice
nsDOMFileFile(const nsDOMFileFile* aOther, uint64_t aStart, uint64_t aLength, nsDOMFileFile(const nsDOMFileFile* aOther, uint64_t aStart, uint64_t aLength,

Просмотреть файл

@ -59,11 +59,13 @@ interface nsIDOMBlob : nsISupports
[notxpcom] FileInfo getFileInfo(in FileManager aFileManager); [notxpcom] FileInfo getFileInfo(in FileManager aFileManager);
}; };
[scriptable, builtinclass, uuid(6928584d-7d87-4d56-9ce1-1c89c24f2c6a)] [scriptable, builtinclass, uuid(0acb4135-9f79-4516-ba92-b5fba5203620)]
interface nsIDOMFile : nsIDOMBlob interface nsIDOMFile : nsIDOMBlob
{ {
readonly attribute DOMString name; readonly attribute DOMString name;
readonly attribute DOMString path;
[implicit_jscontext] [implicit_jscontext]
readonly attribute jsval lastModifiedDate; readonly attribute jsval lastModifiedDate;

Просмотреть файл

@ -299,6 +299,16 @@ public:
mMatchNameSpaceId == aKey.mMatchNameSpaceId; mMatchNameSpaceId == aKey.mMatchNameSpaceId;
} }
/**
* Sets the state to LIST_DIRTY and clears mElements array.
* @note This is the only acceptable way to set state to LIST_DIRTY.
*/
void SetDirty()
{
mState = LIST_DIRTY;
Reset();
}
protected: protected:
/** /**
* Returns whether the element matches our criterion * Returns whether the element matches our criterion
@ -350,16 +360,6 @@ protected:
*/ */
inline void BringSelfUpToDate(bool aDoFlush); inline void BringSelfUpToDate(bool aDoFlush);
/**
* Sets the state to LIST_DIRTY and clears mElements array.
* @note This is the only acceptable way to set state to LIST_DIRTY.
*/
void SetDirty()
{
mState = LIST_DIRTY;
Reset();
}
/** /**
* To be called from non-destructor locations that want to remove from caches. * To be called from non-destructor locations that want to remove from caches.
* Needed because if subclasses want to have cache behavior they can't just * Needed because if subclasses want to have cache behavior they can't just

Просмотреть файл

@ -126,6 +126,14 @@ nsDOMFileBase::GetName(nsAString &aFileName)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsDOMFileBase::GetPath(nsAString &aPath)
{
NS_ASSERTION(mIsFile, "Should only be called on files");
aPath = mPath;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsDOMFileBase::GetLastModifiedDate(JSContext* cx, JS::Value *aLastModifiedDate) nsDOMFileBase::GetLastModifiedDate(JSContext* cx, JS::Value *aLastModifiedDate)
{ {
@ -591,6 +599,12 @@ nsDOMFileFile::GetInternalStream(nsIInputStream **aStream)
-1, -1, sFileStreamFlags); -1, -1, sFileStreamFlags);
} }
void
nsDOMFileFile::SetPath(const nsAString& aPath)
{
mPath = aPath;
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// nsDOMMemoryFile implementation // nsDOMMemoryFile implementation

Просмотреть файл

@ -289,7 +289,7 @@ nsXMLHttpRequest::nsXMLHttpRequest()
mProgressSinceLastProgressEvent(false), mProgressSinceLastProgressEvent(false),
mRequestSentTime(0), mTimeoutMilliseconds(0), mRequestSentTime(0), mTimeoutMilliseconds(0),
mErrorLoad(false), mWaitingForOnStopRequest(false), mErrorLoad(false), mWaitingForOnStopRequest(false),
mProgressTimerIsActive(false), mProgressEventWasDelayed(false), mProgressTimerIsActive(false),
mIsHtml(false), mIsHtml(false),
mWarnAboutSyncHtml(false), mWarnAboutSyncHtml(false),
mLoadLengthComputable(false), mLoadTotal(0), mLoadLengthComputable(false), mLoadTotal(0),
@ -3752,7 +3752,6 @@ nsXMLHttpRequest::StartProgressEventTimer()
mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID); mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
} }
if (mProgressNotifier) { if (mProgressNotifier) {
mProgressEventWasDelayed = false;
mProgressTimerIsActive = true; mProgressTimerIsActive = true;
mProgressNotifier->Cancel(); mProgressNotifier->Cancel();
mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL, mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,

Просмотреть файл

@ -673,7 +673,6 @@ protected:
bool mErrorLoad; bool mErrorLoad;
bool mWaitingForOnStopRequest; bool mWaitingForOnStopRequest;
bool mProgressTimerIsActive; bool mProgressTimerIsActive;
bool mProgressEventWasDelayed;
bool mIsHtml; bool mIsHtml;
bool mWarnAboutMultipartHtml; bool mWarnAboutMultipartHtml;
bool mWarnAboutSyncHtml; bool mWarnAboutSyncHtml;

Просмотреть файл

@ -240,13 +240,13 @@ class HTMLInputElementState MOZ_FINAL : public nsISupports
mValue = aValue; mValue = aValue;
} }
const nsCOMArray<nsIDOMFile>& GetFiles() { const nsTArray<nsCOMPtr<nsIDOMFile> >& GetFiles() {
return mFiles; return mFiles;
} }
void SetFiles(const nsCOMArray<nsIDOMFile>& aFiles) { void SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles) {
mFiles.Clear(); mFiles.Clear();
mFiles.AppendObjects(aFiles); mFiles.AppendElements(aFiles);
} }
HTMLInputElementState() HTMLInputElementState()
@ -257,7 +257,7 @@ class HTMLInputElementState MOZ_FINAL : public nsISupports
protected: protected:
nsString mValue; nsString mValue;
nsCOMArray<nsIDOMFile> mFiles; nsTArray<nsCOMPtr<nsIDOMFile> > mFiles;
bool mChecked; bool mChecked;
bool mCheckedSet; bool mCheckedSet;
}; };
@ -314,6 +314,221 @@ UploadLastDir::ContentPrefCallback::HandleError(nsresult error)
return NS_OK; return NS_OK;
} }
namespace {
/**
* This enumerator returns nsDOMFileFile objects after wrapping a single
* nsIFile representing a directory. It enumerates the files under that
* directory and its subdirectories as a flat list of files, ignoring/skipping
* over symbolic links.
*
* The enumeration involves I/O, so this class must NOT be used on the main
* thread or else the main thread could be blocked for a very long time.
*
* This enumerator does not walk the directory tree breadth-first, but it also
* is not guaranteed to walk it depth-first either (since it uses
* nsIFile::GetDirectoryEntries, which is not guaranteed to group a directory's
* subdirectories at the beginning of the list that it returns).
*/
class DirPickerRecursiveFileEnumerator MOZ_FINAL
: public nsISimpleEnumerator
{
public:
NS_DECL_ISUPPORTS
DirPickerRecursiveFileEnumerator(nsIFile* aTopDir)
: mTopDir(aTopDir)
{
MOZ_ASSERT(!NS_IsMainThread(), "This class blocks on I/O!");
#ifdef DEBUG
{
bool isDir;
aTopDir->IsDirectory(&isDir);
MOZ_ASSERT(isDir);
}
#endif
nsCOMPtr<nsISimpleEnumerator> entries;
if (NS_SUCCEEDED(mTopDir->GetDirectoryEntries(getter_AddRefs(entries))) &&
entries) {
mDirEnumeratorStack.AppendElement(entries);
LookupAndCacheNext();
}
}
NS_IMETHOD
GetNext(nsISupports** aResult)
{
MOZ_ASSERT(!NS_IsMainThread(),
"Walking the directory tree involves I/O, so using this "
"enumerator can block a thread for a long time!");
if (!mNextFile) {
return NS_ERROR_FAILURE;
}
nsRefPtr<nsDOMFileFile> domFile = new nsDOMFileFile(mNextFile);
nsCString relDescriptor;
nsresult rv = mNextFile->GetRelativeDescriptor(mTopDir, relDescriptor);
NS_ENSURE_SUCCESS(rv, rv);
NS_ConvertUTF8toUTF16 path(relDescriptor);
nsAutoString leafName;
mNextFile->GetLeafName(leafName);
MOZ_ASSERT(leafName.Length() <= path.Length());
int32_t length = path.Length() - leafName.Length() - 1; // -1 for "/"
MOZ_ASSERT(length >= -1);
if (length > 0) {
domFile->SetPath(Substring(path, 0, uint32_t(length)));
}
*aResult = static_cast<nsIDOMFile*>(domFile.forget().get());
LookupAndCacheNext();
return NS_OK;
}
NS_IMETHOD
HasMoreElements(bool* aResult)
{
*aResult = !!mNextFile;
return NS_OK;
}
private:
void
LookupAndCacheNext()
{
for (;;) {
if (mDirEnumeratorStack.IsEmpty()) {
mNextFile = nullptr;
break;
}
nsISimpleEnumerator* currentDirEntries =
mDirEnumeratorStack.LastElement();
bool hasMore;
DebugOnly<nsresult> rv = currentDirEntries->HasMoreElements(&hasMore);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (!hasMore) {
mDirEnumeratorStack.RemoveElementAt(mDirEnumeratorStack.Length() - 1);
continue;
}
nsCOMPtr<nsISupports> entry;
rv = currentDirEntries->GetNext(getter_AddRefs(entry));
MOZ_ASSERT(NS_SUCCEEDED(rv));
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
MOZ_ASSERT(file);
bool isLink, isSpecial;
file->IsSymlink(&isLink);
file->IsSpecial(&isSpecial);
if (isLink || isSpecial) {
continue;
}
bool isDir;
file->IsDirectory(&isDir);
if (isDir) {
nsCOMPtr<nsISimpleEnumerator> subDirEntries;
rv = file->GetDirectoryEntries(getter_AddRefs(subDirEntries));
MOZ_ASSERT(NS_SUCCEEDED(rv) && subDirEntries);
mDirEnumeratorStack.AppendElement(subDirEntries);
continue;
}
#ifdef DEBUG
{
bool isFile;
file->IsFile(&isFile);
MOZ_ASSERT(isFile);
}
#endif
mNextFile.swap(file);
return;
}
}
private:
nsCOMPtr<nsIFile> mTopDir;
nsCOMPtr<nsIFile> mNextFile;
nsTArray<nsCOMPtr<nsISimpleEnumerator> > mDirEnumeratorStack;
};
NS_IMPL_ISUPPORTS1(DirPickerRecursiveFileEnumerator, nsISimpleEnumerator)
class DirPickerBuildFileListTask MOZ_FINAL
: public nsRunnable
{
public:
DirPickerBuildFileListTask(HTMLInputElement* aInput, nsIFile* aTopDir)
: mInput(aInput)
, mTopDir(aTopDir)
{}
NS_IMETHOD Run() {
if (!NS_IsMainThread()) {
// Build up list of nsDOMFileFile objects on this dedicated thread:
nsCOMPtr<nsISimpleEnumerator> iter =
new DirPickerRecursiveFileEnumerator(mTopDir);
bool hasMore = true;
nsCOMPtr<nsISupports> tmp;
while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
iter->GetNext(getter_AddRefs(tmp));
nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
MOZ_ASSERT(domFile);
mFileList.AppendElement(domFile);
}
return NS_DispatchToMainThread(this);
}
// Now back on the main thread, set the list on our HTMLInputElement:
if (mFileList.IsEmpty()) {
return NS_OK;
}
// The text control frame (if there is one) isn't going to send a change
// event because it will think this is done by a script.
// So, we can safely send one by ourself.
mInput->SetFiles(mFileList, true);
nsresult rv =
nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
NS_LITERAL_STRING("change"), true,
false);
// Clear mInput to make sure that it can't lose its last strong ref off the
// main thread (which may happen if our dtor runs off the main thread)!
mInput = nullptr;
return rv;
}
private:
nsRefPtr<HTMLInputElement> mInput;
nsCOMPtr<nsIFile> mTopDir;
nsTArray<nsCOMPtr<nsIDOMFile> > mFileList;
};
static already_AddRefed<nsIFile>
DOMFileToLocalFile(nsIDOMFile* aDomFile)
{
nsString path;
nsresult rv = aDomFile->GetMozFullPathInternal(path);
if (NS_FAILED(rv) || path.IsEmpty()) {
return nullptr;
}
nsCOMPtr<nsIFile> localFile;
rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
getter_AddRefs(localFile));
NS_ENSURE_SUCCESS(rv, nullptr);
return localFile.forget();
}
} // anonymous namespace
NS_IMETHODIMP NS_IMETHODIMP
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult) HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
{ {
@ -323,11 +538,43 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
int16_t mode; int16_t mode;
mFilePicker->GetMode(&mode); mFilePicker->GetMode(&mode);
bool multi = mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple);
if (mode == static_cast<int16_t>(nsIFilePicker::modeGetFolder)) {
// Directory picking is different, since we still need to do more I/O to
// build up the list of nsDOMFileFile objects. Since this may block for a
// long time, we need to build the list off on another dedicated thread to
// avoid blocking any other activities that the browser is carrying out.
// The user selected this directory, so we always save this dir, even if
// no files are found under it.
nsCOMPtr<nsIFile> pickedDir;
mFilePicker->GetFile(getter_AddRefs(pickedDir));
#ifdef DEBUG
{
bool isDir;
pickedDir->IsDirectory(&isDir);
MOZ_ASSERT(isDir);
}
#endif
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), pickedDir);
nsCOMPtr<nsIEventTarget> target
= do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
NS_ASSERTION(target, "Must have stream transport service");
// DirPickerBuildFileListTask takes care of calling SetFiles() and
// dispatching the "change" event.
nsRefPtr<DirPickerBuildFileListTask> event =
new DirPickerBuildFileListTask(mInput.get(), pickedDir.get());
return target->Dispatch(event, NS_DISPATCH_NORMAL);
}
// Collect new selected filenames // Collect new selected filenames
nsCOMArray<nsIDOMFile> newFiles; nsTArray<nsCOMPtr<nsIDOMFile> > newFiles;
if (multi) { if (mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)) {
nsCOMPtr<nsISimpleEnumerator> iter; nsCOMPtr<nsISimpleEnumerator> iter;
nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter)); nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -337,41 +584,35 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
} }
nsCOMPtr<nsISupports> tmp; nsCOMPtr<nsISupports> tmp;
bool prefSaved = false; bool hasMore = true;
bool loop = true;
while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) { while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
iter->GetNext(getter_AddRefs(tmp)); iter->GetNext(getter_AddRefs(tmp));
nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp); nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
MOZ_ASSERT(domFile); MOZ_ASSERT(domFile);
newFiles.AppendElement(domFile);
newFiles.AppendObject(domFile);
if (!prefSaved) {
// Store the last used directory using the content pref service
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), domFile);
prefSaved = true;
}
} }
} } else {
else { MOZ_ASSERT(mode == static_cast<int16_t>(nsIFilePicker::modeOpen));
nsCOMPtr<nsIDOMFile> domFile; nsCOMPtr<nsIDOMFile> domFile;
nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile)); nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (domFile) { if (domFile) {
newFiles.AppendObject(domFile); newFiles.AppendElement(domFile);
// Store the last used directory using the content pref service
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), domFile);
} }
} }
if (!newFiles.Count()) { if (newFiles.IsEmpty()) {
return NS_OK; return NS_OK;
} }
// Store the last used directory using the content pref service:
nsCOMPtr<nsIFile> file = DOMFileToLocalFile(newFiles[0]);
nsCOMPtr<nsIFile> lastUsedDir;
file->GetParent(getter_AddRefs(lastUsedDir));
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), lastUsedDir);
// The text control frame (if there is one) isn't going to send a change // The text control frame (if there is one) isn't going to send a change
// event because it will think this is done by a script. // event because it will think this is done by a script.
// So, we can safely send one by ourself. // So, we can safely send one by ourself.
@ -543,7 +784,7 @@ HTMLInputElement::InitColorPicker()
} }
nsresult nsresult
HTMLInputElement::InitFilePicker() HTMLInputElement::InitFilePicker(FilePickerType aType)
{ {
// Get parent nsPIDOMWindow object. // Get parent nsPIDOMWindow object.
nsCOMPtr<nsIDocument> doc = OwnerDoc(); nsCOMPtr<nsIDocument> doc = OwnerDoc();
@ -567,15 +808,23 @@ HTMLInputElement::InitFilePicker()
if (!filePicker) if (!filePicker)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
bool multi = HasAttr(kNameSpaceID_None, nsGkAtoms::multiple); int16_t mode;
nsresult rv = filePicker->Init(win, title, if (aType == FILE_PICKER_DIRECTORY) {
multi mode = static_cast<int16_t>(nsIFilePicker::modeGetFolder);
? static_cast<int16_t>(nsIFilePicker::modeOpenMultiple) } else if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
: static_cast<int16_t>(nsIFilePicker::modeOpen)); mode = static_cast<int16_t>(nsIFilePicker::modeOpenMultiple);
} else {
mode = static_cast<int16_t>(nsIFilePicker::modeOpen);
}
nsresult rv = filePicker->Init(win, title, mode);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) { // Native directory pickers ignore file type filters, so we don't spend
// cycles adding them for FILE_PICKER_DIRECTORY.
if (HasAttr(kNameSpaceID_None, nsGkAtoms::accept) &&
aType != FILE_PICKER_DIRECTORY) {
SetFilePickerFiltersFromAccept(filePicker); SetFilePickerFiltersFromAccept(filePicker);
} else { } else {
filePicker->AppendFilters(nsIFilePicker::filterAll); filePicker->AppendFilters(nsIFilePicker::filterAll);
@ -584,12 +833,13 @@ HTMLInputElement::InitFilePicker()
// Set default directry and filename // Set default directry and filename
nsAutoString defaultName; nsAutoString defaultName;
const nsCOMArray<nsIDOMFile>& oldFiles = GetFilesInternal(); const nsTArray<nsCOMPtr<nsIDOMFile> >& oldFiles = GetFilesInternal();
nsCOMPtr<nsIFilePickerShownCallback> callback = nsCOMPtr<nsIFilePickerShownCallback> callback =
new HTMLInputElement::nsFilePickerShownCallback(this, filePicker); new HTMLInputElement::nsFilePickerShownCallback(this, filePicker);
if (oldFiles.Count()) { if (!oldFiles.IsEmpty() &&
aType != FILE_PICKER_DIRECTORY) {
nsString path; nsString path;
oldFiles[0]->GetMozFullPathInternal(path); oldFiles[0]->GetMozFullPathInternal(path);
@ -608,7 +858,7 @@ HTMLInputElement::InitFilePicker()
// Unfortunately nsIFilePicker doesn't allow multiple files to be // Unfortunately nsIFilePicker doesn't allow multiple files to be
// default-selected, so only select something by default if exactly // default-selected, so only select something by default if exactly
// one file was selected before. // one file was selected before.
if (oldFiles.Count() == 1) { if (oldFiles.Length() == 1) {
nsAutoString leafName; nsAutoString leafName;
oldFiles[0]->GetName(leafName); oldFiles[0]->GetName(leafName);
if (!leafName.IsEmpty()) { if (!leafName.IsEmpty()) {
@ -621,7 +871,6 @@ HTMLInputElement::InitFilePicker()
HTMLInputElement::gUploadLastDir->FetchDirectoryAndDisplayPicker(doc, filePicker, callback); HTMLInputElement::gUploadLastDir->FetchDirectoryAndDisplayPicker(doc, filePicker, callback);
return NS_OK; return NS_OK;
} }
#define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir") #define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir")
@ -680,31 +929,16 @@ UploadLastDir::FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
} }
nsresult nsresult
UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile) UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir)
{ {
NS_PRECONDITION(aDoc, "aDoc is null"); NS_PRECONDITION(aDoc, "aDoc is null");
NS_PRECONDITION(aDomFile, "aDomFile is null"); if (!aDir) {
nsString path;
nsresult rv = aDomFile->GetMozFullPathInternal(path);
if (NS_FAILED(rv) || path.IsEmpty()) {
return NS_OK; return NS_OK;
} }
nsCOMPtr<nsIFile> localFile;
rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
getter_AddRefs(localFile));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI(); nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
NS_PRECONDITION(docURI, "docURI is null"); NS_PRECONDITION(docURI, "docURI is null");
nsCOMPtr<nsIFile> parentFile;
localFile->GetParent(getter_AddRefs(parentFile));
if (!parentFile) {
return NS_OK;
}
// Attempt to get the CPS, if it's not present we'll just return // Attempt to get the CPS, if it's not present we'll just return
nsCOMPtr<nsIContentPrefService2> contentPrefService = nsCOMPtr<nsIContentPrefService2> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID); do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
@ -717,7 +951,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile)
// Find the parent of aFile, and store it // Find the parent of aFile, and store it
nsString unicodePath; nsString unicodePath;
parentFile->GetPath(unicodePath); aDir->GetPath(unicodePath);
if (unicodePath.IsEmpty()) // nothing to do if (unicodePath.IsEmpty()) // nothing to do
return NS_OK; return NS_OK;
nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID); nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
@ -906,7 +1140,7 @@ HTMLInputElement::Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const
GetDisplayFileName(it->mStaticDocFileList); GetDisplayFileName(it->mStaticDocFileList);
} else { } else {
it->mFiles.Clear(); it->mFiles.Clear();
it->mFiles.AppendObjects(mFiles); it->mFiles.AppendElements(mFiles);
} }
break; break;
case VALUE_MODE_DEFAULT_ON: case VALUE_MODE_DEFAULT_ON:
@ -1264,7 +1498,7 @@ HTMLInputElement::GetValueInternal(nsAString& aValue) const
case VALUE_MODE_FILENAME: case VALUE_MODE_FILENAME:
if (nsContentUtils::IsCallerChrome()) { if (nsContentUtils::IsCallerChrome()) {
if (mFiles.Count()) { if (!mFiles.IsEmpty()) {
return mFiles[0]->GetMozFullPath(aValue); return mFiles[0]->GetMozFullPath(aValue);
} }
else { else {
@ -1272,7 +1506,7 @@ HTMLInputElement::GetValueInternal(nsAString& aValue) const
} }
} else { } else {
// Just return the leaf name // Just return the leaf name
if (mFiles.Count() == 0 || NS_FAILED(mFiles[0]->GetName(aValue))) { if (mFiles.IsEmpty() || NS_FAILED(mFiles[0]->GetName(aValue))) {
aValue.Truncate(); aValue.Truncate();
} }
} }
@ -1818,7 +2052,7 @@ HTMLInputElement::StepUp(int32_t n, uint8_t optional_argc)
void void
HTMLInputElement::MozGetFileNameArray(nsTArray< nsString >& aArray) HTMLInputElement::MozGetFileNameArray(nsTArray< nsString >& aArray)
{ {
for (int32_t i = 0; i < mFiles.Count(); i++) { for (uint32_t i = 0; i < mFiles.Length(); i++) {
nsString str; nsString str;
mFiles[i]->GetMozFullPathInternal(str); mFiles[i]->GetMozFullPathInternal(str);
aArray.AppendElement(str); aArray.AppendElement(str);
@ -1857,7 +2091,7 @@ HTMLInputElement::MozGetFileNameArray(uint32_t* aLength, PRUnichar*** aFileNames
void void
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames) HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
{ {
nsCOMArray<nsIDOMFile> files; nsTArray<nsCOMPtr<nsIDOMFile> > files;
for (uint32_t i = 0; i < aFileNames.Length(); ++i) { for (uint32_t i = 0; i < aFileNames.Length(); ++i) {
nsCOMPtr<nsIFile> file; nsCOMPtr<nsIFile> file;
@ -1876,7 +2110,7 @@ HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
if (file) { if (file) {
nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(file); nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(file);
files.AppendObject(domFile); files.AppendElement(domFile);
} else { } else {
continue; // Not much we can do if the file doesn't exist continue; // Not much we can do if the file doesn't exist
} }
@ -2068,14 +2302,14 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
return; return;
} }
if (mFiles.Count() == 1) { if (mFiles.Length() == 1) {
mFiles[0]->GetName(aValue); mFiles[0]->GetName(aValue);
return; return;
} }
nsXPIDLString value; nsXPIDLString value;
if (mFiles.Count() == 0) { if (mFiles.IsEmpty()) {
if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) { if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES, nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"NoFilesSelected", value); "NoFilesSelected", value);
@ -2085,7 +2319,7 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
} }
} else { } else {
nsString count; nsString count;
count.AppendInt(mFiles.Count()); count.AppendInt(mFiles.Length());
const PRUnichar* params[] = { count.get() }; const PRUnichar* params[] = { count.get() };
nsContentUtils::FormatLocalizedString(nsContentUtils::eFORMS_PROPERTIES, nsContentUtils::FormatLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
@ -2096,11 +2330,11 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
} }
void void
HTMLInputElement::SetFiles(const nsCOMArray<nsIDOMFile>& aFiles, HTMLInputElement::SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles,
bool aSetValueChanged) bool aSetValueChanged)
{ {
mFiles.Clear(); mFiles.Clear();
mFiles.AppendObjects(aFiles); mFiles.AppendElements(aFiles);
AfterSetFiles(aSetValueChanged); AfterSetFiles(aSetValueChanged);
} }
@ -2117,7 +2351,7 @@ HTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
for (uint32_t i = 0; i < listLength; i++) { for (uint32_t i = 0; i < listLength; i++) {
nsCOMPtr<nsIDOMFile> file; nsCOMPtr<nsIDOMFile> file;
aFiles->Item(i, getter_AddRefs(file)); aFiles->Item(i, getter_AddRefs(file));
mFiles.AppendObject(file); mFiles.AppendElement(file);
} }
} }
@ -2179,14 +2413,23 @@ HTMLInputElement::GetFiles()
return mFileList; return mFileList;
} }
void
HTMLInputElement::OpenDirectoryPicker(ErrorResult& aRv)
{
if (mType != NS_FORM_INPUT_FILE) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
}
InitFilePicker(FILE_PICKER_DIRECTORY);
}
nsresult nsresult
HTMLInputElement::UpdateFileList() HTMLInputElement::UpdateFileList()
{ {
if (mFileList) { if (mFileList) {
mFileList->Clear(); mFileList->Clear();
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal(); const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
for (int32_t i = 0; i < files.Count(); ++i) { for (uint32_t i = 0; i < files.Length(); ++i) {
if (!mFileList->Append(files[i])) { if (!mFileList->Append(files[i])) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -2890,7 +3133,7 @@ HTMLInputElement::MaybeInitPickers(nsEventChainPostVisitor& aVisitor)
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) && if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
!aVisitor.mEvent->mFlags.mDefaultPrevented) { !aVisitor.mEvent->mFlags.mDefaultPrevented) {
if (mType == NS_FORM_INPUT_FILE) { if (mType == NS_FORM_INPUT_FILE) {
return InitFilePicker(); return InitFilePicker(FILE_PICKER_FILE);
} }
if (mType == NS_FORM_INPUT_COLOR) { if (mType == NS_FORM_INPUT_COLOR) {
return InitColorPicker(); return InitColorPicker();
@ -4574,13 +4817,13 @@ HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
if (mType == NS_FORM_INPUT_FILE) { if (mType == NS_FORM_INPUT_FILE) {
// Submit files // Submit files
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal(); const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
for (int32_t i = 0; i < files.Count(); ++i) { for (uint32_t i = 0; i < files.Length(); ++i) {
aFormSubmission->AddNameFilePair(name, files[i], NullString()); aFormSubmission->AddNameFilePair(name, files[i], NullString());
} }
if (files.Count() == 0) { if (files.IsEmpty()) {
// If no file was selected, pretend we had an empty file with an // If no file was selected, pretend we had an empty file with an
// empty filename. // empty filename.
aFormSubmission->AddNameFilePair(name, nullptr, NullString()); aFormSubmission->AddNameFilePair(name, nullptr, NullString());
@ -4617,7 +4860,7 @@ HTMLInputElement::SaveState()
} }
break; break;
case VALUE_MODE_FILENAME: case VALUE_MODE_FILENAME:
if (mFiles.Count()) { if (!mFiles.IsEmpty()) {
inputState = new HTMLInputElementState(); inputState = new HTMLInputElementState();
inputState->SetFiles(mFiles); inputState->SetFiles(mFiles);
} }
@ -4790,7 +5033,7 @@ HTMLInputElement::RestoreState(nsPresState* aState)
break; break;
case VALUE_MODE_FILENAME: case VALUE_MODE_FILENAME:
{ {
const nsCOMArray<nsIDOMFile>& files = inputState->GetFiles(); const nsTArray<nsCOMPtr<nsIDOMFile> >& files = inputState->GetFiles();
SetFiles(files, true); SetFiles(files, true);
} }
break; break;
@ -5257,8 +5500,8 @@ HTMLInputElement::IsValueMissing() const
return IsValueEmpty(); return IsValueEmpty();
case VALUE_MODE_FILENAME: case VALUE_MODE_FILENAME:
{ {
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal(); const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
return !files.Count(); return files.IsEmpty();
} }
case VALUE_MODE_DEFAULT_ON: case VALUE_MODE_DEFAULT_ON:
// This should not be used for type radio. // This should not be used for type radio.

Просмотреть файл

@ -54,10 +54,9 @@ public:
* Store the last used directory for this location using the * Store the last used directory for this location using the
* content pref service, if it is available * content pref service, if it is available
* @param aURI URI of the current page * @param aURI URI of the current page
* @param aDomFile file chosen by the user - the path to the parent of this * @param aDir Parent directory of the file(s)/directory chosen by the user
* file will be stored
*/ */
nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile); nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir);
class ContentPrefCallback MOZ_FINAL : public nsIContentPrefCallback2 class ContentPrefCallback MOZ_FINAL : public nsIContentPrefCallback2
{ {
@ -191,12 +190,12 @@ public:
void GetDisplayFileName(nsAString& aFileName) const; void GetDisplayFileName(nsAString& aFileName) const;
const nsCOMArray<nsIDOMFile>& GetFilesInternal() const const nsTArray<nsCOMPtr<nsIDOMFile> >& GetFilesInternal() const
{ {
return mFiles; return mFiles;
} }
void SetFiles(const nsCOMArray<nsIDOMFile>& aFiles, bool aSetValueChanged); void SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles, bool aSetValueChanged);
void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged); void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
void SetCheckedChangedInternal(bool aCheckedChanged); void SetCheckedChangedInternal(bool aCheckedChanged);
@ -393,6 +392,8 @@ public:
nsDOMFileList* GetFiles(); nsDOMFileList* GetFiles();
void OpenDirectoryPicker(ErrorResult& aRv);
// XPCOM GetFormAction() is OK // XPCOM GetFormAction() is OK
void SetFormAction(const nsAString& aValue, ErrorResult& aRv) void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
{ {
@ -734,7 +735,7 @@ protected:
bool IsValueEmpty() const; bool IsValueEmpty() const;
void ClearFiles(bool aSetValueChanged) { void ClearFiles(bool aSetValueChanged) {
nsCOMArray<nsIDOMFile> files; nsTArray<nsCOMPtr<nsIDOMFile> > files;
SetFiles(files, aSetValueChanged); SetFiles(files, aSetValueChanged);
} }
@ -1080,7 +1081,11 @@ protected:
*/ */
nsresult MaybeInitPickers(nsEventChainPostVisitor& aVisitor); nsresult MaybeInitPickers(nsEventChainPostVisitor& aVisitor);
nsresult InitFilePicker(); enum FilePickerType {
FILE_PICKER_FILE,
FILE_PICKER_DIRECTORY
};
nsresult InitFilePicker(FilePickerType aType);
nsresult InitColorPicker(); nsresult InitColorPicker();
/** /**
@ -1122,7 +1127,7 @@ protected:
* the frame. Whenever the frame wants to change the filename it has to call * the frame. Whenever the frame wants to change the filename it has to call
* SetFileNames to update this member. * SetFileNames to update this member.
*/ */
nsCOMArray<nsIDOMFile> mFiles; nsTArray<nsCOMPtr<nsIDOMFile> > mFiles;
nsRefPtr<nsDOMFileList> mFileList; nsRefPtr<nsDOMFileList> mFileList;

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/dom/HTMLSelectElementBinding.h" #include "mozilla/dom/HTMLSelectElementBinding.h"
#include "mozilla/Util.h" #include "mozilla/Util.h"
#include "nsContentCreatorFunctions.h" #include "nsContentCreatorFunctions.h"
#include "nsContentList.h"
#include "nsError.h" #include "nsError.h"
#include "nsEventDispatcher.h" #include "nsEventDispatcher.h"
#include "nsEventStates.h" #include "nsEventStates.h"
@ -139,10 +140,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLSelectElement,
nsGenericHTMLFormElementWithState) nsGenericHTMLFormElementWithState)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedOptions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLSelectElement, NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLSelectElement,
nsGenericHTMLFormElementWithState) nsGenericHTMLFormElementWithState)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity) NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedOptions)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(HTMLSelectElement, Element) NS_IMPL_ADDREF_INHERITED(HTMLSelectElement, Element)
@ -769,6 +772,34 @@ HTMLSelectElement::SetLength(uint32_t aLength, ErrorResult& aRv)
} }
} }
/* static */
bool
HTMLSelectElement::MatchSelectedOptions(nsIContent* aContent,
int32_t /* unused */,
nsIAtom* /* unused */,
void* /* unused*/)
{
HTMLOptionElement* option = HTMLOptionElement::FromContent(aContent);
return option && option->Selected();
}
nsIHTMLCollection*
HTMLSelectElement::SelectedOptions()
{
if (!mSelectedOptions) {
mSelectedOptions = new nsContentList(this, MatchSelectedOptions, nullptr,
nullptr, /* deep */ true);
}
return mSelectedOptions;
}
NS_IMETHODIMP
HTMLSelectElement::GetSelectedOptions(nsIDOMHTMLCollection** aSelectedOptions)
{
NS_ADDREF(*aSelectedOptions = SelectedOptions());
return NS_OK;
}
//NS_IMPL_INT_ATTR(HTMLSelectElement, SelectedIndex, selectedindex) //NS_IMPL_INT_ATTR(HTMLSelectElement, SelectedIndex, selectedindex)
NS_IMETHODIMP NS_IMETHODIMP
@ -847,6 +878,7 @@ HTMLSelectElement::OnOptionSelected(nsISelectControlFrame* aSelectFrame,
aSelectFrame->OnOptionSelected(aIndex, aSelected); aSelectFrame->OnOptionSelected(aIndex, aSelected);
} }
UpdateSelectedOptions();
UpdateValueMissingValidityState(); UpdateValueMissingValidityState();
UpdateState(aNotify); UpdateState(aNotify);
} }
@ -1848,6 +1880,8 @@ HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify)
return; return;
} }
UpdateSelectedOptions();
bool previousSelectionChangedValue = mSelectionHasChanged; bool previousSelectionChangedValue = mSelectionHasChanged;
mSelectionHasChanged = aValue; mSelectionHasChanged = aValue;
@ -1856,6 +1890,14 @@ HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify)
} }
} }
void
HTMLSelectElement::UpdateSelectedOptions()
{
if (mSelectedOptions) {
mSelectedOptions->SetDirty();
}
}
JSObject* JSObject*
HTMLSelectElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope) HTMLSelectElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
{ {

Просмотреть файл

@ -18,7 +18,9 @@
#include "nsError.h" #include "nsError.h"
#include "mozilla/dom/HTMLFormElement.h" #include "mozilla/dom/HTMLFormElement.h"
class nsContentList;
class nsIDOMHTMLOptionElement; class nsIDOMHTMLOptionElement;
class nsIHTMLCollection;
class nsISelectControlFrame; class nsISelectControlFrame;
class nsPresState; class nsPresState;
@ -208,6 +210,11 @@ public:
mOptions->IndexedSetter(aIndex, aOption, aRv); mOptions->IndexedSetter(aIndex, aOption, aRv);
} }
static bool MatchSelectedOptions(nsIContent* aContent, int32_t, nsIAtom*,
void*);
nsIHTMLCollection* SelectedOptions();
int32_t SelectedIndex() const int32_t SelectedIndex() const
{ {
return mSelectedIndex; return mSelectedIndex;
@ -553,6 +560,12 @@ protected:
void SetSelectionChanged(bool aValue, bool aNotify); void SetSelectionChanged(bool aValue, bool aNotify);
/**
* Marks the selectedOptions list as dirty, so that it'll populate itself
* again.
*/
void UpdateSelectedOptions();
/** /**
* Return whether an element should have a validity UI. * Return whether an element should have a validity UI.
* (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes). * (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes).
@ -618,6 +631,11 @@ protected:
* done adding options * done adding options
*/ */
nsCOMPtr<SelectState> mRestoreState; nsCOMPtr<SelectState> mRestoreState;
/**
* The live list of selected options.
*/
nsRefPtr<nsContentList> mSelectedOptions;
}; };
} // namespace dom } // namespace dom

Просмотреть файл

@ -470,6 +470,13 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
if (filename16.IsEmpty()) { if (filename16.IsEmpty()) {
filename16.AssignLiteral("blob"); filename16.AssignLiteral("blob");
} else {
nsAutoString filepath16;
rv = file->GetPath(filepath16);
NS_ENSURE_SUCCESS(rv, rv);
if (!filepath16.IsEmpty()) {
filename16 = filepath16 + NS_LITERAL_STRING("/") + filename16;
}
} }
rv = EncodeVal(filename16, filename, true); rv = EncodeVal(filename16, filename, true);

Просмотреть файл

@ -67,6 +67,7 @@ MOCHITEST_FILES = \
test_input_color_picker_popup.html \ test_input_color_picker_popup.html \
test_input_color_input_change_events.html \ test_input_color_input_change_events.html \
test_restore_form_elements.html \ test_restore_form_elements.html \
test_select_selectedOptions.html \
$(NULL) $(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,120 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=596681
-->
<head>
<title>Test for HTMLSelectElement.selectedOptions</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596681">Mozilla Bug 596681</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript;version=1.7">
/** Test for HTMLSelectElement's selectedOptions attribute.
*
* selectedOptions is a live list of the options that have selectedness of true
* (not the selected content attribute).
*
* See http://www.whatwg.org/html/#dom-select-selectedoptions
**/
function checkSelectedOptions(size, elements)
{
is(selectedOptions.length, size,
"select should have " + size + " selected options");
for (let i = 0; i < size; ++i) {
ok(selectedOptions[i], "selected option is valid");
if (selectedOptions[i]) {
is(selectedOptions[i].value, elements[i].value, "selected options are correct");
}
}
}
let select = document.createElement("select");
document.body.appendChild(select);
let selectedOptions = select.selectedOptions;
ok("selectedOptions" in select,
"select element should have a selectedOptions IDL attribute");
ok(select.selectedOptions instanceof HTMLCollection,
"selectedOptions should be an HTMLCollection instance");
let option1 = document.createElement("option");
let option2 = document.createElement("option");
let option3 = document.createElement("option");
option1.id = "option1";
option1.value = "option1";
option2.value = "option2";
option3.value = "option3";
checkSelectedOptions(0, null);
select.add(option1, null);
is(selectedOptions.namedItem("option1").value, "option1", "named getter works");
checkSelectedOptions(1, [option1]);
select.add(option2, null);
checkSelectedOptions(1, [option1]);
select.options[1].selected = true;
checkSelectedOptions(1, [option2]);
select.multiple = true;
checkSelectedOptions(1, [option2]);
select.options[0].selected = true;
checkSelectedOptions(2, [option1, option2]);
option1.selected = false;
// Usinig selected directly on the option should work.
checkSelectedOptions(1, [option2]);
select.remove(1);
select.add(option2, 0);
select.options[0].selected = true;
select.options[1].selected = true;
// Should be in tree order.
checkSelectedOptions(2, [option2, option1]);
select.add(option3, null);
checkSelectedOptions(2, [option2, option1]);
select.options[2].selected = true;
checkSelectedOptions(3, [option2, option1, option3]);
select.length = 0;
option1.selected = false;
option2.selected = false;
option3.selected = false;
var optgroup1 = document.createElement("optgroup");
optgroup1.appendChild(option1);
optgroup1.appendChild(option2);
select.add(optgroup1)
var optgroup2 = document.createElement("optgroup");
optgroup2.appendChild(option3);
select.add(optgroup2);
checkSelectedOptions(0, null);
option2.selected = true;
checkSelectedOptions(1, [option2]);
option3.selected = true;
checkSelectedOptions(2, [option2, option3]);
optgroup1.removeChild(option2);
checkSelectedOptions(1, [option3]);
document.body.removeChild(select);
option1.selected = true;
checkSelectedOptions(2, [option1, option3]);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -107,9 +107,6 @@ static bool IsOmxSupported()
// nullptr is returned if Omx decoding is not supported on the device, // nullptr is returned if Omx decoding is not supported on the device,
static const char* GetOmxLibraryName() static const char* GetOmxLibraryName()
{ {
if (!IsOmxSupported())
return nullptr;
#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1"); nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
NS_ASSERTION(infoService, "Could not find a system info service"); NS_ASSERTION(infoService, "Could not find a system info service");
@ -138,19 +135,18 @@ static const char* GetOmxLibraryName()
ALOG("Android Manufacturer is: %s", NS_LossyConvertUTF16toASCII(manufacturer).get()); ALOG("Android Manufacturer is: %s", NS_LossyConvertUTF16toASCII(manufacturer).get());
} }
if (version >= 16 && manufacturer.Find("HTC") == 0) { nsAutoString hardware;
return "libomxpluginjb-htc.so"; rv = infoService->GetPropertyAsAString(NS_LITERAL_STRING("hardware"), hardware);
if (NS_SUCCEEDED(rv)) {
ALOG("Android Hardware is: %s", NS_LossyConvertUTF16toASCII(hardware).get());
} }
else if (version == 15 && #endif
(device.Find("LT28", false) == 0 ||
device.Find("LT26", false) == 0 || if (!IsOmxSupported())
device.Find("LT22", false) == 0 || return nullptr;
device.Find("IS12", false) == 0 ||
device.Find("MT27", false) == 0)) { #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
// Sony Ericsson devices running ICS if (version == 13 || version == 12 || version == 11) {
return "libomxpluginsony.so";
}
else if (version == 13 || version == 12 || version == 11) {
return "libomxpluginhc.so"; return "libomxpluginhc.so";
} }
else if (version == 10 && release_version >= NS_LITERAL_STRING("2.3.6")) { else if (version == 10 && release_version >= NS_LITERAL_STRING("2.3.6")) {

Просмотреть файл

@ -61,7 +61,6 @@ MOCHITEST_FILES := \
test_convolverNode_mono_mono.html \ test_convolverNode_mono_mono.html \
test_currentTime.html \ test_currentTime.html \
test_delayNode.html \ test_delayNode.html \
test_delayNodeAtMax.html \
test_delayNodeSmallMaxDelay.html \ test_delayNodeSmallMaxDelay.html \
test_delayNodeWithGain.html \ test_delayNodeWithGain.html \
test_dynamicsCompressorNode.html \ test_dynamicsCompressorNode.html \
@ -113,4 +112,10 @@ MOCHITEST_FILES := \
audio-quad.wav \ audio-quad.wav \
$(NULL) $(NULL)
ifneq ($(MOZ_DEBUG)+$(MOZ_WIDGET_TOOLKIT),+gtk2) # bug 911777
MOCHITEST_FILES += \
test_delayNodeAtMax.html \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -19,7 +19,7 @@
interface nsIDOMValidityState; interface nsIDOMValidityState;
[scriptable, uuid(846578b2-6d4f-4399-86cc-2c05f19469d0)] [scriptable, uuid(d8914a2d-3556-4b66-911c-a84c4394e7fa)]
interface nsIDOMHTMLSelectElement : nsISupports interface nsIDOMHTMLSelectElement : nsISupports
{ {
attribute boolean autofocus; attribute boolean autofocus;
@ -44,6 +44,7 @@ interface nsIDOMHTMLSelectElement : nsISupports
raises(DOMException); raises(DOMException);
void remove(in long index); void remove(in long index);
readonly attribute nsIDOMHTMLCollection selectedOptions;
attribute long selectedIndex; attribute long selectedIndex;
attribute DOMString value; attribute DOMString value;

Просмотреть файл

@ -33,6 +33,8 @@ interface HTMLInputElement : HTMLElement {
readonly attribute HTMLFormElement? form; readonly attribute HTMLFormElement? form;
[Pure] [Pure]
readonly attribute FileList? files; readonly attribute FileList? files;
[Throws, Pref="dom.input.dirpicker"]
void openDirectoryPicker();
[Pure, SetterThrows] [Pure, SetterThrows]
attribute DOMString formAction; attribute DOMString formAction;
[Pure, SetterThrows] [Pure, SetterThrows]

Просмотреть файл

@ -38,7 +38,7 @@ interface HTMLSelectElement : HTMLElement {
[Throws] [Throws]
setter creator void (unsigned long index, HTMLOptionElement? option); setter creator void (unsigned long index, HTMLOptionElement? option);
// NYI: readonly attribute HTMLCollection selectedOptions; readonly attribute HTMLCollection selectedOptions;
[SetterThrows, Pure] [SetterThrows, Pure]
attribute long selectedIndex; attribute long selectedIndex;
[Pure] [Pure]

Просмотреть файл

@ -353,6 +353,29 @@ private:
return true; return true;
} }
static bool
GetPath(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
{
nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "path");
if (!file) {
return false;
}
nsString path;
if (NS_FAILED(file->GetPath(path))) {
path.Truncate();
}
JSString* jsPath = JS_NewUCStringCopyN(aCx, path.get(), path.Length());
if (!jsPath) {
return false;
}
aVp.set(STRING_TO_JSVAL(jsPath));
return true;
}
static bool static bool
GetLastModifiedDate(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval, GetLastModifiedDate(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp) JS::MutableHandle<JS::Value> aVp)
@ -382,6 +405,8 @@ JSClass File::sClass = {
const JSPropertySpec File::sProperties[] = { const JSPropertySpec File::sProperties[] = {
{ "name", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetName), { "name", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetName),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "path", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetPath),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "lastModifiedDate", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetLastModifiedDate), { "lastModifiedDate", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetLastModifiedDate),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "mozFullPath", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetMozFullPath), { "mozFullPath", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetMozFullPath),

Просмотреть файл

@ -514,13 +514,13 @@ LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */)
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_allocation_threshold_mb"); "gc_allocation_threshold_mb");
if (memPrefName == matchName || (!rts && index == 9)) { if (memPrefName == matchName || (!rts && index == 8)) {
UpdateCommonJSGCMemoryOption(rts, matchName, JSGC_ALLOCATION_THRESHOLD); UpdateCommonJSGCMemoryOption(rts, matchName, JSGC_ALLOCATION_THRESHOLD);
continue; continue;
} }
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_incremental_slice_ms"); matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_incremental_slice_ms");
if (memPrefName == matchName || (!rts && index == 10)) { if (memPrefName == matchName || (!rts && index == 9)) {
int32_t prefValue = GetWorkerPref(matchName, -1); int32_t prefValue = GetWorkerPref(matchName, -1);
uint32_t value = uint32_t value =
(prefValue <= 0 || prefValue >= 100000) ? 0 : uint32_t(prefValue); (prefValue <= 0 || prefValue >= 100000) ? 0 : uint32_t(prefValue);
@ -529,7 +529,7 @@ LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */)
} }
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_heap_growth"); matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_heap_growth");
if (memPrefName == matchName || (!rts && index == 11)) { if (memPrefName == matchName || (!rts && index == 10)) {
bool prefValue = GetWorkerPref(matchName, false); bool prefValue = GetWorkerPref(matchName, false);
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_HEAP_GROWTH, UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_HEAP_GROWTH,
prefValue ? 0 : 1); prefValue ? 0 : 1);
@ -537,7 +537,7 @@ LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */)
} }
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_mark_slice"); matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_mark_slice");
if (memPrefName == matchName || (!rts && index == 12)) { if (memPrefName == matchName || (!rts && index == 11)) {
bool prefValue = GetWorkerPref(matchName, false); bool prefValue = GetWorkerPref(matchName, false);
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_MARK_SLICE, UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_MARK_SLICE,
prefValue ? 0 : 1); prefValue ? 0 : 1);

Просмотреть файл

@ -9,6 +9,7 @@ onmessage = function(event) {
rtnObj.size = file.size; rtnObj.size = file.size;
rtnObj.type = file.type; rtnObj.type = file.type;
rtnObj.name = file.name; rtnObj.name = file.name;
rtnObj.path = file.path;
rtnObj.lastModifiedDate = file.lastModifiedDate; rtnObj.lastModifiedDate = file.lastModifiedDate;
rtnObj.mozFullPath = file.mozFullPath; rtnObj.mozFullPath = file.mozFullPath;

Просмотреть файл

@ -69,6 +69,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=123456
is(event.data.size, expectedSize, "size proproperty accessed from worker is not the same as on main thread."); is(event.data.size, expectedSize, "size proproperty accessed from worker is not the same as on main thread.");
is(event.data.type, expectedType, "type proproperty accessed from worker is incorrect."); is(event.data.type, expectedType, "type proproperty accessed from worker is incorrect.");
is(event.data.name, file.name, "name proproperty accessed from worker is incorrect."); is(event.data.name, file.name, "name proproperty accessed from worker is incorrect.");
is(event.data.path, file.path, "path proproperty accessed from worker is incorrect.");
is(event.data.lastModifiedDate.toString(), file.lastModifiedDate.toString(), "lastModifiedDate proproperty accessed from worker is incorrect."); is(event.data.lastModifiedDate.toString(), file.lastModifiedDate.toString(), "lastModifiedDate proproperty accessed from worker is incorrect.");
is(event.data.mozFullPath, file.mozFullPath, "mozFullPath proproperty accessed from worker is not the same as on main thread."); is(event.data.mozFullPath, file.mozFullPath, "mozFullPath proproperty accessed from worker is not the same as on main thread.");
finish(); finish();

Просмотреть файл

@ -256,7 +256,8 @@ ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, Texture
TemporaryRef<BufferTextureClient> TemporaryRef<BufferTextureClient>
ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat) ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat)
{ {
return CompositableClient::CreateBufferTextureClient(aFormat, mTextureFlags); return CompositableClient::CreateBufferTextureClient(aFormat,
mTextureFlags | TEXTURE_FLAGS_DEFAULT);
} }
void void

Просмотреть файл

@ -4383,7 +4383,36 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
} }
} }
#ifdef PR_LOGGING
PRLogModuleInfo *log = (mStyle.systemFont ?
gfxPlatform::GetLog(eGfxLog_textrunui) :
gfxPlatform::GetLog(eGfxLog_textrun));
#endif
if (sizeof(T) == sizeof(uint8_t) && !transformedString) { if (sizeof(T) == sizeof(uint8_t) && !transformedString) {
#ifdef PR_LOGGING
if (MOZ_UNLIKELY(log)) {
nsAutoCString lang;
mStyle.language->ToUTF8String(lang);
nsAutoCString str((const char*)aString, aLength);
PR_LOG(log, PR_LOG_WARNING,\
("(%s) fontgroup: [%s] lang: %s script: %d len %d "
"weight: %d width: %d style: %s size: %6.2f %d-byte "
"TEXTRUN [%s] ENDTEXTRUN\n",
(mStyle.systemFont ? "textrunui" : "textrun"),
NS_ConvertUTF16toUTF8(mFamilies).get(),
lang.get(), MOZ_SCRIPT_LATIN, aLength,
uint32_t(mStyle.weight), uint32_t(mStyle.stretch),
(mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" :
(mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" :
"normal")),
mStyle.size,
sizeof(T),
str.get()));
}
#endif
// the text is still purely 8-bit; bypass the script-run itemizer // the text is still purely 8-bit; bypass the script-run itemizer
// and treat it as a single Latin run // and treat it as a single Latin run
InitScriptRun(aContext, aTextRun, aString, InitScriptRun(aContext, aTextRun, aString,
@ -4402,12 +4431,6 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
// the font matching process below // the font matching process below
gfxScriptItemizer scriptRuns(textPtr, aLength); gfxScriptItemizer scriptRuns(textPtr, aLength);
#ifdef PR_LOGGING
PRLogModuleInfo *log = (mStyle.systemFont ?
gfxPlatform::GetLog(eGfxLog_textrunui) :
gfxPlatform::GetLog(eGfxLog_textrun));
#endif
uint32_t runStart = 0, runLimit = aLength; uint32_t runStart = 0, runLimit = aLength;
int32_t runScript = MOZ_SCRIPT_LATIN; int32_t runScript = MOZ_SCRIPT_LATIN;
while (scriptRuns.Next(runStart, runLimit, runScript)) { while (scriptRuns.Next(runStart, runLimit, runScript)) {
@ -4419,7 +4442,7 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
uint32_t runLen = runLimit - runStart; uint32_t runLen = runLimit - runStart;
PR_LOG(log, PR_LOG_WARNING,\ PR_LOG(log, PR_LOG_WARNING,\
("(%s) fontgroup: [%s] lang: %s script: %d len %d " ("(%s) fontgroup: [%s] lang: %s script: %d len %d "
"weight: %d width: %d style: %s " "weight: %d width: %d style: %s size: %6.2f %d-byte "
"TEXTRUN [%s] ENDTEXTRUN\n", "TEXTRUN [%s] ENDTEXTRUN\n",
(mStyle.systemFont ? "textrunui" : "textrun"), (mStyle.systemFont ? "textrunui" : "textrun"),
NS_ConvertUTF16toUTF8(mFamilies).get(), NS_ConvertUTF16toUTF8(mFamilies).get(),
@ -4428,6 +4451,8 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
(mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" : (mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" :
(mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" : (mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" :
"normal")), "normal")),
mStyle.size,
sizeof(T),
NS_ConvertUTF16toUTF8(textPtr + runStart, runLen).get())); NS_ConvertUTF16toUTF8(textPtr + runStart, runLen).get()));
} }
#endif #endif

Просмотреть файл

@ -39,9 +39,9 @@ class JavaScriptParent
JS::MutableHandle<JSPropertyDescriptor> desc, unsigned flags); JS::MutableHandle<JSPropertyDescriptor> desc, unsigned flags);
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc); JS::MutableHandle<JSPropertyDescriptor> desc);
bool getOwnPropertyNames(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props); bool getOwnPropertyNames(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp); bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
bool enumerate(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props); bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
// Derived proxy traps. Implementing these is useful for perfomance. // Derived proxy traps. Implementing these is useful for perfomance.
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp); bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
@ -50,7 +50,7 @@ class JavaScriptParent
JS::HandleId id, JS::MutableHandleValue vp); JS::HandleId id, JS::MutableHandleValue vp);
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver, bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, bool strict, JS::MutableHandleValue vp); JS::HandleId id, bool strict, JS::MutableHandleValue vp);
bool keys(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props); bool keys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
// We use "iterate" provided by the base class here. // We use "iterate" provided by the base class here.
// SpiderMonkey Extensions. // SpiderMonkey Extensions.
@ -82,7 +82,8 @@ class JavaScriptParent
private: private:
bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp); bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp);
bool getPropertyNames(JSContext *cx, JS::HandleObject proxy, uint32_t flags, js::AutoIdVector &props); bool getPropertyNames(JSContext *cx, JS::HandleObject proxy, uint32_t flags,
JS::AutoIdVector &props);
ObjectId idOf(JSObject *obj); ObjectId idOf(JSObject *obj);
// Catastrophic IPC failure. // Catastrophic IPC failure.

116
js/src/NamespaceImports.h Normal file
Просмотреть файл

@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/. */
// This file imports some common JS:: names into the js namespace so we can
// make unqualified references to them.
#ifndef NamespaceImports_h
#define NamespaceImports_h
// These includes are needed these for some typedefs (e.g. HandleValue) and
// functions (e.g. NullValue())...
#include "js/CallNonGenericMethod.h"
#include "js/TypeDecls.h"
#include "js/Value.h"
// ... but we do forward declarations of the structs and classes not pulled in
// by the headers included above.
namespace JS {
class Latin1CharsZ;
class StableCharPtr;
class TwoByteChars;
class AutoFunctionVector;
class AutoIdVector;
class AutoObjectVector;
class AutoScriptVector;
class AutoValueVector;
class AutoIdArray;
class AutoGCRooter;
class AutoArrayRooter;
template <typename T> class AutoVectorRooter;
template<typename K, typename V> class AutoHashMapRooter;
template<typename T> class AutoHashSetRooter;
}
// Do the importing.
namespace js {
using JS::Value;
using JS::BooleanValue;
using JS::DoubleValue;
using JS::Int32Value;
using JS::IsPoisonedValue;
using JS::MagicValue;
using JS::NullValue;
using JS::NumberValue;
using JS::ObjectOrNullValue;
using JS::ObjectValue;
using JS::PrivateUint32Value;
using JS::PrivateValue;
using JS::StringValue;
using JS::UndefinedValue;
using JS::IsPoisonedPtr;
using JS::Latin1CharsZ;
using JS::StableCharPtr;
using JS::TwoByteChars;
using JS::AutoFunctionVector;
using JS::AutoIdVector;
using JS::AutoObjectVector;
using JS::AutoScriptVector;
using JS::AutoValueVector;
using JS::AutoIdArray;
using JS::AutoGCRooter;
using JS::AutoArrayRooter;
using JS::AutoHashMapRooter;
using JS::AutoHashSetRooter;
using JS::AutoVectorRooter;
using JS::CallArgs;
using JS::CallNonGenericMethod;
using JS::CallReceiver;
using JS::CompileOptions;
using JS::IsAcceptableThis;
using JS::NativeImpl;
using JS::Rooted;
using JS::RootedFunction;
using JS::RootedId;
using JS::RootedObject;
using JS::RootedScript;
using JS::RootedString;
using JS::RootedValue;
using JS::Handle;
using JS::HandleFunction;
using JS::HandleId;
using JS::HandleObject;
using JS::HandleScript;
using JS::HandleString;
using JS::HandleValue;
using JS::MutableHandle;
using JS::MutableHandleFunction;
using JS::MutableHandleId;
using JS::MutableHandleObject;
using JS::MutableHandleScript;
using JS::MutableHandleString;
using JS::MutableHandleValue;
using JS::Zone;
} /* namespace js */
#endif /* NamespaceImports_h */

Просмотреть файл

@ -223,7 +223,8 @@ if test "$GNU_CC"; then
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections" CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
fi fi
CXXFLAGS="$CXXFLAGS -fno-exceptions" CFLAGS="$CFLAGS -fno-math-errno"
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
fi fi
dnl ======================================================== dnl ========================================================

Просмотреть файл

@ -7,7 +7,6 @@
#ifndef builtin_BinaryData_h #ifndef builtin_BinaryData_h
#define builtin_BinaryData_h #define builtin_BinaryData_h
#include "jsapi.h"
#include "jsobj.h" #include "jsobj.h"
#include "builtin/TypeRepresentation.h" #include "builtin/TypeRepresentation.h"

Просмотреть файл

@ -7,8 +7,8 @@
#ifndef builtin_Eval_h #ifndef builtin_Eval_h
#define builtin_Eval_h #define builtin_Eval_h
#include "jsapi.h"
#include "jsbytecode.h" #include "jsbytecode.h"
#include "NamespaceImports.h"
namespace js { namespace js {

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef builtin_Intl_h #ifndef builtin_Intl_h
#define builtin_Intl_h #define builtin_Intl_h
#include "jsapi.h" #include "NamespaceImports.h"
#include "js/RootingAPI.h" #include "js/RootingAPI.h"

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef builtin_TestingFunctions_h #ifndef builtin_TestingFunctions_h
#define builtin_TestingFunctions_h #define builtin_TestingFunctions_h
#include "jsapi.h" #include "NamespaceImports.h"
namespace js { namespace js {
@ -15,10 +15,10 @@ bool
DefineTestingFunctions(JSContext *cx, HandleObject obj); DefineTestingFunctions(JSContext *cx, HandleObject obj);
bool bool
testingFunc_inParallelSection(JSContext *cx, unsigned argc, jsval *vp); testingFunc_inParallelSection(JSContext *cx, unsigned argc, Value *vp);
bool bool
testingFunc_bailout(JSContext *cx, unsigned argc, jsval *vp); testingFunc_bailout(JSContext *cx, unsigned argc, Value *vp);
} /* namespace js */ } /* namespace js */

Просмотреть файл

@ -232,7 +232,7 @@ changequote(,)
MOZJS_MAJOR_VERSION=`echo $MOZILLA_VERSION | sed "s|\(^[0-9]*\)\.[0-9]*.*|\1|"` MOZJS_MAJOR_VERSION=`echo $MOZILLA_VERSION | sed "s|\(^[0-9]*\)\.[0-9]*.*|\1|"`
MOZJS_MINOR_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.\([0-9]*\).*|\1|"` MOZJS_MINOR_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.\([0-9]*\).*|\1|"`
MOZJS_PATCH_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9]*[^0-9]*||"` MOZJS_PATCH_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9]*[^0-9]*||"`
IS_ALPHA=`echo $MOZILLA_VERSION | grep [ab]` IS_ALPHA=`echo $MOZILLA_VERSION | grep '[ab]'`
dnl XXX in a temporary bid to avoid developer anger at renaming files dnl XXX in a temporary bid to avoid developer anger at renaming files
dnl XXX before "js" symlinks exist, don't change names. dnl XXX before "js" symlinks exist, don't change names.

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef ds_IdValuePair_h #ifndef ds_IdValuePair_h
#define ds_IdValuePair_h #define ds_IdValuePair_h
#include "jsapi.h" #include "NamespaceImports.h"
namespace js { namespace js {

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef frontend_BytecodeCompiler_h #ifndef frontend_BytecodeCompiler_h
#define frontend_BytecodeCompiler_h #define frontend_BytecodeCompiler_h
#include "jsapi.h" #include "NamespaceImports.h"
class JSLinearString; class JSLinearString;

Просмотреть файл

@ -317,6 +317,12 @@ struct CompileError {
} }
~CompileError(); ~CompileError();
void throwError(JSContext *cx); void throwError(JSContext *cx);
private:
// CompileError owns raw allocated memory, so disable assignment and copying
// for safety.
void operator=(const CompileError &) MOZ_DELETE;
CompileError(const CompileError &) MOZ_DELETE;
}; };
// Ideally, tokenizing would be entirely independent of context. But the // Ideally, tokenizing would be entirely independent of context. But the

Просмотреть файл

@ -8,6 +8,7 @@
#define gc_Barrier_h #define gc_Barrier_h
#include "jsapi.h" #include "jsapi.h"
#include "NamespaceImports.h"
#include "gc/Heap.h" #include "gc/Heap.h"
#include "js/HashTable.h" #include "js/HashTable.h"

Просмотреть файл

@ -10,10 +10,11 @@
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/PodOperations.h" #include "mozilla/PodOperations.h"
#include "jsapi.h" #include "jsalloc.h"
#include "jspubtd.h" #include "jspubtd.h"
#include "js/GCAPI.h" #include "js/GCAPI.h"
#include "js/Vector.h"
struct JSCompartment; struct JSCompartment;

Просмотреть файл

@ -21,6 +21,7 @@
// actually run.) // actually run.)
#include "jsapi.h" #include "jsapi.h"
#include "NamespaceImports.h"
void breakpoint(); void breakpoint();

Просмотреть файл

@ -5223,7 +5223,7 @@ StackDecrementForCall(MacroAssembler &masm, const VectorT &argTypes, unsigned ex
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * STACK_SLOT_SIZE + static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * STACK_SLOT_SIZE +
NonVolatileRegs.fpus().size() * sizeof(double); NonVolatileRegs.fpus().size() * sizeof(double);
#ifndef JS_CPU_ARM
static bool static bool
GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFunc) GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFunc)
{ {
@ -5237,72 +5237,85 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
// PushRegsInMask(NonVolatileRegs). // PushRegsInMask(NonVolatileRegs).
masm.setFramePushed(0); masm.setFramePushed(0);
masm.PushRegsInMask(NonVolatileRegs); masm.PushRegsInMask(NonVolatileRegs);
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
// Remember the stack pointer in the current AsmJSActivation. This will be // Remember the stack pointer in the current AsmJSActivation. This will be
// used by error exit paths to set the stack pointer back to what it was // used by error exit paths to set the stack pointer back to what it was
// right after the (C++) caller's non-volatile registers were saved so that // right after the (C++) caller's non-volatile registers were saved so that
// they can be restored. // they can be restored.
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
Register activation = ABIArgGenerator::NonArgReturnVolatileReg0; Register activation = ABIArgGenerator::NonArgReturnVolatileReg0;
LoadAsmJSActivationIntoRegister(masm, activation); LoadAsmJSActivationIntoRegister(masm, activation);
masm.movePtr(StackPointer, Operand(activation, AsmJSActivation::offsetOfErrorRejoinSP())); masm.storePtr(StackPointer, Address(activation, AsmJSActivation::offsetOfErrorRejoinSP()));
#if defined(JS_CPU_X64) // ARM has a globally-pinned GlobalReg (x64 uses RIP-relative addressing,
// Install the heap pointer into the globally-pinned HeapReg. The heap // x86 uses immediates in effective addresses) and NaN register (used as
// pointer is stored in the global data section and is patched at dynamic // part of the out-of-bounds handling in heap loads/stores).
// link time. #if defined(JS_CPU_ARM)
CodeOffsetLabel label = masm.loadRipRelativeInt64(HeapReg); masm.movePtr(IntArgReg1, GlobalReg);
m.addGlobalAccess(AsmJSGlobalAccess(label.offset(), m.module().heapOffset())); masm.ma_vimm(js_NaN, NANReg);
#endif #endif
// ARM and x64 have a globally-pinned HeapReg (x86 uses immediates in
// effective addresses).
#if defined(JS_CPU_X64) || defined(JS_CPU_ARM)
masm.loadPtr(Address(IntArgReg1, m.module().heapOffset()), HeapReg);
#endif
// Get 'argv' into a non-arg register and save it on the stack.
Register argv = ABIArgGenerator::NonArgReturnVolatileReg0; Register argv = ABIArgGenerator::NonArgReturnVolatileReg0;
Register scratch = ABIArgGenerator::NonArgReturnVolatileReg1; Register scratch = ABIArgGenerator::NonArgReturnVolatileReg1;
#if defined(JS_CPU_X86) #if defined(JS_CPU_X86)
masm.movl(Operand(StackPointer, NativeFrameSize + masm.framePushed()), argv); masm.loadPtr(Address(StackPointer, NativeFrameSize + masm.framePushed()), argv);
#elif defined(JS_CPU_X64) #else
masm.movq(IntArgReg0, argv); masm.movePtr(IntArgReg0, argv);
masm.Push(argv);
#endif #endif
masm.Push(argv);
// Bump the stack for the call. // Bump the stack for the call.
const ModuleCompiler::Func &func = *m.lookupFunction(exportedFunc.name()); const ModuleCompiler::Func &func = *m.lookupFunction(exportedFunc.name());
unsigned stackDec = StackDecrementForCall(masm, func.sig().args()); unsigned stackDec = StackDecrementForCall(masm, func.sig().args());
masm.reserveStack(stackDec); masm.reserveStack(stackDec);
// Copy parameters out of argv and into the registers/stack-slots specified by
// the system ABI.
for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) { for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
Operand src(argv, iter.index() * sizeof(uint64_t)); unsigned argOffset = iter.index() * sizeof(uint64_t);
Address src(argv, argOffset);
switch (iter->kind()) { switch (iter->kind()) {
case ABIArg::GPR: case ABIArg::GPR:
masm.load32(src, iter->gpr()); masm.load32(src, iter->gpr());
break; break;
case ABIArg::FPU: case ABIArg::FPU:
#if defined(JS_CPU_ARM) and !defined(JS_CPU_ARM_HARDFP)
masm.ma_dataTransferN(IsLoad, 64, true, argv, Imm32(argOffset),
Register::FromCode(iter->fpu().code()*2));
#else
masm.loadDouble(src, iter->fpu()); masm.loadDouble(src, iter->fpu());
#endif
break; break;
case ABIArg::Stack: case ABIArg::Stack:
if (iter.mirType() == MIRType_Int32) { if (iter.mirType() == MIRType_Int32) {
masm.load32(src, scratch); masm.load32(src, scratch);
masm.storePtr(scratch, Operand(StackPointer, iter->offsetFromArgBase())); masm.storePtr(scratch, Address(StackPointer, iter->offsetFromArgBase()));
} else { } else {
JS_ASSERT(iter.mirType() == MIRType_Double); JS_ASSERT(iter.mirType() == MIRType_Double);
masm.loadDouble(src, ScratchFloatReg); masm.loadDouble(src, ScratchFloatReg);
masm.storeDouble(ScratchFloatReg, Operand(StackPointer, iter->offsetFromArgBase())); masm.storeDouble(ScratchFloatReg, Address(StackPointer, iter->offsetFromArgBase()));
} }
break; break;
} }
} }
// Call into the real function.
AssertStackAlignment(masm); AssertStackAlignment(masm);
masm.call(func.code()); masm.call(func.code());
// Pop the stack and recover the original 'argv' argument passed to the
// trampoline (which was pushed on the stack).
masm.freeStack(stackDec); masm.freeStack(stackDec);
#if defined(JS_CPU_X86)
masm.movl(Operand(StackPointer, NativeFrameSize + masm.framePushed()), argv);
#elif defined(JS_CPU_X64)
masm.Pop(argv); masm.Pop(argv);
#endif
// Store return value in argv[0] // Store the return value in argv[0]
switch (func.sig().retType().which()) { switch (func.sig().retType().which()) {
case RetType::Void: case RetType::Void:
break; break;
@ -5310,119 +5323,7 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0)); masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0));
break; break;
case RetType::Double: case RetType::Double:
masm.canonicalizeDouble(ReturnFloatReg); #if defined(JS_CPU_ARM) and !defined(JS_CPU_ARM_HARDFP)
masm.storeDouble(ReturnFloatReg, Address(argv, 0));
break;
}
// Restore clobbered registers.
masm.PopRegsInMask(NonVolatileRegs);
JS_ASSERT(masm.framePushed() == 0);
masm.move32(Imm32(true), ReturnReg);
masm.ret();
return true;
}
#else
static bool
GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFunc)
{
const ModuleCompiler::Func &func = *m.lookupFunction(exportedFunc.name());
MacroAssembler &masm = m.masm();
// In constrast to the X64 system ABI, the Ion convention is that all
// registers are clobbered by calls. Thus, we must save the caller's
// non-volatile registers.
//
// NB: GenerateExits assumes that masm.framePushed() == 0 before
// PushRegsInMask(NonVolatileRegs).
masm.setFramePushed(0);
masm.PushRegsInMask(NonVolatileRegs);
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
JS_ASSERT(masm.framePushed() % 8 == 0);
// Remember the stack pointer in the current AsmJSActivation. This will be
// used by error exit paths to set the stack pointer back to what it was
// right after the (C++) caller's non-volatile registers were saved so that
// they can be restored.
LoadAsmJSActivationIntoRegister(masm, r9);
masm.ma_str(StackPointer, Address(r9, AsmJSActivation::offsetOfErrorRejoinSP()));
// masm.storeErrorRejoinSp();
// Move the parameters into non-argument registers since we are about to
// clobber these registers with the contents of argv.
Register argv = r9;
masm.movePtr(IntArgReg1, GlobalReg); // globalData
masm.movePtr(IntArgReg0, argv); // argv
masm.ma_ldr(Operand(GlobalReg, Imm32(m.module().heapOffset())), HeapReg);
// Remember argv so that we can load argv[0] after the call.
JS_ASSERT(masm.framePushed() % 8 == 0);
masm.Push(argv);
JS_ASSERT(masm.framePushed() % 8 == 4);
// Determine how many stack slots we need to hold arguments that don't fit
// in registers.
unsigned numStackArgs = 0;
for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
if (iter->kind() == ABIArg::Stack)
numStackArgs++;
}
// Before calling, we must ensure sp % 16 == 0. Since (sp % 16) = 8 on
// entry, we need to push 8 (mod 16) bytes.
//JS_ASSERT(AlignmentAtPrologue == 8);
JS_ASSERT(masm.framePushed() % 8 == 4);
unsigned stackDec = numStackArgs * sizeof(double) + (masm.framePushed() >> 2) % 2 * sizeof(uint32_t);
masm.reserveStack(stackDec);
//JS_ASSERT(masm.framePushed() % 8 == 0);
if(getenv("GDB_BREAK")) {
masm.breakpoint(js::jit::Assembler::Always);
}
// Copy parameters out of argv into the registers/stack-slots specified by
// the system ABI.
for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
unsigned argOffset = iter.index() * sizeof(uint64_t);
switch (iter->kind()) {
case ABIArg::GPR:
masm.ma_ldr(Operand(argv, argOffset), iter->gpr());
break;
case ABIArg::FPU:
#if defined(JS_CPU_ARM_HARDFP)
masm.ma_vldr(Operand(argv, argOffset), iter->fpu());
#else
// The ABI is expecting a double value in a pair of gpr's. Figure out which gprs it is,
// and use them explicityl.
masm.ma_dataTransferN(IsLoad, 64, true, argv, Imm32(argOffset), Register::FromCode(iter->fpu().code()*2));
#endif
break;
case ABIArg::Stack:
if (iter.mirType() == MIRType_Int32) {
masm.memMove32(Address(argv, argOffset), Address(StackPointer, iter->offsetFromArgBase()));
} else {
masm.memMove64(Address(argv, argOffset), Address(StackPointer, iter->offsetFromArgBase()));
}
break;
}
}
masm.ma_vimm(js_NaN, NANReg);
masm.call(func.code());
// Recover argv.
masm.freeStack(stackDec);
masm.Pop(argv);
// Store the result in argv[0].
switch (func.sig().retType().which()) {
case RetType::Void:
break;
case RetType::Signed:
masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0));
break;
case RetType::Double:
#ifndef JS_CPU_ARM_HARDFP
masm.ma_vxfer(r0, r1, d0); masm.ma_vxfer(r0, r1, d0);
#endif #endif
masm.canonicalizeDouble(ReturnFloatReg); masm.canonicalizeDouble(ReturnFloatReg);
@ -5430,13 +5331,15 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
break; break;
} }
// Restore clobbered non-volatile registers of the caller.
masm.PopRegsInMask(NonVolatileRegs); masm.PopRegsInMask(NonVolatileRegs);
masm.ma_mov(Imm32(true), ReturnReg); JS_ASSERT(masm.framePushed() == 0);
masm.move32(Imm32(true), ReturnReg);
masm.abiret(); masm.abiret();
return true; return true;
} }
#endif
static inline bool static inline bool
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex, TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
@ -6029,16 +5932,9 @@ GenerateStackOverflowExit(ModuleCompiler &m, Label *throwLabel)
LoadAsmJSActivationIntoRegister(masm, eax); LoadAsmJSActivationIntoRegister(masm, eax);
LoadJSContextFromActivation(masm, eax, eax); LoadJSContextFromActivation(masm, eax, eax);
masm.storePtr(eax, Address(StackPointer, 0)); masm.storePtr(eax, Address(StackPointer, 0));
#elif defined(JS_CPU_X64)
LoadAsmJSActivationIntoRegister(masm, IntArgReg0);
LoadJSContextFromActivation(masm, IntArgReg0, IntArgReg0);
#else #else
// on ARM, we should always be aligned, just do the context manipulation
// and make the call.
LoadAsmJSActivationIntoRegister(masm, IntArgReg0); LoadAsmJSActivationIntoRegister(masm, IntArgReg0);
LoadJSContextFromActivation(masm, IntArgReg0, IntArgReg0); LoadJSContextFromActivation(masm, IntArgReg0, IntArgReg0);
#endif #endif
void (*pf)(JSContext*) = js_ReportOverRecursed; void (*pf)(JSContext*) = js_ReportOverRecursed;
masm.call(ImmWord(JS_FUNC_TO_DATA_PTR(void*, pf))); masm.call(ImmWord(JS_FUNC_TO_DATA_PTR(void*, pf)));

Просмотреть файл

@ -7,7 +7,9 @@
#ifndef jit_AsmJS_h #ifndef jit_AsmJS_h
#define jit_AsmJS_h #define jit_AsmJS_h
#include "jsapi.h" #include <stddef.h>
#include "js/TypeDecls.h"
namespace js { namespace js {

Просмотреть файл

@ -362,13 +362,8 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
JitActivation jitActivation(cx, /* firstFrameIsConstructing = */ false, /* active */ false); JitActivation jitActivation(cx, /* firstFrameIsConstructing = */ false, /* active */ false);
// Call the per-exported-function trampoline created by GenerateEntry. // Call the per-exported-function trampoline created by GenerateEntry.
#ifdef JS_CPU_ARM
if (!module.entryTrampoline(func)(coercedArgs.begin(), module.globalData())) if (!module.entryTrampoline(func)(coercedArgs.begin(), module.globalData()))
return false; return false;
#else
if (!module.entryTrampoline(func)(coercedArgs.begin()))
return false;
#endif
} }
switch (func.returnType()) { switch (func.returnType()) {

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef jit_AsmJSLink_h #ifndef jit_AsmJSLink_h
#define jit_AsmJSLink_h #define jit_AsmJSLink_h
#include "jsapi.h" #include "NamespaceImports.h"
namespace js { namespace js {

Просмотреть файл

@ -183,11 +183,7 @@ class AsmJSModule
ionCodeOffset_ = off; ionCodeOffset_ = off;
} }
}; };
#ifdef JS_CPU_ARM
typedef int32_t (*CodePtr)(uint64_t *args, uint8_t *global); typedef int32_t (*CodePtr)(uint64_t *args, uint8_t *global);
#else
typedef int32_t (*CodePtr)(uint64_t *args);
#endif
typedef Vector<AsmJSCoercion, 0, SystemAllocPolicy> ArgCoercionVector; typedef Vector<AsmJSCoercion, 0, SystemAllocPolicy> ArgCoercionVector;

Просмотреть файл

@ -9,7 +9,7 @@
#ifdef DEBUG #ifdef DEBUG
#include "jsapi.h" #include "NamespaceImports.h"
#include "js/RootingAPI.h" #include "js/RootingAPI.h"

Просмотреть файл

@ -1786,6 +1786,9 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
if (!emitCallToUncompiledScriptPar(call, calleereg)) if (!emitCallToUncompiledScriptPar(call, calleereg))
return false; return false;
break; break;
default:
MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
masm.bind(&end); masm.bind(&end);
@ -1911,6 +1914,9 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
if (!emitCallToUncompiledScriptPar(call, calleereg)) if (!emitCallToUncompiledScriptPar(call, calleereg))
return false; return false;
break; break;
default:
MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
masm.bind(&end); masm.bind(&end);
@ -4800,7 +4806,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool)
masm.jump(ool->rejoin()); masm.jump(ool->rejoin());
return true; return true;
case ParallelExecution: case ParallelExecution: {
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// If the problem is that we do not have sufficient capacity, // If the problem is that we do not have sufficient capacity,
// try to reallocate the elements array and then branch back // try to reallocate the elements array and then branch back
@ -4855,6 +4861,10 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool)
return false; return false;
masm.jump(bail1->entry()); masm.jump(bail1->entry());
return true; return true;
}
default:
MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
JS_ASSERT(false); JS_ASSERT(false);

Просмотреть файл

@ -30,11 +30,15 @@ CountArgSlots(JSScript *script, JSFunction *fun)
enum ExecutionMode { enum ExecutionMode {
// Normal JavaScript execution // Normal JavaScript execution
SequentialExecution = 0, SequentialExecution,
// JavaScript code to be executed in parallel worker threads, // JavaScript code to be executed in parallel worker threads,
// e.g. by ParallelArray // e.g. by ParallelArray
ParallelExecution ParallelExecution,
// MIR analysis performed when invoking 'new' on a script, to determine
// definite properties
DefinitePropertiesAnalysis
}; };
// Not as part of the enum so we don't get warnings about unhandled enum // Not as part of the enum so we don't get warnings about unhandled enum

Просмотреть файл

@ -22,6 +22,7 @@ HasIonScript(JSScript *script, ExecutionMode cmode)
switch (cmode) { switch (cmode) {
case SequentialExecution: return script->hasIonScript(); case SequentialExecution: return script->hasIonScript();
case ParallelExecution: return script->hasParallelIonScript(); case ParallelExecution: return script->hasParallelIonScript();
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
@ -32,6 +33,7 @@ GetIonScript(JSScript *script, ExecutionMode cmode)
switch (cmode) { switch (cmode) {
case SequentialExecution: return script->maybeIonScript(); case SequentialExecution: return script->maybeIonScript();
case ParallelExecution: return script->maybeParallelIonScript(); case ParallelExecution: return script->maybeParallelIonScript();
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
@ -42,6 +44,7 @@ SetIonScript(JSScript *script, ExecutionMode cmode, IonScript *ionScript)
switch (cmode) { switch (cmode) {
case SequentialExecution: script->setIonScript(ionScript); return; case SequentialExecution: script->setIonScript(ionScript); return;
case ParallelExecution: script->setParallelIonScript(ionScript); return; case ParallelExecution: script->setParallelIonScript(ionScript); return;
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
@ -52,6 +55,7 @@ OffsetOfIonInJSScript(ExecutionMode cmode)
switch (cmode) { switch (cmode) {
case SequentialExecution: return JSScript::offsetOfIonScript(); case SequentialExecution: return JSScript::offsetOfIonScript();
case ParallelExecution: return JSScript::offsetOfParallelIonScript(); case ParallelExecution: return JSScript::offsetOfParallelIonScript();
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
@ -62,6 +66,8 @@ CanIonCompile(JSScript *script, ExecutionMode cmode)
switch (cmode) { switch (cmode) {
case SequentialExecution: return script->canIonCompile(); case SequentialExecution: return script->canIonCompile();
case ParallelExecution: return script->canParallelIonCompile(); case ParallelExecution: return script->canParallelIonCompile();
case DefinitePropertiesAnalysis: return true;
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
return false; return false;
@ -79,6 +85,7 @@ CompilingOffThread(JSScript *script, ExecutionMode cmode)
switch (cmode) { switch (cmode) {
case SequentialExecution: return script->isIonCompilingOffThread(); case SequentialExecution: return script->isIonCompilingOffThread();
case ParallelExecution: return script->isParallelIonCompilingOffThread(); case ParallelExecution: return script->isParallelIonCompilingOffThread();
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
@ -89,6 +96,7 @@ CompilingOffThread(HandleScript script, ExecutionMode cmode)
switch (cmode) { switch (cmode) {
case SequentialExecution: return script->isIonCompilingOffThread(); case SequentialExecution: return script->isIonCompilingOffThread();
case ParallelExecution: return script->isParallelIonCompilingOffThread(); case ParallelExecution: return script->isParallelIonCompilingOffThread();
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
@ -99,6 +107,7 @@ CompilerOutputKind(ExecutionMode cmode)
switch (cmode) { switch (cmode) {
case SequentialExecution: return types::CompilerOutput::Ion; case SequentialExecution: return types::CompilerOutput::Ion;
case ParallelExecution: return types::CompilerOutput::ParallelIon; case ParallelExecution: return types::CompilerOutput::ParallelIon;
default:;
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }

Просмотреть файл

@ -2451,6 +2451,8 @@ jit::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetU
if (!scripts.append(script->parallelIonScript()->recompileInfo())) if (!scripts.append(script->parallelIonScript()->recompileInfo()))
return false; return false;
break; break;
default:
MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
Invalidate(cx, scripts, resetUses); Invalidate(cx, scripts, resetUses);
@ -2542,6 +2544,9 @@ jit::ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode)
script->setParallelIonScript(ION_DISABLED_SCRIPT); script->setParallelIonScript(ION_DISABLED_SCRIPT);
return; return;
default:
MOZ_ASSUME_UNREACHABLE("No such execution mode");
} }
MOZ_ASSUME_UNREACHABLE("No such execution mode"); MOZ_ASSUME_UNREACHABLE("No such execution mode");

Просмотреть файл

@ -8,14 +8,20 @@
#include "jsanalyze.h" #include "jsanalyze.h"
#include "jit/BaselineInspector.h"
#include "jit/Ion.h" #include "jit/Ion.h"
#include "jit/IonBuilder.h" #include "jit/IonBuilder.h"
#include "jit/LIR.h" #include "jit/LIR.h"
#include "jit/MIRGraph.h" #include "jit/MIRGraph.h"
#include "jsinferinlines.h"
#include "jsscriptinlines.h"
using namespace js; using namespace js;
using namespace js::jit; using namespace js::jit;
using mozilla::DebugOnly;
// A critical edge is an edge which is neither its successor's only predecessor // A critical edge is an edge which is neither its successor's only predecessor
// nor its predecessor's only successor. Critical edges must be split to // nor its predecessor's only successor. Critical edges must be split to
// prevent copy-insertion and code motion from affecting other edges. // prevent copy-insertion and code motion from affecting other edges.
@ -1605,3 +1611,263 @@ LinearSum::print(Sprinter &sp) const
else if (constant_ < 0) else if (constant_ < 0)
sp.printf("%d", constant_); sp.printf("%d", constant_);
} }
static bool
AnalyzePoppedThis(JSContext *cx, types::TypeObject *type,
MDefinition *thisValue, MInstruction *ins, bool definitelyExecuted,
HandleObject baseobj,
Vector<types::TypeNewScript::Initializer> *initializerList,
Vector<jsid> *accessedProperties,
bool *phandled)
{
// Determine the effect that a use of the |this| value when calling |new|
// on a script has on the properties definitely held by the new object.
if (ins->isCallSetProperty()) {
MCallSetProperty *setprop = ins->toCallSetProperty();
if (setprop->obj() != thisValue)
return true;
// Don't use GetAtomId here, we need to watch for SETPROP on
// integer properties and bail out. We can't mark the aggregate
// JSID_VOID type property as being in a definite slot.
RootedId id(cx, NameToId(setprop->name()));
if (types::IdToTypeId(id) != id ||
id == NameToId(cx->names().classPrototype) ||
id == NameToId(cx->names().proto) ||
id == NameToId(cx->names().constructor))
{
return true;
}
// Ignore assignments to properties that were already written to.
if (baseobj->nativeLookup(cx, id)) {
*phandled = true;
return true;
}
// Don't add definite properties for properties that were already
// read in the constructor.
for (size_t i = 0; i < accessedProperties->length(); i++) {
if ((*accessedProperties)[i] == id)
return true;
}
if (baseobj->slotSpan() >= (types::TYPE_FLAG_DEFINITE_MASK >> types::TYPE_FLAG_DEFINITE_SHIFT)) {
// Maximum number of definite properties added.
return true;
}
// Assignments to new properties must always execute.
if (!definitelyExecuted)
return true;
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, type, id)) {
// The prototype chain already contains a getter/setter for this
// property, or type information is too imprecise.
return true;
}
DebugOnly<unsigned> slotSpan = baseobj->slotSpan();
RootedValue value(cx, UndefinedValue());
if (!DefineNativeProperty(cx, baseobj, id, value, NULL, NULL,
JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE))
{
return false;
}
JS_ASSERT(baseobj->slotSpan() != slotSpan);
JS_ASSERT(!baseobj->inDictionaryMode());
Vector<MResumePoint *> callerResumePoints(cx);
MBasicBlock *block = ins->block();
for (MResumePoint *rp = block->callerResumePoint();
rp;
block = rp->block(), rp = block->callerResumePoint())
{
JSScript *script = rp->block()->info().script();
types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script());
if (!callerResumePoints.append(rp))
return false;
}
for (int i = callerResumePoints.length() - 1; i >= 0; i--) {
MResumePoint *rp = callerResumePoints[i];
JSScript *script = rp->block()->info().script();
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP_FRAME,
rp->pc() - script->code);
if (!initializerList->append(entry))
return false;
}
JSScript *script = ins->block()->info().script();
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP,
setprop->resumePoint()->pc() - script->code);
if (!initializerList->append(entry))
return false;
*phandled = true;
return true;
}
if (ins->isCallGetProperty()) {
MCallGetProperty *get = ins->toCallGetProperty();
/*
* Properties can be read from the 'this' object if the following hold:
*
* - The read is not on a getter along the prototype chain, which
* could cause 'this' to escape.
*
* - The accessed property is either already a definite property or
* is not later added as one. Since the definite properties are
* added to the object at the point of its creation, reading a
* definite property before it is assigned could incorrectly hit.
*/
RootedId id(cx, NameToId(get->name()));
if (types::IdToTypeId(id) != id)
return true;
if (!baseobj->nativeLookup(cx, id) && !accessedProperties->append(id.get()))
return false;
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, type, id)) {
// The |this| value can escape if any property reads it does go
// through a getter.
return true;
}
*phandled = true;
return true;
}
if (ins->isPostWriteBarrier()) {
*phandled = true;
return true;
}
return true;
}
static int
CmpInstructions(const void *a, const void *b)
{
return (*static_cast<MInstruction * const *>(a))->id() -
(*static_cast<MInstruction * const *>(b))->id();
}
bool
jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
types::TypeObject *type, HandleObject baseobj,
Vector<types::TypeNewScript::Initializer> *initializerList)
{
// When invoking 'new' on the specified script, try to find some properties
// which will definitely be added to the created object before it has a
// chance to escape and be accessed elsewhere.
if (!fun->nonLazyScript()->compileAndGo)
return true;
if (!fun->nonLazyScript()->ensureHasTypes(cx))
return false;
types::TypeScript::SetThis(cx, fun->nonLazyScript(), types::Type::ObjectType(type));
Vector<jsid> accessedProperties(cx);
LifoAlloc alloc(JSCompartment::ANALYSIS_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
TempAllocator temp(&alloc);
IonContext ictx(cx, &temp);
types::AutoEnterAnalysis enter(cx);
if (!fun->nonLazyScript()->ensureRanAnalysis(cx))
return false;
MIRGraph graph(&temp);
CompileInfo info(fun->nonLazyScript(), fun,
/* osrPc = */ NULL, /* constructing = */ false,
DefinitePropertiesAnalysis);
AutoTempAllocatorRooter root(cx, &temp);
BaselineInspector inspector(cx, fun->nonLazyScript());
IonBuilder builder(cx, &temp, &graph, &inspector, &info, /* baselineFrame = */ NULL);
if (!builder.build()) {
if (builder.abortReason() == AbortReason_Alloc)
return false;
return true;
}
if (!SplitCriticalEdges(graph))
return false;
if (!RenumberBlocks(graph))
return false;
if (!BuildDominatorTree(graph))
return false;
if (!EliminatePhis(&builder, graph, AggressiveObservability))
return false;
MDefinition *thisValue = graph.begin()->getSlot(info.thisSlot());
// Get a list of instructions using the |this| value in the order they
// appear in the graph.
Vector<MInstruction *> instructions(cx);
Vector<MDefinition *> useWorklist(cx);
for (MUseDefIterator uses(thisValue); uses; uses++) {
MDefinition *use = uses.def();
// Don't track |this| through assignments to phis.
if (!use->isInstruction())
return true;
if (!instructions.append(use->toInstruction()))
return false;
}
// Sort the instructions to visit in increasing order.
qsort(instructions.begin(), instructions.length(),
sizeof(MInstruction *), CmpInstructions);
// Find all exit blocks in the graph.
Vector<MBasicBlock *> exitBlocks(cx);
for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
if (!block->numSuccessors() && !exitBlocks.append(*block))
return false;
}
for (size_t i = 0; i < instructions.length(); i++) {
MInstruction *ins = instructions[i];
// Track whether the use of |this| is in unconditional code, i.e.
// the block dominates all graph exits.
bool definitelyExecuted = true;
for (size_t i = 0; i < exitBlocks.length(); i++) {
for (MBasicBlock *exit = exitBlocks[i];
exit != ins->block();
exit = exit->immediateDominator())
{
if (exit == exit->immediateDominator()) {
definitelyExecuted = false;
break;
}
}
}
bool handled = false;
if (!AnalyzePoppedThis(cx, type, thisValue, ins, definitelyExecuted,
baseobj, initializerList, &accessedProperties, &handled))
{
return false;
}
if (!handled)
return true;
}
return true;
}

Просмотреть файл

@ -124,6 +124,11 @@ class LinearSum
int32_t constant_; int32_t constant_;
}; };
bool
AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
types::TypeObject *type, HandleObject baseobj,
Vector<types::TypeNewScript::Initializer> *initializerList);
} // namespace jit } // namespace jit
} // namespace js } // namespace js

Просмотреть файл

@ -3929,16 +3929,21 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
return false; return false;
} }
// Caller must be... somewhat hot. // Caller must be... somewhat hot. Ignore use counts when inlining for
// the definite properties analysis, as the caller has not run yet.
uint32_t callerUses = script()->getUseCount(); uint32_t callerUses = script()->getUseCount();
if (callerUses < js_IonOptions.usesBeforeInlining()) { if (callerUses < js_IonOptions.usesBeforeInlining() &&
info().executionMode() != DefinitePropertiesAnalysis)
{
IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: caller is insufficiently hot.", IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: caller is insufficiently hot.",
targetScript->filename(), targetScript->lineno); targetScript->filename(), targetScript->lineno);
return false; return false;
} }
// Callee must be hot relative to the caller. // Callee must be hot relative to the caller.
if (targetScript->getUseCount() * js_IonOptions.inlineUseCountRatio < callerUses) { if (targetScript->getUseCount() * js_IonOptions.inlineUseCountRatio < callerUses &&
info().executionMode() != DefinitePropertiesAnalysis)
{
IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: callee is not hot.", IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: callee is not hot.",
targetScript->filename(), targetScript->lineno); targetScript->filename(), targetScript->lineno);
return false; return false;
@ -4803,7 +4808,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
// When this script isn't inlined, use MApplyArgs, // When this script isn't inlined, use MApplyArgs,
// to copy the arguments from the stack and call the function // to copy the arguments from the stack and call the function
if (inliningDepth_ == 0) { if (inliningDepth_ == 0 && info().executionMode() != DefinitePropertiesAnalysis) {
// Vp // Vp
MPassArg *passVp = current->pop()->toPassArg(); MPassArg *passVp = current->pop()->toPassArg();
@ -4841,7 +4846,9 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
// When inlining we have the arguments the function gets called with // When inlining we have the arguments the function gets called with
// and can optimize even more, by just calling the functions with the args. // and can optimize even more, by just calling the functions with the args.
JS_ASSERT(inliningDepth_ > 0); // We also try this path when doing the definite properties analysis, as we
// can inline the apply() target and don't care about the actual arguments
// that were passed in.
CallInfo callInfo(cx, false); CallInfo callInfo(cx, false);
@ -4853,8 +4860,10 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
// Arguments // Arguments
Vector<MDefinition *> args(cx); Vector<MDefinition *> args(cx);
if (!args.append(inlineCallInfo_->argv().begin(), inlineCallInfo_->argv().end())) if (inliningDepth_) {
return false; if (!args.append(inlineCallInfo_->argv().begin(), inlineCallInfo_->argv().end()))
return false;
}
callInfo.setArgs(&args); callInfo.setArgs(&args);
// This // This
@ -5570,6 +5579,7 @@ IonBuilder::jsop_initprop(HandlePropertyName name)
// forkjoin.cpp for more information. // forkjoin.cpp for more information.
switch (info().executionMode()) { switch (info().executionMode()) {
case SequentialExecution: case SequentialExecution:
case DefinitePropertiesAnalysis:
break; break;
case ParallelExecution: case ParallelExecution:
needsBarrier = false; needsBarrier = false;
@ -8019,11 +8029,22 @@ IonBuilder::jsop_getprop(HandlePropertyName name)
if (!getPropTryArgumentsLength(&emitted) || emitted) if (!getPropTryArgumentsLength(&emitted) || emitted)
return emitted; return emitted;
bool barrier = PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types);
// Try to hardcode known constants. // Try to hardcode known constants.
if (!getPropTryConstant(&emitted, id, types) || emitted) if (!getPropTryConstant(&emitted, id, types) || emitted)
return emitted; return emitted;
bool barrier = PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types); // Except when loading constants above, always use a call if we are doing
// the definite properties analysis and not actually emitting code, to
// simplify later analysis.
if (info().executionMode() == DefinitePropertiesAnalysis) {
MDefinition *obj = current->pop();
MCallGetProperty *call = MCallGetProperty::New(obj, name);
current->add(call);
current->push(call);
return resumeAfter(call);
}
// Try to emit loads from definite slots. // Try to emit loads from definite slots.
if (!getPropTryDefiniteSlot(&emitted, name, barrier, types) || emitted) if (!getPropTryDefiniteSlot(&emitted, name, barrier, types) || emitted)
@ -8370,6 +8391,15 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
RootedId id(cx, NameToId(name)); RootedId id(cx, NameToId(name));
bool emitted = false; bool emitted = false;
// Always use a call if we are doing the definite properties analysis and
// not actually emitting code, to simplify later analysis.
if (info().executionMode() == DefinitePropertiesAnalysis) {
MInstruction *ins = MCallSetProperty::New(obj, value, name, script()->strict);
current->add(ins);
current->push(value);
return resumeAfter(ins);
}
// Add post barrier if needed. // Add post barrier if needed.
if (NeedsPostBarrier(info(), value)) if (NeedsPostBarrier(info(), value))
current->add(MPostWriteBarrier::New(obj, value)); current->add(MPostWriteBarrier::New(obj, value));
@ -8759,6 +8789,15 @@ IonBuilder::jsop_this()
return true; return true;
} }
// If we are doing a definite properties analysis, we don't yet know the
// |this| type as its type object is being created right now. Instead of
// bailing out just push the |this| slot, as this code won't actually
// execute and it does not matter whether |this| is primitive.
if (info().executionMode() == DefinitePropertiesAnalysis) {
current->pushSlot(info().thisSlot());
return true;
}
return abort("JSOP_THIS hard case not yet handled"); return abort("JSOP_THIS hard case not yet handled");
} }

Просмотреть файл

@ -1102,7 +1102,7 @@ IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo)
// access the "in warmup" flag of the runtime. // access the "in warmup" flag of the runtime.
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
case ParallelExecution: case ParallelExecution: {
// During Parallel Exec, we always force sequential, so // During Parallel Exec, we always force sequential, so
// replace with true. This permits UCE to eliminate the // replace with true. This permits UCE to eliminate the
// entire path as dead, which is important. // entire path as dead, which is important.
@ -1111,6 +1111,9 @@ IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo)
current->add(ins); current->add(ins);
current->push(ins); current->push(ins);
return InliningStatus_Inlined; return InliningStatus_Inlined;
}
default:;
} }
MOZ_ASSUME_UNREACHABLE("Invalid execution mode"); MOZ_ASSUME_UNREACHABLE("Invalid execution mode");
@ -1285,6 +1288,7 @@ IonBuilder::inlineNewDenseArray(CallInfo &callInfo)
return inlineNewDenseArrayForSequentialExecution(callInfo); return inlineNewDenseArrayForSequentialExecution(callInfo);
case ParallelExecution: case ParallelExecution:
return inlineNewDenseArrayForParallelExecution(callInfo); return inlineNewDenseArrayForParallelExecution(callInfo);
default:;
} }
MOZ_ASSUME_UNREACHABLE("unknown ExecutionMode"); MOZ_ASSUME_UNREACHABLE("unknown ExecutionMode");

Просмотреть файл

@ -147,7 +147,7 @@ PerfSpewer::writeProfile(JSScript *script,
if (size > 0) { if (size > 0) {
fprintf(fp_, fprintf(fp_,
"%lx %lx %s:%d: Func%02d\n", "%lx %lx %s:%d: Func%02d\n",
reinterpret_cast<unsigned long>(code->raw()), reinterpret_cast<uintptr_t>(code->raw()),
size, size,
script->filename(), script->filename(),
script->lineno, script->lineno,

Просмотреть файл

@ -1787,88 +1787,6 @@ ScriptAnalysis::needsArgsObj(JSContext *cx)
return needsArgsObj(cx, seen, SSAValue::PushedValue(pcOff, 0)); return needsArgsObj(cx, seen, SSAValue::PushedValue(pcOff, 0));
} }
CrossSSAValue
CrossScriptSSA::foldValue(const CrossSSAValue &cv)
{
const Frame &frame = getFrame(cv.frame);
const SSAValue &v = cv.v;
JSScript *parentScript = NULL;
ScriptAnalysis *parentAnalysis = NULL;
if (frame.parent != INVALID_FRAME) {
parentScript = getFrame(frame.parent).script;
parentAnalysis = parentScript->analysis();
}
if (v.kind() == SSAValue::VAR && v.varInitial() && parentScript) {
uint32_t slot = v.varSlot();
if (slot >= ArgSlot(0) && slot < LocalSlot(frame.script, 0)) {
uint32_t argc = GET_ARGC(frame.parentpc);
SSAValue argv = parentAnalysis->poppedValue(frame.parentpc, argc - 1 - (slot - ArgSlot(0)));
return foldValue(CrossSSAValue(frame.parent, argv));
}
}
if (v.kind() == SSAValue::PUSHED) {
jsbytecode *pc = frame.script->code + v.pushedOffset();
switch (JSOp(*pc)) {
case JSOP_THIS:
if (parentScript) {
uint32_t argc = GET_ARGC(frame.parentpc);
SSAValue thisv = parentAnalysis->poppedValue(frame.parentpc, argc);
return foldValue(CrossSSAValue(frame.parent, thisv));
}
break;
case JSOP_CALL: {
/*
* If there is a single inline callee with a single return site,
* propagate back to that.
*/
JSScript *callee = NULL;
uint32_t calleeFrame = INVALID_FRAME;
for (unsigned i = 0; i < numFrames(); i++) {
if (iterFrame(i).parent == cv.frame && iterFrame(i).parentpc == pc) {
if (callee)
return cv; /* Multiple callees */
callee = iterFrame(i).script;
calleeFrame = iterFrame(i).index;
}
}
if (callee && callee->analysis()->numReturnSites() == 1) {
ScriptAnalysis *analysis = callee->analysis();
uint32_t offset = 0;
while (offset < callee->length) {
jsbytecode *pc = callee->code + offset;
if (analysis->maybeCode(pc) && JSOp(*pc) == JSOP_RETURN)
return foldValue(CrossSSAValue(calleeFrame, analysis->poppedValue(pc, 0)));
offset += GetBytecodeLength(pc);
}
}
break;
}
case JSOP_TOID: {
/*
* TOID acts as identity for integers, so to get better precision
* we should propagate its popped values forward if it acted as
* identity.
*/
ScriptAnalysis *analysis = frame.script->analysis();
SSAValue toidv = analysis->poppedValue(pc, 0);
if (analysis->getValueTypes(toidv)->getKnownTypeTag() == JSVAL_TYPE_INT32)
return foldValue(CrossSSAValue(cv.frame, toidv));
break;
}
default:;
}
}
return cv;
}
#ifdef DEBUG #ifdef DEBUG
void void

Просмотреть файл

@ -78,15 +78,6 @@ class Bytecode
/* Whether this is a catch/finally entry point. */ /* Whether this is a catch/finally entry point. */
bool exceptionEntry : 1; bool exceptionEntry : 1;
/*
* Side effects of this bytecode were not determined by type inference.
* Either a property set with unknown lvalue, or call with unknown callee.
*/
bool monitoredTypes : 1;
/* Call whose result should be monitored. */
bool monitoredTypesReturn : 1;
/* /*
* Dynamically observed state about the execution of this opcode. These are * Dynamically observed state about the execution of this opcode. These are
* hints about the script for use during compilation. * hints about the script for use during compilation.
@ -129,14 +120,6 @@ class Bytecode
*/ */
Vector<SlotValue> *pendingValues; Vector<SlotValue> *pendingValues;
}; };
/* --------- Type inference --------- */
/* Types for all values pushed by this bytecode. */
types::StackTypeSet *pushedTypes;
/* Any type barriers in place at this bytecode. */
types::TypeBarrier *typeBarriers;
}; };
/* /*
@ -471,7 +454,6 @@ class SSAValue
uint32_t phiSlot() const; uint32_t phiSlot() const;
uint32_t phiLength() const; uint32_t phiLength() const;
const SSAValue &phiValue(uint32_t i) const; const SSAValue &phiValue(uint32_t i) const;
types::TypeSet *phiTypes() const;
/* Offset at which this phi node was created. */ /* Offset at which this phi node was created. */
uint32_t phiOffset() const { uint32_t phiOffset() const {
@ -571,7 +553,6 @@ class SSAValue
*/ */
struct SSAPhiNode struct SSAPhiNode
{ {
types::StackTypeSet types;
uint32_t slot; uint32_t slot;
uint32_t length; uint32_t length;
SSAValue *options; SSAValue *options;
@ -599,13 +580,6 @@ SSAValue::phiValue(uint32_t i) const
return u.phi.node->options[i]; return u.phi.node->options[i];
} }
inline types::TypeSet *
SSAValue::phiTypes() const
{
JS_ASSERT(kind() == PHI);
return &u.phi.node->types;
}
class SSAUseChain class SSAUseChain
{ {
public: public:
@ -654,7 +628,6 @@ class ScriptAnalysis
bool ranBytecode_; bool ranBytecode_;
bool ranSSA_; bool ranSSA_;
bool ranLifetimes_; bool ranLifetimes_;
bool ranInference_;
#ifdef DEBUG #ifdef DEBUG
/* Whether the compartment was in debug mode when we performed the analysis. */ /* Whether the compartment was in debug mode when we performed the analysis. */
@ -689,15 +662,10 @@ class ScriptAnalysis
bool ranBytecode() { return ranBytecode_; } bool ranBytecode() { return ranBytecode_; }
bool ranSSA() { return ranSSA_; } bool ranSSA() { return ranSSA_; }
bool ranLifetimes() { return ranLifetimes_; } bool ranLifetimes() { return ranLifetimes_; }
bool ranInference() { return ranInference_; }
void analyzeBytecode(JSContext *cx); void analyzeBytecode(JSContext *cx);
void analyzeSSA(JSContext *cx); void analyzeSSA(JSContext *cx);
void analyzeLifetimes(JSContext *cx); void analyzeLifetimes(JSContext *cx);
void analyzeTypes(JSContext *cx);
/* Analyze the effect of invoking 'new' on script. */
void analyzeTypesNew(JSContext *cx);
bool OOM() const { return outOfMemory; } bool OOM() const { return outOfMemory; }
bool failed() const { return hadFailure; } bool failed() const { return hadFailure; }
@ -760,45 +728,6 @@ class ScriptAnalysis
} }
const SlotValue *newValues(const jsbytecode *pc) { return newValues(pc - script_->code); } const SlotValue *newValues(const jsbytecode *pc) { return newValues(pc - script_->code); }
inline types::StackTypeSet *pushedTypes(uint32_t offset, uint32_t which = 0);
inline types::StackTypeSet *pushedTypes(const jsbytecode *pc, uint32_t which);
bool hasPushedTypes(const jsbytecode *pc) { return getCode(pc).pushedTypes != NULL; }
types::TypeBarrier *typeBarriers(JSContext *cx, uint32_t offset) {
if (getCode(offset).typeBarriers)
pruneTypeBarriers(cx, offset);
return getCode(offset).typeBarriers;
}
types::TypeBarrier *typeBarriers(JSContext *cx, const jsbytecode *pc) {
return typeBarriers(cx, pc - script_->code);
}
void addTypeBarrier(JSContext *cx, const jsbytecode *pc,
types::TypeSet *target, types::Type type);
void addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc,
types::TypeSet *target,
HandleObject singleton, HandleId singletonId);
/* Remove obsolete type barriers at the given offset. */
void pruneTypeBarriers(JSContext *cx, uint32_t offset);
/*
* Remove still-active type barriers at the given offset. If 'all' is set,
* then all barriers are removed, otherwise only those deemed excessive
* are removed.
*/
void breakTypeBarriers(JSContext *cx, uint32_t offset, bool all);
/* Break all type barriers used in computing v. */
void breakTypeBarriersSSA(JSContext *cx, const SSAValue &v);
inline void addPushedType(JSContext *cx, uint32_t offset, uint32_t which, types::Type type);
inline types::StackTypeSet *getValueTypes(const SSAValue &v);
inline types::StackTypeSet *poppedTypes(uint32_t offset, uint32_t which);
inline types::StackTypeSet *poppedTypes(const jsbytecode *pc, uint32_t which);
bool trackUseChain(const SSAValue &v) { bool trackUseChain(const SSAValue &v) {
JS_ASSERT_IF(v.kind() == SSAValue::VAR, trackSlot(v.varSlot())); JS_ASSERT_IF(v.kind() == SSAValue::VAR, trackSlot(v.varSlot()));
return v.kind() != SSAValue::EMPTY && return v.kind() != SSAValue::EMPTY &&
@ -912,9 +841,6 @@ class ScriptAnalysis
{} {}
}; };
/* Type inference helpers */
bool analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferenceState &state);
typedef Vector<SSAValue, 16> SeenVector; typedef Vector<SSAValue, 16> SeenVector;
bool needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v); bool needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v);
bool needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use); bool needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use);
@ -928,84 +854,6 @@ class ScriptAnalysis
#endif #endif
}; };
/* SSA value as used by CrossScriptSSA, identifies the frame it came from. */
struct CrossSSAValue
{
unsigned frame;
SSAValue v;
CrossSSAValue(unsigned frame, const SSAValue &v) : frame(frame), v(v) {}
};
/*
* Analysis for managing SSA values from multiple call stack frames. These are
* created by the backend compiler when inlining functions, and allow for
* values to be tracked as they flow into or out of the inlined frames.
*/
class CrossScriptSSA
{
public:
static const uint32_t OUTER_FRAME = UINT32_MAX;
static const unsigned INVALID_FRAME = uint32_t(-2);
struct Frame {
uint32_t index;
JSScript *script;
uint32_t depth; /* Distance from outer frame to this frame, in sizeof(Value) */
uint32_t parent;
jsbytecode *parentpc;
Frame(uint32_t index, JSScript *script, uint32_t depth, uint32_t parent,
jsbytecode *parentpc)
: index(index), script(script), depth(depth), parent(parent), parentpc(parentpc)
{}
};
const Frame &getFrame(uint32_t index) {
if (index == OUTER_FRAME)
return outerFrame;
return inlineFrames[index];
}
unsigned numFrames() { return 1 + inlineFrames.length(); }
const Frame &iterFrame(unsigned i) {
if (i == 0)
return outerFrame;
return inlineFrames[i - 1];
}
JSScript *outerScript() { return outerFrame.script; }
/* Total length of scripts preceding a frame. */
size_t frameLength(uint32_t index) {
if (index == OUTER_FRAME)
return 0;
size_t res = outerFrame.script->length;
for (unsigned i = 0; i < index; i++)
res += inlineFrames[i].script->length;
return res;
}
inline types::StackTypeSet *getValueTypes(const CrossSSAValue &cv);
bool addInlineFrame(JSScript *script, uint32_t depth, uint32_t parent,
jsbytecode *parentpc)
{
uint32_t index = inlineFrames.length();
return inlineFrames.append(Frame(index, script, depth, parent, parentpc));
}
CrossScriptSSA(JSContext *cx, JSScript *outer)
: outerFrame(OUTER_FRAME, outer, 0, INVALID_FRAME, NULL), inlineFrames(cx)
{}
CrossSSAValue foldValue(const CrossSSAValue &cv);
private:
Frame outerFrame;
Vector<Frame> inlineFrames;
};
#ifdef DEBUG #ifdef DEBUG
void PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc); void PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc);
#endif #endif

Просмотреть файл

@ -29,64 +29,6 @@ ScriptAnalysis::poppedValue(const jsbytecode *pc, uint32_t which)
return poppedValue(pc - script_->code, which); return poppedValue(pc - script_->code, which);
} }
inline types::StackTypeSet *
ScriptAnalysis::pushedTypes(uint32_t offset, uint32_t which)
{
JS_ASSERT(offset < script_->length);
JS_ASSERT(which < GetDefCount(script_, offset) +
(ExtendedDef(script_->code + offset) ? 1 : 0));
types::StackTypeSet *array = getCode(offset).pushedTypes;
JS_ASSERT(array);
return array + which;
}
inline types::StackTypeSet *
ScriptAnalysis::pushedTypes(const jsbytecode *pc, uint32_t which)
{
return pushedTypes(pc - script_->code, which);
}
inline types::StackTypeSet *
ScriptAnalysis::getValueTypes(const SSAValue &v)
{
switch (v.kind()) {
case SSAValue::PUSHED:
return pushedTypes(v.pushedOffset(), v.pushedIndex());
case SSAValue::VAR:
JS_ASSERT(!slotEscapes(v.varSlot()));
if (v.varInitial()) {
if (v.varSlot() < LocalSlot(script_, 0))
return types::TypeScript::SlotTypes(script_, v.varSlot());
return undefinedTypeSet;
} else {
/*
* Results of intermediate assignments have the same type as
* the first type pushed by the assignment op. Note that this
* may not be the exact same value as was pushed, due to
* post-inc/dec ops.
*/
return pushedTypes(v.varOffset(), 0);
}
case SSAValue::PHI:
return &v.phiNode()->types;
default:
/* Cannot compute types for empty SSA values. */
MOZ_ASSUME_UNREACHABLE("Bad SSA value");
}
}
inline types::StackTypeSet *
ScriptAnalysis::poppedTypes(uint32_t offset, uint32_t which)
{
return getValueTypes(poppedValue(offset, which));
}
inline types::StackTypeSet *
ScriptAnalysis::poppedTypes(const jsbytecode *pc, uint32_t which)
{
return getValueTypes(poppedValue(pc, which));
}
inline SSAUseChain *& inline SSAUseChain *&
ScriptAnalysis::useChain(const SSAValue &v) ScriptAnalysis::useChain(const SSAValue &v)
{ {
@ -107,12 +49,6 @@ ScriptAnalysis::getCallPC(jsbytecode *pc)
return script_->code + uses->offset; return script_->code + uses->offset;
} }
inline types::StackTypeSet *
CrossScriptSSA::getValueTypes(const CrossSSAValue &cv)
{
return getFrame(cv.frame).script->analysis()->getValueTypes(cv.v);
}
} /* namespace analyze */ } /* namespace analyze */
} /* namespace js */ } /* namespace js */

Просмотреть файл

@ -9,11 +9,9 @@
#ifndef jsapi_h #ifndef jsapi_h
#define jsapi_h #define jsapi_h
#include "mozilla/Compiler.h"
#include "mozilla/FloatingPoint.h" #include "mozilla/FloatingPoint.h"
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/RangedPtr.h" #include "mozilla/RangedPtr.h"
#include "mozilla/TypeTraits.h"
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
@ -24,7 +22,6 @@
#include "jspubtd.h" #include "jspubtd.h"
#include "js/CallArgs.h" #include "js/CallArgs.h"
#include "js/CallNonGenericMethod.h"
#include "js/Class.h" #include "js/Class.h"
#include "js/HashTable.h" #include "js/HashTable.h"
#include "js/Id.h" #include "js/Id.h"
@ -1358,7 +1355,7 @@ JS_EndRequest(JSContext *cx);
extern JS_PUBLIC_API(bool) extern JS_PUBLIC_API(bool)
JS_IsInRequest(JSRuntime *rt); JS_IsInRequest(JSRuntime *rt);
namespace JS { namespace js {
inline bool inline bool
IsPoisonedId(jsid iden) IsPoisonedId(jsid iden)
@ -1370,15 +1367,11 @@ IsPoisonedId(jsid iden)
return false; return false;
} }
} /* namespace JS */
namespace js {
template <> struct GCMethods<jsid> template <> struct GCMethods<jsid>
{ {
static jsid initial() { return JSID_VOID; } static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; } static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return JS::IsPoisonedId(id); } static bool poisoned(jsid id) { return IsPoisonedId(id); }
static bool needsPostBarrier(jsid id) { return false; } static bool needsPostBarrier(jsid id) { return false; }
#ifdef JSGC_GENERATIONAL #ifdef JSGC_GENERATIONAL
static void postBarrier(jsid *idp) {} static void postBarrier(jsid *idp) {}
@ -4586,81 +4579,4 @@ extern JS_PUBLIC_DATA(const Handle<jsid>) JSID_EMPTYHANDLE;
} /* namespace JS */ } /* namespace JS */
namespace js {
/*
* Import some JS:: names into the js namespace so we can make unqualified
* references to them.
*/
using JS::Value;
using JS::IsPoisonedValue;
using JS::NullValue;
using JS::UndefinedValue;
using JS::Int32Value;
using JS::DoubleValue;
using JS::StringValue;
using JS::BooleanValue;
using JS::ObjectValue;
using JS::MagicValue;
using JS::NumberValue;
using JS::ObjectOrNullValue;
using JS::PrivateValue;
using JS::PrivateUint32Value;
using JS::IsPoisonedPtr;
using JS::IsPoisonedId;
using JS::StableCharPtr;
using JS::TwoByteChars;
using JS::Latin1CharsZ;
using JS::AutoIdVector;
using JS::AutoValueVector;
using JS::AutoObjectVector;
using JS::AutoFunctionVector;
using JS::AutoScriptVector;
using JS::AutoIdArray;
using JS::AutoGCRooter;
using JS::AutoArrayRooter;
using JS::AutoVectorRooter;
using JS::AutoHashMapRooter;
using JS::AutoHashSetRooter;
using JS::CallArgs;
using JS::IsAcceptableThis;
using JS::NativeImpl;
using JS::CallReceiver;
using JS::CompileOptions;
using JS::CallNonGenericMethod;
using JS::Rooted;
using JS::RootedObject;
using JS::RootedFunction;
using JS::RootedScript;
using JS::RootedString;
using JS::RootedId;
using JS::RootedValue;
using JS::Handle;
using JS::HandleObject;
using JS::HandleFunction;
using JS::HandleScript;
using JS::HandleString;
using JS::HandleId;
using JS::HandleValue;
using JS::MutableHandle;
using JS::MutableHandleObject;
using JS::MutableHandleFunction;
using JS::MutableHandleScript;
using JS::MutableHandleString;
using JS::MutableHandleId;
using JS::MutableHandleValue;
using JS::Zone;
} /* namespace js */
#endif /* jsapi_h */ #endif /* jsapi_h */

Просмотреть файл

@ -6,11 +6,13 @@
#ifndef jsbool_h #ifndef jsbool_h
#define jsbool_h #define jsbool_h
/* /*
* JS boolean interface. * JS boolean interface.
*/ */
#include "jsapi.h" #include "jsapi.h"
#include "NamespaceImports.h"
extern JSObject * extern JSObject *
js_InitBooleanClass(JSContext *cx, js::HandleObject obj); js_InitBooleanClass(JSContext *cx, js::HandleObject obj);

Просмотреть файл

@ -12,6 +12,7 @@
#define jsexn_h #define jsexn_h
#include "jsapi.h" #include "jsapi.h"
#include "NamespaceImports.h"
/* /*
* Initialize the exception constructor/prototype hierarchy. * Initialize the exception constructor/prototype hierarchy.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -571,22 +571,8 @@ class StackTypeSet : public TypeSet
*/ */
static StackTypeSet *make(JSContext *cx, const char *name); static StackTypeSet *make(JSContext *cx, const char *name);
/* Constraints for type inference. */ /* Propagate any types from this set into target. */
void addSubset(JSContext *cx, StackTypeSet *target);
void addSubset(JSContext *cx, TypeSet *target);
void addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *target, jsid id);
void addSetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *target, jsid id);
void addSetElement(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *objectTypes, StackTypeSet *valueTypes);
void addCall(JSContext *cx, TypeCallsite *site);
void addArith(JSContext *cx, JSScript *script, jsbytecode *pc,
TypeSet *target, TypeSet *other = NULL);
void addTransformThis(JSContext *cx, JSScript *script, TypeSet *target);
void addPropagateThis(JSContext *cx, JSScript *script, jsbytecode *pc,
Type type, StackTypeSet *types = NULL);
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
/* /*
* Constraints for JIT compilation. * Constraints for JIT compilation.
@ -679,16 +665,8 @@ class HeapTypeSet : public TypeSet
{ {
public: public:
/* Constraints for type inference. */ /* Propagate any types from this set into target. */
void addSubset(JSContext *cx, HeapTypeSet *target);
void addSubset(JSContext *cx, TypeSet *target);
void addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *target, jsid id);
void addCallProperty(JSContext *cx, JSScript *script, jsbytecode *pc, jsid id);
void addFilterPrimitives(JSContext *cx, TypeSet *target);
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
/* Constraints for JIT compilation. */
/* Completely freeze the contents of this type set. */ /* Completely freeze the contents of this type set. */
void addFreeze(JSContext *cx); void addFreeze(JSContext *cx);
@ -745,6 +723,13 @@ TypeSet::toHeapTypeSet()
return (HeapTypeSet *) this; return (HeapTypeSet *) this;
} }
bool
AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, TypeObject *type, jsid id);
void
AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type,
JSScript *script, JSScript *calleeScript);
/* /*
* Handler which persists information about dynamic types pushed within a * Handler which persists information about dynamic types pushed within a
* script which can affect its behavior and are not covered by JOF_TYPESET ops, * script which can affect its behavior and are not covered by JOF_TYPESET ops,
@ -932,14 +917,14 @@ struct TypeNewScript : public TypeObjectAddendum
* scripted setter is added to one of the object's prototypes while it is * scripted setter is added to one of the object's prototypes while it is
* in the middle of being initialized, so we can walk the stack and fixup * in the middle of being initialized, so we can walk the stack and fixup
* any objects which look for in-progress objects which were prematurely * any objects which look for in-progress objects which were prematurely
* set with their final shape. Initialization can traverse stack frames, * set with their final shape. Property assignments in inner frames are
* in which case FRAME_PUSH/FRAME_POP are used. * preceded by a series of SETPROP_FRAME entries specifying the stack down
* to the frame containing the write.
*/ */
struct Initializer { struct Initializer {
enum Kind { enum Kind {
SETPROP, SETPROP,
FRAME_PUSH, SETPROP_FRAME,
FRAME_POP,
DONE DONE
} kind; } kind;
uint32_t offset; uint32_t offset;
@ -1145,7 +1130,7 @@ struct TypeObject : gc::Cell
void clearAddendum(ExclusiveContext *cx); void clearAddendum(ExclusiveContext *cx);
void clearNewScriptAddendum(ExclusiveContext *cx); void clearNewScriptAddendum(ExclusiveContext *cx);
void clearBinaryDataAddendum(ExclusiveContext *cx); void clearBinaryDataAddendum(ExclusiveContext *cx);
void getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force = false); void getFromPrototypes(JSContext *cx, jsid id, HeapTypeSet *types, bool force = false);
void print(); void print();
@ -1493,10 +1478,6 @@ struct TypeCompartment
void addPendingRecompile(JSContext *cx, const RecompileInfo &info); void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
void addPendingRecompile(JSContext *cx, JSScript *script); void addPendingRecompile(JSContext *cx, JSScript *script);
/* Monitor future effects on a bytecode. */
void monitorBytecode(JSContext *cx, JSScript *script, uint32_t offset,
bool returnOnly = false);
/* Mark any type set containing obj as having a generic object type. */ /* Mark any type set containing obj as having a generic object type. */
void markSetsUnknown(JSContext *cx, TypeObject *obj); void markSetsUnknown(JSContext *cx, TypeObject *obj);

Просмотреть файл

@ -1682,18 +1682,6 @@ JSScript::ensureRanAnalysis(JSContext *cx)
return true; return true;
} }
inline bool
JSScript::ensureRanInference(JSContext *cx)
{
if (!ensureRanAnalysis(cx))
return false;
if (!analysis()->ranInference()) {
js::types::AutoEnterAnalysis enter(cx);
analysis()->analyzeTypes(cx);
}
return !analysis()->OOM() && !cx->zone()->types.pendingNukeTypes;
}
inline bool inline bool
JSScript::hasAnalysis() JSScript::hasAnalysis()
{ {
@ -1723,14 +1711,6 @@ JSScript::clearPropertyReadTypes()
types->propertyReadTypes = NULL; types->propertyReadTypes = NULL;
} }
inline void
js::analyze::ScriptAnalysis::addPushedType(JSContext *cx, uint32_t offset, uint32_t which,
js::types::Type type)
{
js::types::TypeSet *pushed = pushedTypes(offset, which);
pushed->addType(cx, type);
}
namespace js { namespace js {
template <> template <>

Просмотреть файл

@ -9,7 +9,7 @@
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "jsapi.h" #include "NamespaceImports.h"
namespace js { namespace js {

Просмотреть файл

@ -9,7 +9,7 @@
#include "mozilla/FloatingPoint.h" #include "mozilla/FloatingPoint.h"
#include "jsapi.h" #include "NamespaceImports.h"
#include "vm/NumericConversions.h" #include "vm/NumericConversions.h"

Просмотреть файл

@ -8,6 +8,7 @@
#define json_h #define json_h
#include "jsapi.h" #include "jsapi.h"
#include "NamespaceImports.h"
#include "js/RootingAPI.h" #include "js/RootingAPI.h"

Просмотреть файл

@ -13,6 +13,7 @@
#include "jsapi.h" #include "jsapi.h"
#include "jsbytecode.h" #include "jsbytecode.h"
#include "NamespaceImports.h"
#include "frontend/SourceNotes.h" #include "frontend/SourceNotes.h"

Просмотреть файл

@ -6,7 +6,6 @@
#include "jspropertytree.h" #include "jspropertytree.h"
#include "jsapi.h"
#include "jscntxt.h" #include "jscntxt.h"
#include "jsgc.h" #include "jsgc.h"
#include "jstypes.h" #include "jstypes.h"

Просмотреть файл

@ -2834,11 +2834,6 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
} }
} }
if (script->hasAnalysis() && script->analysis()->ranInference()) {
types::AutoEnterAnalysis enter(cx);
types::TypeScript::MonitorUnknown(cx, script, script->argumentsBytecode());
}
return true; return true;
} }

Просмотреть файл

@ -10,12 +10,13 @@
#include "mozilla/HashFunctions.h" #include "mozilla/HashFunctions.h"
#include "mozilla/PodOperations.h" #include "mozilla/PodOperations.h"
#include "jsapi.h"
#include "jsutil.h" #include "jsutil.h"
#include "NamespaceImports.h"
#include "js/RootingAPI.h" #include "js/RootingAPI.h"
#include "vm/Unicode.h" #include "vm/Unicode.h"
class JSAutoByteString;
class JSFlatString; class JSFlatString;
class JSLinearString; class JSLinearString;
class JSStableString; class JSStableString;

Просмотреть файл

@ -8,7 +8,6 @@
#define jswatchpoint_h #define jswatchpoint_h
#include "jsalloc.h" #include "jsalloc.h"
#include "jsapi.h"
#include "gc/Barrier.h" #include "gc/Barrier.h"
#include "js/HashTable.h" #include "js/HashTable.h"

Просмотреть файл

@ -202,6 +202,9 @@ ParseTask::~ParseTask()
// ParseTask takes over ownership of its input exclusive context. // ParseTask takes over ownership of its input exclusive context.
js_delete(cx); js_delete(cx);
for (size_t i = 0; i < errors.length(); i++)
js_delete(errors[i]);
} }
bool bool
@ -550,7 +553,7 @@ WorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *toke
if (maybecx) { if (maybecx) {
AutoCompartment ac(maybecx, parseTask->scopeChain); AutoCompartment ac(maybecx, parseTask->scopeChain);
for (size_t i = 0; i < parseTask->errors.length(); i++) for (size_t i = 0; i < parseTask->errors.length(); i++)
parseTask->errors[i].throwError(maybecx); parseTask->errors[i]->throwError(maybecx);
} }
JSScript *script = parseTask->script; JSScript *script = parseTask->script;
@ -677,9 +680,12 @@ ExclusiveContext::setWorkerThread(WorkerThread *workerThread)
frontend::CompileError & frontend::CompileError &
ExclusiveContext::addPendingCompileError() ExclusiveContext::addPendingCompileError()
{ {
if (!workerThread->parseTask->errors.append(frontend::CompileError())) frontend::CompileError *error = js_new<frontend::CompileError>();
if (!error)
MOZ_CRASH(); MOZ_CRASH();
return workerThread->parseTask->errors.back(); if (!workerThread->parseTask->errors.append(error))
MOZ_CRASH();
return *error;
} }
void void

Просмотреть файл

@ -389,7 +389,7 @@ struct ParseTask
// Any errors or warnings produced during compilation. These are reported // Any errors or warnings produced during compilation. These are reported
// when finishing the script. // when finishing the script.
Vector<frontend::CompileError> errors; Vector<frontend::CompileError *> errors;
ParseTask(ExclusiveContext *cx, const CompileOptions &options, ParseTask(ExclusiveContext *cx, const CompileOptions &options,
const jschar *chars, size_t length, JSObject *scopeChain, const jschar *chars, size_t length, JSObject *scopeChain,

Просмотреть файл

@ -6,7 +6,10 @@
#ifndef perf_jsperf_h #ifndef perf_jsperf_h
#define perf_jsperf_h #define perf_jsperf_h
#include "jsapi.h" #include "jstypes.h"
#include "js/TypeDecls.h"
#include "js/Utility.h"
namespace JS { namespace JS {
@ -118,12 +121,12 @@ extern JS_FRIEND_API(JSObject*)
RegisterPerfMeasurement(JSContext *cx, JSObject *global); RegisterPerfMeasurement(JSContext *cx, JSObject *global);
/* /*
* Given a jsval which contains an instance of the aforementioned * Given a Value which contains an instance of the aforementioned
* wrapper class, extract the C++ object. Returns NULL if the * wrapper class, extract the C++ object. Returns NULL if the
* jsval is not an instance of the wrapper. * Value is not an instance of the wrapper.
*/ */
extern JS_FRIEND_API(PerfMeasurement*) extern JS_FRIEND_API(PerfMeasurement*)
ExtractPerfMeasurement(jsval wrapper); ExtractPerfMeasurement(Value wrapper);
} // namespace JS } // namespace JS

Просмотреть файл

@ -953,8 +953,8 @@ TryNoteIter::settle()
} }
} }
#define PUSH_COPY(v) do { *regs.sp++ = v; assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0) #define PUSH_COPY(v) do { *regs.sp++ = (v); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
#define PUSH_COPY_SKIP_CHECK(v) *regs.sp++ = v #define PUSH_COPY_SKIP_CHECK(v) *regs.sp++ = (v)
#define PUSH_NULL() regs.sp++->setNull() #define PUSH_NULL() regs.sp++->setNull()
#define PUSH_UNDEFINED() regs.sp++->setUndefined() #define PUSH_UNDEFINED() regs.sp++->setUndefined()
#define PUSH_BOOLEAN(b) regs.sp++->setBoolean(b) #define PUSH_BOOLEAN(b) regs.sp++->setBoolean(b)
@ -964,13 +964,13 @@ TryNoteIter::settle()
#define PUSH_OBJECT(obj) do { regs.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0) #define PUSH_OBJECT(obj) do { regs.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
#define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0) #define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
#define PUSH_HOLE() regs.sp++->setMagic(JS_ELEMENTS_HOLE) #define PUSH_HOLE() regs.sp++->setMagic(JS_ELEMENTS_HOLE)
#define POP_COPY_TO(v) v = *--regs.sp #define POP_COPY_TO(v) (v) = *--regs.sp
#define POP_RETURN_VALUE() regs.fp()->setReturnValue(*--regs.sp) #define POP_RETURN_VALUE() regs.fp()->setReturnValue(*--regs.sp)
#define FETCH_OBJECT(cx, n, obj) \ #define FETCH_OBJECT(cx, n, obj) \
JS_BEGIN_MACRO \ JS_BEGIN_MACRO \
HandleValue val = regs.stackHandleAt(n); \ HandleValue val = regs.stackHandleAt(n); \
obj = ToObjectFromStack(cx, (val)); \ obj = ToObjectFromStack((cx), (val)); \
if (!obj) \ if (!obj) \
goto error; \ goto error; \
JS_END_MACRO JS_END_MACRO
@ -1277,35 +1277,19 @@ Interpret(JSContext *cx, RunState &state)
register int switchMask = 0; register int switchMask = 0;
int switchOp; int switchOp;
# define DO_OP() goto do_op #define DO_OP() goto do_op
# define BEGIN_CASE(OP) case OP: #define BEGIN_CASE(OP) case OP:
# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH) #define END_CASE(OP) \
# define END_CASE_LEN(n) END_CASE_LENX(n) JS_BEGIN_MACRO \
# define END_CASE_LENX(n) END_CASE_LEN##n len = OP##_LENGTH; \
goto advanceAndDoOp; \
JS_END_MACRO;
/* #define END_VARLEN_CASE goto advanceAndDoOp;
* To share the code for all len == 1 cases we use the specialized label with
* code that falls through to advanceAndDoOp: .
*/
# define END_CASE_LEN1 goto advance_pc_by_one;
# define END_CASE_LEN2 len = 2; goto advanceAndDoOp;
# define END_CASE_LEN3 len = 3; goto advanceAndDoOp;
# define END_CASE_LEN4 len = 4; goto advanceAndDoOp;
# define END_CASE_LEN5 len = 5; goto advanceAndDoOp;
# define END_CASE_LEN6 len = 6; goto advanceAndDoOp;
# define END_CASE_LEN7 len = 7; goto advanceAndDoOp;
# define END_CASE_LEN8 len = 8; goto advanceAndDoOp;
# define END_CASE_LEN9 len = 9; goto advanceAndDoOp;
# define END_CASE_LEN10 len = 10; goto advanceAndDoOp;
# define END_CASE_LEN11 len = 11; goto advanceAndDoOp;
# define END_CASE_LEN12 len = 12; goto advanceAndDoOp;
# define END_VARLEN_CASE goto advanceAndDoOp;
# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
# define END_EMPTY_CASES goto advance_pc_by_one;
#define LOAD_DOUBLE(PCOFF, dbl) \ #define LOAD_DOUBLE(PCOFF, dbl) \
(dbl = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble()) ((dbl) = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble())
/* /*
* Prepare to call a user-supplied branch handler, and abort the script * Prepare to call a user-supplied branch handler, and abort the script
@ -1431,12 +1415,7 @@ Interpret(JSContext *cx, RunState &state)
if (rt->profilingScripts || cx->runtime()->debugHooks.interruptHook) if (rt->profilingScripts || cx->runtime()->debugHooks.interruptHook)
switchMask = -1; /* Enable interrupts. */ switchMask = -1; /* Enable interrupts. */
goto advanceAndDoOp;
for (;;) { for (;;) {
advance_pc_by_one:
JS_ASSERT(js_CodeSpec[op].length == 1);
len = 1;
advanceAndDoOp: advanceAndDoOp:
js::gc::MaybeVerifyBarriers(cx); js::gc::MaybeVerifyBarriers(cx);
regs.pc += len; regs.pc += len;
@ -1518,51 +1497,55 @@ Interpret(JSContext *cx, RunState &state)
goto do_switch; goto do_switch;
} }
/* No-ops for ease of decompilation. */ /* Various 1-byte no-ops. */
ADD_EMPTY_CASE(JSOP_NOP) BEGIN_CASE(JSOP_NOP)
ADD_EMPTY_CASE(JSOP_UNUSED125) BEGIN_CASE(JSOP_UNUSED125)
ADD_EMPTY_CASE(JSOP_UNUSED126) BEGIN_CASE(JSOP_UNUSED126)
ADD_EMPTY_CASE(JSOP_UNUSED132) BEGIN_CASE(JSOP_UNUSED132)
ADD_EMPTY_CASE(JSOP_UNUSED148) BEGIN_CASE(JSOP_UNUSED148)
ADD_EMPTY_CASE(JSOP_UNUSED161) BEGIN_CASE(JSOP_UNUSED161)
ADD_EMPTY_CASE(JSOP_UNUSED162) BEGIN_CASE(JSOP_UNUSED162)
ADD_EMPTY_CASE(JSOP_UNUSED163) BEGIN_CASE(JSOP_UNUSED163)
ADD_EMPTY_CASE(JSOP_UNUSED164) BEGIN_CASE(JSOP_UNUSED164)
ADD_EMPTY_CASE(JSOP_UNUSED165) BEGIN_CASE(JSOP_UNUSED165)
ADD_EMPTY_CASE(JSOP_UNUSED166) BEGIN_CASE(JSOP_UNUSED166)
ADD_EMPTY_CASE(JSOP_UNUSED167) BEGIN_CASE(JSOP_UNUSED167)
ADD_EMPTY_CASE(JSOP_UNUSED168) BEGIN_CASE(JSOP_UNUSED168)
ADD_EMPTY_CASE(JSOP_UNUSED169) BEGIN_CASE(JSOP_UNUSED169)
ADD_EMPTY_CASE(JSOP_UNUSED170) BEGIN_CASE(JSOP_UNUSED170)
ADD_EMPTY_CASE(JSOP_UNUSED171) BEGIN_CASE(JSOP_UNUSED171)
ADD_EMPTY_CASE(JSOP_UNUSED172) BEGIN_CASE(JSOP_UNUSED172)
ADD_EMPTY_CASE(JSOP_UNUSED173) BEGIN_CASE(JSOP_UNUSED173)
ADD_EMPTY_CASE(JSOP_UNUSED174) BEGIN_CASE(JSOP_UNUSED174)
ADD_EMPTY_CASE(JSOP_UNUSED175) BEGIN_CASE(JSOP_UNUSED175)
ADD_EMPTY_CASE(JSOP_UNUSED176) BEGIN_CASE(JSOP_UNUSED176)
ADD_EMPTY_CASE(JSOP_UNUSED177) BEGIN_CASE(JSOP_UNUSED177)
ADD_EMPTY_CASE(JSOP_UNUSED178) BEGIN_CASE(JSOP_UNUSED178)
ADD_EMPTY_CASE(JSOP_UNUSED179) BEGIN_CASE(JSOP_UNUSED179)
ADD_EMPTY_CASE(JSOP_UNUSED180) BEGIN_CASE(JSOP_UNUSED180)
ADD_EMPTY_CASE(JSOP_UNUSED181) BEGIN_CASE(JSOP_UNUSED181)
ADD_EMPTY_CASE(JSOP_UNUSED182) BEGIN_CASE(JSOP_UNUSED182)
ADD_EMPTY_CASE(JSOP_UNUSED183) BEGIN_CASE(JSOP_UNUSED183)
ADD_EMPTY_CASE(JSOP_UNUSED188) BEGIN_CASE(JSOP_UNUSED188)
ADD_EMPTY_CASE(JSOP_UNUSED189) BEGIN_CASE(JSOP_UNUSED189)
ADD_EMPTY_CASE(JSOP_UNUSED190) BEGIN_CASE(JSOP_UNUSED190)
ADD_EMPTY_CASE(JSOP_UNUSED200) BEGIN_CASE(JSOP_UNUSED200)
ADD_EMPTY_CASE(JSOP_UNUSED201) BEGIN_CASE(JSOP_UNUSED201)
ADD_EMPTY_CASE(JSOP_UNUSED208) BEGIN_CASE(JSOP_UNUSED208)
ADD_EMPTY_CASE(JSOP_UNUSED209) BEGIN_CASE(JSOP_UNUSED209)
ADD_EMPTY_CASE(JSOP_UNUSED210) BEGIN_CASE(JSOP_UNUSED210)
ADD_EMPTY_CASE(JSOP_UNUSED219) BEGIN_CASE(JSOP_UNUSED219)
ADD_EMPTY_CASE(JSOP_UNUSED220) BEGIN_CASE(JSOP_UNUSED220)
ADD_EMPTY_CASE(JSOP_UNUSED221) BEGIN_CASE(JSOP_UNUSED221)
ADD_EMPTY_CASE(JSOP_UNUSED222) BEGIN_CASE(JSOP_UNUSED222)
ADD_EMPTY_CASE(JSOP_UNUSED223) BEGIN_CASE(JSOP_UNUSED223)
ADD_EMPTY_CASE(JSOP_CONDSWITCH) BEGIN_CASE(JSOP_CONDSWITCH)
ADD_EMPTY_CASE(JSOP_TRY) BEGIN_CASE(JSOP_TRY)
END_EMPTY_CASES {
JS_ASSERT(js_CodeSpec[op].length == 1);
len = 1;
goto advanceAndDoOp;
}
BEGIN_CASE(JSOP_LOOPHEAD) BEGIN_CASE(JSOP_LOOPHEAD)
END_CASE(JSOP_LOOPHEAD) END_CASE(JSOP_LOOPHEAD)
@ -1605,7 +1588,6 @@ END_CASE(JSOP_LOOPENTRY)
BEGIN_CASE(JSOP_NOTEARG) BEGIN_CASE(JSOP_NOTEARG)
END_CASE(JSOP_NOTEARG) END_CASE(JSOP_NOTEARG)
/* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
BEGIN_CASE(JSOP_LINENO) BEGIN_CASE(JSOP_LINENO)
END_CASE(JSOP_LINENO) END_CASE(JSOP_LINENO)
@ -1772,17 +1754,17 @@ END_CASE(JSOP_AND)
#define FETCH_ELEMENT_ID(n, id) \ #define FETCH_ELEMENT_ID(n, id) \
JS_BEGIN_MACRO \ JS_BEGIN_MACRO \
if (!ValueToId<CanGC>(cx, regs.stackHandleAt(n), &id)) \ if (!ValueToId<CanGC>(cx, regs.stackHandleAt(n), &(id))) \
goto error; \ goto error; \
JS_END_MACRO JS_END_MACRO
#define TRY_BRANCH_AFTER_COND(cond,spdec) \ #define TRY_BRANCH_AFTER_COND(cond,spdec) \
JS_BEGIN_MACRO \ JS_BEGIN_MACRO \
JS_ASSERT(js_CodeSpec[op].length == 1); \ JS_ASSERT(js_CodeSpec[op].length == 1); \
unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ; \ unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ;\
if (diff_ <= 1) { \ if (diff_ <= 1) { \
regs.sp -= spdec; \ regs.sp -= (spdec); \
if (cond == (diff_ != 0)) { \ if ((cond) == (diff_ != 0)) { \
++regs.pc; \ ++regs.pc; \
len = GET_JUMP_OFFSET(regs.pc); \ len = GET_JUMP_OFFSET(regs.pc); \
BRANCH(len); \ BRANCH(len); \
@ -2004,7 +1986,7 @@ END_CASE(JSOP_NE)
bool equal; \ bool equal; \
if (!StrictlyEqual(cx, lref, rref, &equal)) \ if (!StrictlyEqual(cx, lref, rref, &equal)) \
goto error; \ goto error; \
COND = equal OP true; \ (COND) = equal OP true; \
regs.sp--; \ regs.sp--; \
JS_END_MACRO JS_END_MACRO

Просмотреть файл

@ -14,6 +14,7 @@
#include "jsfriendapi.h" #include "jsfriendapi.h"
#include "jsinfer.h" #include "jsinfer.h"
#include "NamespaceImports.h"
#include "gc/Barrier.h" #include "gc/Barrier.h"
#include "gc/Heap.h" #include "gc/Heap.h"

Просмотреть файл

@ -9,7 +9,6 @@
#include "mozilla/Endian.h" #include "mozilla/Endian.h"
#include "jsapi.h"
#include "jsatom.h" #include "jsatom.h"
namespace js { namespace js {

Просмотреть файл

@ -36,6 +36,7 @@
#include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BindingUtils.h"
using namespace mozilla; using namespace mozilla;
using namespace JS;
using namespace js; using namespace js;
using namespace xpc; using namespace xpc;

Просмотреть файл

@ -41,6 +41,7 @@
#include "nsGlobalWindow.h" #include "nsGlobalWindow.h"
using namespace mozilla; using namespace mozilla;
using namespace JS;
using namespace js; using namespace js;
using namespace xpc; using namespace xpc;
@ -3714,7 +3715,7 @@ nsXPCComponents::AttachComponentsObject(JSContext* aCx,
MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx)); MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx));
RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)); RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
return JS_DefinePropertyById(aCx, global, id, js::ObjectValue(*components), return JS_DefinePropertyById(aCx, global, id, JS::ObjectValue(*components),
nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY); nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
} }

Просмотреть файл

@ -24,6 +24,7 @@
#include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BindingUtils.h"
using namespace mozilla; using namespace mozilla;
using namespace JS;
using namespace js; using namespace js;
namespace xpc { namespace xpc {

Просмотреть файл

@ -15,6 +15,7 @@
#include "jsapi.h" #include "jsapi.h"
using namespace JS;
using namespace js; using namespace js;
namespace xpc { namespace xpc {

Просмотреть файл

@ -20,6 +20,7 @@
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
using namespace JS;
using namespace js; using namespace js;
using namespace mozilla; using namespace mozilla;

Просмотреть файл

@ -66,17 +66,6 @@ public:
return 0; return 0;
} }
#if defined(MOZ_ANDROID_SONY_WORKAROUND)
private:
// Sony ICS devices have extra virtual methods in DataSource.
// The dummy methods below fill these vtable positions.
virtual void foo1() { abort(); }
virtual void foo2() { abort(); }
virtual void foo3() { abort(); }
virtual void foo4() { abort(); }
public:
#endif
virtual status_t reconnectAtOffset(off64_t offset) { virtual status_t reconnectAtOffset(off64_t offset) {
return ERROR_UNSUPPORTED; return ERROR_UNSUPPORTED;
} }

Просмотреть файл

@ -20,22 +20,4 @@ index 81ef632..713af92 100644
public: public:
enum Flags { enum Flags {
kWantsPrefetching = 1, kWantsPrefetching = 1,
@@ -66,17 +62,6 @@ public:
return 0;
}
-#if defined(MOZ_ANDROID_SONY_WORKAROUND)
-private:
- // Sony ICS devices have extra virtual methods in DataSource.
- // The dummy methods below fill these vtable positions.
- virtual void foo1() { abort(); }
- virtual void foo2() { abort(); }
- virtual void foo3() { abort(); }
- virtual void foo4() { abort(); }
-public:
-#endif
-
virtual status_t reconnectAtOffset(off64_t offset) {
return ERROR_UNSUPPORTED;
}

Просмотреть файл

@ -1,60 +0,0 @@
# Copyright 2012 Mozilla Foundation and Mozilla contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE_NAME = omxpluginjb-htc
FORCE_SHARED_LIB = 1
# Don't use STL wrappers; this isn't Gecko code
STL_FLAGS =
# must link statically with the CRT; this isn't Gecko code
USE_STATIC_LIBS = 1
# Need to custom install OMX media plugin
NO_INSTALL = 1
include $(topsrcdir)/config/rules.mk
ifdef GNU_CXX
# Turn off C++ 11 features due to conflicts with Android OS headers and char16_t definition
CXXFLAGS += -std=gnu++98
endif
INCLUDES += \
-I$(srcdir)/../../../content/media/plugins \
$(NULL)
EXTRA_DSO_LDOPTS += \
-L$(DEPTH)/media/omx-plugin/lib/ics/libutils \
-lutils \
-L$(DEPTH)/media/omx-plugin/lib/ics/libstagefright \
-lstagefright \
$(NULL)
INCLUDES += \
-I$(srcdir)/../include/ics \
-I$(srcdir)/../include/ics/media/stagefright/openmax \
$(NULL)
libs:: $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
$(INSTALL) $< $(DEPTH)/dist/bin
libs:: $(PROGRAMS)

Просмотреть файл

@ -1,9 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#define MOZ_STAGEFRIGHT_OFF_T off64_t
#define MOZ_ANDROID_ICS
#define MOZ_ANDROID_HTC_WORKAROUND
#include "../OmxPlugin.cpp"

Просмотреть файл

@ -1,15 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
MODULE = 'omxpluginjb-htc'
NO_DIST_INSTALL = True
CPP_SOURCES += [
'OmxPluginJB-HTC.cpp',
]
LIBRARY_NAME = 'omxpluginjb-htc'

Просмотреть файл

@ -1,60 +0,0 @@
# Copyright 2012 Mozilla Foundation and Mozilla contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE_NAME = omxpluginsony
FORCE_SHARED_LIB = 1
# Don't use STL wrappers; this isn't Gecko code
STL_FLAGS =
# must link statically with the CRT; this isn't Gecko code
USE_STATIC_LIBS = 1
# Need to custom install OMX media plugin
NO_INSTALL = 1
include $(topsrcdir)/config/rules.mk
ifdef GNU_CXX
# Turn off C++ 11 features due to conflicts with Android OS headers and char16_t definition
CXXFLAGS += -std=gnu++98
endif
INCLUDES += \
-I$(srcdir)/../../../content/media/plugins \
$(NULL)
EXTRA_DSO_LDOPTS += \
-L$(DEPTH)/media/omx-plugin/lib/ics/libutils \
-lutils \
-L$(DEPTH)/media/omx-plugin/lib/ics/libstagefright \
-lstagefright \
$(NULL)
INCLUDES += \
-I$(srcdir)/../include/ics \
-I$(srcdir)/../include/ics/media/stagefright/openmax \
$(NULL)
libs:: $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
$(INSTALL) $< $(DEPTH)/dist/bin
libs:: $(PROGRAMS)

Просмотреть файл

@ -1,10 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#define MOZ_STAGEFRIGHT_OFF_T off64_t
#define MOZ_ANDROID_GB
#define MOZ_ANDROID_HC
#include <ui/egl/android_natives.h>
#include "../OmxPlugin.cpp"

Просмотреть файл

@ -1,9 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#define MOZ_STAGEFRIGHT_OFF_T off64_t
#define MOZ_ANDROID_ICS
#define MOZ_ANDROID_SONY_WORKAROUND
#include "../OmxPlugin.cpp"

Просмотреть файл

@ -1,15 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
MODULE = 'omxpluginsony'
NO_DIST_INSTALL = True
CPP_SOURCES += [
'OmxPluginSony.cpp',
]
LIBRARY_NAME = 'omxpluginsony'

Просмотреть файл

@ -8,6 +8,11 @@
#include <math.h> #include <math.h>
using mozilla::DoublesAreIdentical; using mozilla::DoublesAreIdentical;
using mozilla::IsFinite;
using mozilla::IsInfinite;
using mozilla::IsNaN;
using mozilla::IsNegative;
using mozilla::IsNegativeZero;
using mozilla::NegativeInfinity; using mozilla::NegativeInfinity;
using mozilla::PositiveInfinity; using mozilla::PositiveInfinity;
using mozilla::SpecificNaN; using mozilla::SpecificNaN;
@ -97,8 +102,54 @@ TestDoublesAreIdentical()
ShouldNotBeIdentical(UnspecifiedNaN(), NegativeInfinity()); ShouldNotBeIdentical(UnspecifiedNaN(), NegativeInfinity());
} }
static void
TestPredicates()
{
MOZ_ASSERT(IsNaN(UnspecifiedNaN()));
MOZ_ASSERT(IsNaN(SpecificNaN(1, 17)));;
MOZ_ASSERT(IsNaN(SpecificNaN(0, 0xfffffffffff0fULL)));
MOZ_ASSERT(!IsNaN(0));
MOZ_ASSERT(!IsNaN(-0.0));
MOZ_ASSERT(!IsNaN(1.0));
MOZ_ASSERT(!IsNaN(PositiveInfinity()));
MOZ_ASSERT(!IsNaN(NegativeInfinity()));
MOZ_ASSERT(IsInfinite(PositiveInfinity()));
MOZ_ASSERT(IsInfinite(NegativeInfinity()));
MOZ_ASSERT(!IsInfinite(UnspecifiedNaN()));
MOZ_ASSERT(!IsInfinite(0));
MOZ_ASSERT(!IsInfinite(-0.0));
MOZ_ASSERT(!IsInfinite(1.0));
MOZ_ASSERT(!IsFinite(PositiveInfinity()));
MOZ_ASSERT(!IsFinite(NegativeInfinity()));
MOZ_ASSERT(!IsFinite(UnspecifiedNaN()));
MOZ_ASSERT(IsFinite(0));
MOZ_ASSERT(IsFinite(-0.0));
MOZ_ASSERT(IsFinite(1.0));
MOZ_ASSERT(!IsNegative(PositiveInfinity()));
MOZ_ASSERT(IsNegative(NegativeInfinity()));
MOZ_ASSERT(IsNegative(-0.0));
MOZ_ASSERT(!IsNegative(0.0));
MOZ_ASSERT(IsNegative(-1.0));
MOZ_ASSERT(!IsNegative(1.0));
MOZ_ASSERT(!IsNegativeZero(PositiveInfinity()));
MOZ_ASSERT(!IsNegativeZero(NegativeInfinity()));
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 17)));;
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 0xfffffffffff0fULL)));
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 17)));;
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 0xfffffffffff0fULL)));
MOZ_ASSERT(IsNegativeZero(-0.0));
MOZ_ASSERT(!IsNegativeZero(0.0));
MOZ_ASSERT(!IsNegativeZero(-1.0));
MOZ_ASSERT(!IsNegativeZero(1.0));
}
int int
main() main()
{ {
TestDoublesAreIdentical(); TestDoublesAreIdentical();
TestPredicates();
} }

Просмотреть файл

@ -44,8 +44,6 @@
@BINPATH@/@DLL_PREFIX@omxplugingb@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxplugingb@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxplugingb235@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxplugingb235@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxpluginhc@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxpluginhc@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxpluginjb-htc@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxpluginsony@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxpluginfroyo@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxpluginfroyo@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@

Просмотреть файл

@ -118,17 +118,21 @@ class TreeMetadataEmitter(LoggingMixin):
CPP_UNIT_TESTS='CPP_UNIT_TESTS', CPP_UNIT_TESTS='CPP_UNIT_TESTS',
CSRCS='CSRCS', CSRCS='CSRCS',
DEFINES='DEFINES', DEFINES='DEFINES',
EXPORT_LIBRARY='EXPORT_LIBRARY',
EXTRA_COMPONENTS='EXTRA_COMPONENTS', EXTRA_COMPONENTS='EXTRA_COMPONENTS',
EXTRA_JS_MODULES='EXTRA_JS_MODULES', EXTRA_JS_MODULES='EXTRA_JS_MODULES',
EXTRA_PP_COMPONENTS='EXTRA_PP_COMPONENTS', EXTRA_PP_COMPONENTS='EXTRA_PP_COMPONENTS',
EXTRA_PP_JS_MODULES='EXTRA_PP_JS_MODULES', EXTRA_PP_JS_MODULES='EXTRA_PP_JS_MODULES',
FAIL_ON_WARNINGS='FAIL_ON_WARNINGS', FAIL_ON_WARNINGS='FAIL_ON_WARNINGS',
FORCE_SHARED_LIB='FORCE_SHARED_LIB',
FORCE_STATIC_LIB='FORCE_STATIC_LIB',
GTEST_CMMSRCS='GTEST_CMM_SOURCES', GTEST_CMMSRCS='GTEST_CMM_SOURCES',
GTEST_CPPSRCS='GTEST_CPP_SOURCES', GTEST_CPPSRCS='GTEST_CPP_SOURCES',
GTEST_CSRCS='GTEST_C_SOURCES', GTEST_CSRCS='GTEST_C_SOURCES',
HOST_CPPSRCS='HOST_CPPSRCS', HOST_CPPSRCS='HOST_CPPSRCS',
HOST_CSRCS='HOST_CSRCS', HOST_CSRCS='HOST_CSRCS',
HOST_LIBRARY_NAME='HOST_LIBRARY_NAME', HOST_LIBRARY_NAME='HOST_LIBRARY_NAME',
IS_COMPONENT='IS_COMPONENT',
JS_MODULES_PATH='JS_MODULES_PATH', JS_MODULES_PATH='JS_MODULES_PATH',
LIBRARY_NAME='LIBRARY_NAME', LIBRARY_NAME='LIBRARY_NAME',
LIBS='LIBS', LIBS='LIBS',

Просмотреть файл

@ -98,6 +98,10 @@ VARIABLES = {
delimiters. delimiters.
"""), """),
'EXPORT_LIBRARY': (bool, bool, False,
"""Install the library to the static libraries folder.
"""),
'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list, [], 'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list, [],
"""Additional component files to distribute. """Additional component files to distribute.
@ -138,6 +142,14 @@ VARIABLES = {
"""Whether to treat warnings as errors. """Whether to treat warnings as errors.
"""), """),
'FORCE_SHARED_LIB': (bool, bool, False,
"""Whether the library in this directory is a shared library.
"""),
'FORCE_STATIC_LIB': (bool, bool, False,
"""Whether the library in this directory is a static library.
"""),
'GTEST_C_SOURCES': (StrictOrderingOnAppendList, list, [], 'GTEST_C_SOURCES': (StrictOrderingOnAppendList, list, [],
"""C code source files for GTest unit tests. """C code source files for GTest unit tests.
@ -171,6 +183,10 @@ VARIABLES = {
This variable contains a list of C source files to compile. This variable contains a list of C source files to compile.
"""), """),
'IS_COMPONENT': (bool, bool, False,
"""Whether the library contains a binary XPCOM component manifest.
"""),
'PARALLEL_DIRS': (list, list, [], 'PARALLEL_DIRS': (list, list, [],
"""A parallel version of DIRS. """A parallel version of DIRS.
@ -212,7 +228,7 @@ VARIABLES = {
'LIBXUL_LIBRARY': (bool, bool, False, 'LIBXUL_LIBRARY': (bool, bool, False,
"""Whether the library in this directory is linked into libxul. """Whether the library in this directory is linked into libxul.
Implies MOZILLA_INTERNAL_API. Implies MOZILLA_INTERNAL_API and FORCE_STATIC_LIB.
"""), """),
'MSVC_ENABLE_PGO': (bool, bool, False, 'MSVC_ENABLE_PGO': (bool, bool, False,

Просмотреть файл

@ -45,3 +45,8 @@ LIBXUL_LIBRARY = True
MSVC_ENABLE_PGO = True MSVC_ENABLE_PGO = True
NO_DIST_INSTALL = True NO_DIST_INSTALL = True
FORCE_SHARED_LIB = True
FORCE_STATIC_LIB = True
EXPORT_LIBRARY = True
IS_COMPONENT = True

Просмотреть файл

@ -132,17 +132,21 @@ class TestEmitterBasic(unittest.TestCase):
CSRCS=['fans.c', 'tans.c'], CSRCS=['fans.c', 'tans.c'],
CPP_UNIT_TESTS=['foo.cpp'], CPP_UNIT_TESTS=['foo.cpp'],
DEFINES=['-Dfans', '-Dtans'], DEFINES=['-Dfans', '-Dtans'],
EXPORT_LIBRARY=True,
EXTRA_COMPONENTS=['fans.js', 'tans.js'], EXTRA_COMPONENTS=['fans.js', 'tans.js'],
EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'], EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'],
EXTRA_JS_MODULES=['bar.jsm', 'foo.jsm'], EXTRA_JS_MODULES=['bar.jsm', 'foo.jsm'],
EXTRA_PP_JS_MODULES=['bar.pp.jsm', 'foo.pp.jsm'], EXTRA_PP_JS_MODULES=['bar.pp.jsm', 'foo.pp.jsm'],
FAIL_ON_WARNINGS=True, FAIL_ON_WARNINGS=True,
FORCE_SHARED_LIB=True,
FORCE_STATIC_LIB=True,
GTEST_CSRCS=['test1.c', 'test2.c'], GTEST_CSRCS=['test1.c', 'test2.c'],
GTEST_CMMSRCS=['test1.mm', 'test2.mm'], GTEST_CMMSRCS=['test1.mm', 'test2.mm'],
GTEST_CPPSRCS=['test1.cpp', 'test2.cpp'], GTEST_CPPSRCS=['test1.cpp', 'test2.cpp'],
HOST_CPPSRCS=['fans.cpp', 'tans.cpp'], HOST_CPPSRCS=['fans.cpp', 'tans.cpp'],
HOST_CSRCS=['fans.c', 'tans.c'], HOST_CSRCS=['fans.c', 'tans.c'],
HOST_LIBRARY_NAME='host_fans', HOST_LIBRARY_NAME='host_fans',
IS_COMPONENT=True,
LIBRARY_NAME='lib_name', LIBRARY_NAME='lib_name',
LIBS=['fans.lib', 'tans.lib'], LIBS=['fans.lib', 'tans.lib'],
LIBXUL_LIBRARY=True, LIBXUL_LIBRARY=True,

Просмотреть файл

@ -184,15 +184,15 @@ function _do_quit() {
} }
function _format_exception_stack(stack) { function _format_exception_stack(stack) {
// frame is of the form "fname(args)@file:line" // frame is of the form "fname@file:line"
let frame_regexp = new RegExp("(.*)\\(.*\\)@(.*):(\\d*)", "g"); let frame_regexp = new RegExp("(.*)@(.*):(\\d*)", "g");
return stack.split("\n").reduce(function(stack_msg, frame) { return stack.split("\n").reduce(function(stack_msg, frame) {
if (frame) { if (frame) {
let parts = frame_regexp.exec(frame); let parts = frame_regexp.exec(frame);
if (parts) { if (parts) {
return stack_msg + "JS frame :: " + parts[2] + " :: " + let [ _, func, file, line ] = parts;
(parts[1] ? parts[1] : "anonymous") + return stack_msg + "JS frame :: " + file + " :: " +
" :: line " + parts[3] + "\n"; (func || "anonymous") + " :: line " + line + "\n";
} }
else { /* Could be a -e (command line string) style location. */ else { /* Could be a -e (command line string) style location. */
return stack_msg + "JS frame :: " + frame + "\n"; return stack_msg + "JS frame :: " + frame + "\n";

Просмотреть файл

@ -345,7 +345,7 @@ INNER_ROBOCOP_PACKAGE=echo 'Testing is disabled - No Robocop for you'
endif endif
ifdef MOZ_OMX_PLUGIN ifdef MOZ_OMX_PLUGIN
DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginsony.so libomxpluginfroyo.so libomxpluginjb-htc.so DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginfroyo.so
endif endif
SO_LIBRARIES := $(filter %.so,$(DIST_FILES)) SO_LIBRARIES := $(filter %.so,$(DIST_FILES))

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше