Merge from mozilla-central to mozilla-inbound

This commit is contained in:
Matt Brubeck 2012-12-27 14:53:29 -08:00
commit 6cc14fe75a
12 changed files with 60 additions and 183 deletions

View File

@ -178,6 +178,9 @@ NS_IMETHODIMP
nsDOMFileBase::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
{
NS_ASSERTION(mIsFile, "Should only be called on files");
if (IsDateUnknown()) {
mLastModificationDate = PR_Now();
}
*aLastModifiedDate = mLastModificationDate;
return NS_OK;
}
@ -489,7 +492,6 @@ nsDOMFileFile::GetLastModifiedDate(JSContext* cx, JS::Value* aLastModifiedDate)
NS_ASSERTION(mIsFile, "Should only be called on files");
PRTime msecs;
mFile->GetLastModifiedTime(&msecs);
if (IsDateUnknown()) {
nsresult rv = mFile->GetLastModifiedTime(&msecs);
NS_ENSURE_SUCCESS(rv, rv);
@ -562,6 +564,12 @@ NS_IMETHODIMP
nsDOMFileFile::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
{
NS_ASSERTION(mIsFile, "Should only be called on files");
if (IsDateUnknown()) {
PRTime msecs;
nsresult rv = mFile->GetLastModifiedTime(&msecs);
NS_ENSURE_SUCCESS(rv, rv);
mLastModificationDate = msecs;
}
*aLastModifiedDate = mLastModificationDate;
return NS_OK;
}

View File

@ -933,7 +933,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
{ \
vx = v.vector[0]; \
repeat (PIXMAN_REPEAT_NORMAL, &vx, pixman_int_to_fixed(src_image->bits.width)); \
max_x = pixman_fixed_to_int (vx + (width - 1) * unit_x) + 1; \
max_x = pixman_fixed_to_int (vx + (width - 1) * (int64_t)unit_x) + 1; \
\
if (src_image->bits.width < REPEAT_NORMAL_MIN_WIDTH) \
{ \

View File

@ -114,7 +114,7 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString string, MatchPairs &matc
}
RegExpRunStatus
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re, RegExpObject &regexp,
JSLinearString *input, StableCharPtr chars, size_t length,
size_t *lastIndex, MatchConduit &matches)
{
@ -126,7 +126,7 @@ ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
/* Only one MatchPair slot provided: execute short-circuiting regexp. */
status = re.executeMatchOnly(cx, chars, length, lastIndex, *matches.u.pair);
if (status == RegExpRunStatus_Success && res)
res->updateLazily(cx, input, &re, lastIndex_orig);
res->updateLazily(cx, input, &regexp, lastIndex_orig);
} else {
/* Vector of MatchPairs provided: execute full regexp. */
status = re.execute(cx, chars, length, lastIndex, *matches.u.pairs);
@ -151,7 +151,7 @@ js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
MatchConduit conduit(&matches);
RegExpRunStatus status =
ExecuteRegExpImpl(cx, res, *shared, input, chars, length, lastIndex, conduit);
ExecuteRegExpImpl(cx, res, *shared, reobj, input, chars, length, lastIndex, conduit);
if (status == RegExpRunStatus_Error)
return false;
@ -591,7 +591,7 @@ js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string, Match
/* Steps 8-21. */
size_t lastIndexInt(i);
RegExpRunStatus status =
ExecuteRegExpImpl(cx, res, *re, stableInput, chars, length, &lastIndexInt, matches);
ExecuteRegExpImpl(cx, res, *re, *reobj, stableInput, chars, length, &lastIndexInt, matches);
if (status == RegExpRunStatus_Error)
return RegExpRunStatus_Error;

View File

@ -332,6 +332,7 @@ DeclMarkerImpl(Object, DebugScopeObject)
DeclMarkerImpl(Object, GlobalObject)
DeclMarkerImpl(Object, JSObject)
DeclMarkerImpl(Object, JSFunction)
DeclMarkerImpl(Object, RegExpObject)
DeclMarkerImpl(Object, ScopeObject)
DeclMarkerImpl(Script, JSScript)
DeclMarkerImpl(Shape, Shape)

View File

@ -97,6 +97,7 @@ DeclMarker(Object, DebugScopeObject)
DeclMarker(Object, GlobalObject)
DeclMarker(Object, JSObject)
DeclMarker(Object, JSFunction)
DeclMarker(Object, RegExpObject)
DeclMarker(Object, ScopeObject)
DeclMarker(Script, JSScript)
DeclMarker(Shape, Shape)

View File

@ -674,6 +674,9 @@ Shape::Range::AutoRooter::trace(JSTracer *trc)
void
RegExpStatics::AutoRooter::trace(JSTracer *trc)
{
if (statics->regexp)
MarkObjectRoot(trc, reinterpret_cast<JSObject**>(&statics->regexp),
"RegExpStatics::AutoRooter regexp");
if (statics->matchesInput)
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchesInput),
"RegExpStatics::AutoRooter matchesInput");

View File

@ -2308,114 +2308,6 @@ BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *reps
return true;
}
struct StringRange
{
size_t start;
size_t length;
StringRange(size_t s, size_t l)
: start(s), length(l)
{ }
};
static JSString *
AppendSubstrings(JSContext *cx, Handle<JSStableString*> stableStr,
const StringRange *ranges, size_t rangesLen)
{
JS_ASSERT(rangesLen);
/* For single substrings, construct a dependent string. */
if (rangesLen == 1)
return js_NewDependentString(cx, stableStr, ranges[0].start, ranges[0].length);
/* Collect substrings into a rope. */
RopeBuilder rope(cx);
for (size_t i = 0; i < rangesLen; i++) {
const StringRange &sr = ranges[i];
RootedString substr(cx, js_NewDependentString(cx, stableStr, sr.start, sr.length));
if (!substr)
return NULL;
/* Appending to the rope permanently roots the substring. */
rope.append(substr);
}
return rope.result();
}
static bool
str_replace_regexp_remove(JSContext *cx, CallArgs args, HandleString str, RegExpShared &re)
{
Rooted<JSStableString*> stableStr(cx, str->ensureStable(cx));
if (!stableStr)
return false;
Vector<StringRange, 16, SystemAllocPolicy> ranges;
StableCharPtr chars = stableStr->chars();
size_t charsLen = stableStr->length();
MatchPair match;
size_t startIndex = 0; /* Index used for iterating through the string. */
size_t lastIndex = 0; /* Index after last successful match. */
/* Accumulate StringRanges for unmatched substrings. */
while (startIndex <= charsLen) {
if (!JS_CHECK_OPERATION_LIMIT(cx))
return false;
RegExpRunStatus status = re.executeMatchOnly(cx, chars, charsLen, &startIndex, match);
if (status == RegExpRunStatus_Error)
return false;
if (status == RegExpRunStatus_Success_NotFound)
break;
/* Include the latest unmatched substring. */
if (size_t(match.start) > lastIndex) {
if (!ranges.append(StringRange(lastIndex, match.start - lastIndex)))
return false;
}
lastIndex = startIndex;
/* Non-global removal executes at most once. */
if (!re.global())
break;
if (match.isEmpty())
startIndex++;
}
/* If unmatched, return the input string. */
if (!lastIndex) {
args.rval().setString(str);
return true;
}
/* The last successful match updates the RegExpStatics. */
cx->regExpStatics()->updateLazily(cx, stableStr, &re, lastIndex);
/* Include any remaining part of the string. */
if (lastIndex < charsLen) {
if (!ranges.append(StringRange(lastIndex, charsLen - lastIndex)))
return false;
}
/* Handle the empty string before calling .begin(). */
if (ranges.empty()) {
args.rval().setString(cx->runtime->emptyString);
return true;
}
JSString *result = AppendSubstrings(cx, stableStr, ranges.begin(), ranges.length());
if (!result)
return false;
args.rval().setString(result);
return true;
}
static inline bool
str_replace_regexp(JSContext *cx, CallArgs args, ReplaceData &rdata)
{
@ -2428,12 +2320,6 @@ str_replace_regexp(JSContext *cx, CallArgs args, ReplaceData &rdata)
RegExpStatics *res = cx->regExpStatics();
RegExpShared &re = rdata.g.regExp();
/* Optimize removal. */
if (rdata.repstr && rdata.repstr->length() == 0 && !rdata.dollar) {
JS_ASSERT(!rdata.lambda && !rdata.elembase);
return str_replace_regexp_remove(cx, args, rdata.str, re);
}
Value tmp;
if (!DoMatch(cx, res, rdata.str, re, ReplaceRegExpCallback, &rdata, REPLACE_ARGS, &tmp))
return false;

View File

@ -645,18 +645,6 @@ RegExpCompartment::RegExpCompartment(JSRuntime *rt)
RegExpCompartment::~RegExpCompartment()
{
JS_ASSERT(map_.empty());
/*
* RegExpStatics may have prevented a single RegExpShared from
* being collected during RegExpCompartment::sweep().
*/
if (!inUse_.empty()) {
PendingSet::Enum e(inUse_);
RegExpShared *shared = e.front();
JS_ASSERT(shared->activeUseCount == 0);
js_delete(shared);
e.removeFront();
}
JS_ASSERT(inUse_.empty());
}

View File

@ -198,31 +198,22 @@ class RegExpShared
class RegExpGuard
{
RegExpShared *re_;
private:
RegExpGuard(const RegExpGuard &) MOZ_DELETE;
void operator=(const RegExpGuard &) MOZ_DELETE;
public:
RegExpGuard() : re_(NULL) {}
RegExpGuard(RegExpShared &re) : re_(&re) {
re_->incRef();
}
~RegExpGuard() { release(); }
public:
void init(RegExpShared &re) {
JS_ASSERT(!initialized());
JS_ASSERT(!re_);
re_ = &re;
re_->incRef();
}
void release() {
if (re_) {
~RegExpGuard() {
if (re_)
re_->decRef();
re_ = NULL;
}
}
bool initialized() const { return !!re_; }
RegExpShared *re() const { JS_ASSERT(initialized()); return re_; }
RegExpShared *operator->() { return re(); }
@ -234,12 +225,9 @@ class RegExpCompartment
struct Key {
JSAtom *atom;
uint16_t flag;
Key() {}
Key(JSAtom *atom, RegExpFlag flag)
: atom(atom), flag(flag)
{ }
: atom(atom), flag(flag) {}
typedef Key Lookup;
static HashNumber hash(const Lookup &l) {
return DefaultHasher<JSAtom *>::hash(l.atom) ^ (l.flag << 1);

View File

@ -27,6 +27,15 @@ SizeOfRegExpStaticsData(const JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
return mallocSizeOf(obj->getPrivate());
}
inline
RegExpStatics::RegExpStatics()
: pendingLazyEvaluation(false),
bufferLink(NULL),
copied(false)
{
clear();
}
inline bool
RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out)
{
@ -222,20 +231,15 @@ RegExpStatics::copyTo(RegExpStatics &dst)
if (!pendingLazyEvaluation)
dst.matches.initArrayFrom(matches);
if (regexpGuard.initialized())
dst.regexpGuard.init(*regexpGuard);
else
dst.regexpGuard.release();
dst.matchesInput = matchesInput;
dst.regexp = regexp;
dst.lastIndex = lastIndex;
dst.pendingInput = pendingInput;
dst.flags = flags;
dst.pendingLazyEvaluation = pendingLazyEvaluation;
JS_ASSERT_IF(pendingLazyEvaluation, regexpGuard.initialized());
JS_ASSERT_IF(pendingLazyEvaluation, regexp);
JS_ASSERT_IF(pendingLazyEvaluation, matchesInput);
JS_ASSERT(regexpGuard.initialized() == dst.regexpGuard.initialized());
}
inline void
@ -257,20 +261,17 @@ RegExpStatics::restore()
inline void
RegExpStatics::updateLazily(JSContext *cx, JSLinearString *input,
RegExpShared *shared, size_t lastIndex)
RegExpObject *regexp, size_t lastIndex)
{
JS_ASSERT(input && shared);
JS_ASSERT(input && regexp);
aboutToWrite();
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
pendingInput, input,
matchesInput, input);
if (regexpGuard.initialized())
regexpGuard.release();
regexpGuard.init(*shared);
this->lastIndex = lastIndex;
pendingLazyEvaluation = true;
this->regexp = regexp;
this->lastIndex = lastIndex;
}
inline bool
@ -281,7 +282,7 @@ RegExpStatics::updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchP
/* Unset all lazy state. */
pendingLazyEvaluation = false;
this->regexpGuard.release();
this->regexp = NULL;
this->lastIndex = size_t(-1);
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
@ -300,14 +301,11 @@ inline void
RegExpStatics::clear()
{
aboutToWrite();
matches.forgetArray();
matchesInput = NULL;
regexpGuard.release();
lastIndex = size_t(-1);
pendingInput = NULL;
flags = RegExpFlag(0);
pendingInput = NULL;
pendingLazyEvaluation = false;
matchesInput = NULL;
matches.forgetArray();
}
inline void
@ -365,9 +363,8 @@ RegExpStatics::checkInvariants()
{
#ifdef DEBUG
if (pendingLazyEvaluation) {
JS_ASSERT(regexpGuard.initialized());
JS_ASSERT(regexp);
JS_ASSERT(pendingInput);
JS_ASSERT(lastIndex != size_t(-1));
return;
}

View File

@ -74,7 +74,7 @@ RegExpStatics::executeLazy(JSContext *cx)
if (!pendingLazyEvaluation)
return true;
JS_ASSERT(regexpGuard.initialized());
JS_ASSERT(regexp);
JS_ASSERT(matchesInput);
JS_ASSERT(lastIndex != size_t(-1));
@ -87,14 +87,17 @@ RegExpStatics::executeLazy(JSContext *cx)
StableCharPtr chars(matchesInput->chars(), length);
/* Execute the full regular expression. */
RegExpRunStatus status = regexpGuard->execute(cx, chars, length, &this->lastIndex, this->matches);
RegExpGuard shared;
if (!regexp->getShared(cx, &shared))
return false;
RegExpRunStatus status = shared->execute(cx, chars, length, &this->lastIndex, this->matches);
if (status == RegExpRunStatus_Error)
return false;
/* Unset lazy state and remove rooted values that now have no use. */
pendingLazyEvaluation = false;
regexpGuard.release();
lastIndex = size_t(-1);
regexp = NULL;
return true;
}

View File

@ -15,7 +15,6 @@
#include "js/Vector.h"
#include "vm/MatchPairs.h"
#include "vm/RegExpObject.h"
namespace js {
@ -26,7 +25,7 @@ class RegExpStatics
HeapPtr<JSLinearString> matchesInput;
/* The previous RegExp input, used to resolve lazy state. */
RegExpGuard regexpGuard; /* Strong reference to RegExpShared. */
HeapPtr<RegExpObject> regexp;
size_t lastIndex;
/* The latest RegExp input, set before execution. */
@ -34,7 +33,7 @@ class RegExpStatics
RegExpFlag flags;
/*
* If true, |matchesInput|, |regexpGuard|, and |lastIndex| may be used
* If true, |matchesInput|, |regexp|, and |lastIndex| may be used
* to replay the last executed RegExp, and |matches| is invalid.
*/
bool pendingLazyEvaluation;
@ -43,10 +42,6 @@ class RegExpStatics
RegExpStatics *bufferLink;
bool copied;
public:
RegExpStatics() : bufferLink(NULL), copied(false) { clear(); }
static JSObject *create(JSContext *cx, GlobalObject *parent);
private:
bool executeLazy(JSContext *cx);
@ -83,9 +78,14 @@ class RegExpStatics
friend class PreserveRegExpStatics;
public:
inline RegExpStatics();
static JSObject *create(JSContext *cx, GlobalObject *parent);
/* Mutators. */
inline void updateLazily(JSContext *cx, JSLinearString *input,
RegExpShared *shared, size_t lastIndex);
RegExpObject *regexp, size_t lastIndex);
inline bool updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs &newPairs);
inline void setMultiline(JSContext *cx, bool enabled);
@ -118,6 +118,8 @@ class RegExpStatics
}
void mark(JSTracer *trc) {
if (regexp)
gc::MarkObject(trc, &regexp, "res->regexp");
if (pendingInput)
MarkString(trc, &pendingInput, "res->pendingInput");
if (matchesInput)