mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1128528 - Don't unnecessarily require flat strings, to avoid wasting a ton of memory in pathological cases. r=luke
This commit is contained in:
parent
bc70f6c592
commit
0317fb9ab5
@ -191,7 +191,7 @@ ParseEvalStringAsJSON(JSContext *cx, const mozilla::Range<const CharT> chars, Mu
|
||||
}
|
||||
|
||||
static EvalJSONResult
|
||||
TryEvalJSON(JSContext *cx, JSFlatString *str, MutableHandleValue rval)
|
||||
TryEvalJSON(JSContext *cx, JSLinearString *str, MutableHandleValue rval)
|
||||
{
|
||||
if (str->hasLatin1Chars()) {
|
||||
AutoCheckCannotGC nogc;
|
||||
@ -203,13 +203,13 @@ TryEvalJSON(JSContext *cx, JSFlatString *str, MutableHandleValue rval)
|
||||
return EvalJSON_NotJSON;
|
||||
}
|
||||
|
||||
AutoStableStringChars flatChars(cx);
|
||||
if (!flatChars.init(cx, str))
|
||||
AutoStableStringChars linearChars(cx);
|
||||
if (!linearChars.init(cx, str))
|
||||
return EvalJSON_Failure;
|
||||
|
||||
return flatChars.isLatin1()
|
||||
? ParseEvalStringAsJSON(cx, flatChars.latin1Range(), rval)
|
||||
: ParseEvalStringAsJSON(cx, flatChars.twoByteRange(), rval);
|
||||
return linearChars.isLatin1()
|
||||
? ParseEvalStringAsJSON(cx, linearChars.latin1Range(), rval)
|
||||
: ParseEvalStringAsJSON(cx, linearChars.twoByteRange(), rval);
|
||||
}
|
||||
|
||||
// Define subset of ExecuteType so that casting performs the injection.
|
||||
@ -277,19 +277,19 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
|
||||
thisv = ObjectValue(*thisobj);
|
||||
}
|
||||
|
||||
Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx));
|
||||
if (!flatStr)
|
||||
RootedLinearString linearStr(cx, str->ensureLinear(cx));
|
||||
if (!linearStr)
|
||||
return false;
|
||||
|
||||
RootedScript callerScript(cx, caller ? caller.script() : nullptr);
|
||||
EvalJSONResult ejr = TryEvalJSON(cx, flatStr, args.rval());
|
||||
EvalJSONResult ejr = TryEvalJSON(cx, linearStr, args.rval());
|
||||
if (ejr != EvalJSON_NotJSON)
|
||||
return ejr == EvalJSON_Success;
|
||||
|
||||
EvalScriptGuard esg(cx);
|
||||
|
||||
if (evalType == DIRECT_EVAL && caller.isNonEvalFunctionFrame())
|
||||
esg.lookupInEvalCache(flatStr, callerScript, pc);
|
||||
esg.lookupInEvalCache(linearStr, callerScript, pc);
|
||||
|
||||
if (!esg.foundScript()) {
|
||||
RootedScript maybeScript(cx);
|
||||
@ -323,18 +323,18 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
|
||||
.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
|
||||
.maybeMakeStrictMode(evalType == DIRECT_EVAL && IsStrictEvalPC(pc));
|
||||
|
||||
AutoStableStringChars flatChars(cx);
|
||||
if (!flatChars.initTwoByte(cx, flatStr))
|
||||
AutoStableStringChars linearChars(cx);
|
||||
if (!linearChars.initTwoByte(cx, linearStr))
|
||||
return false;
|
||||
|
||||
const char16_t *chars = flatChars.twoByteRange().start().get();
|
||||
SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller()
|
||||
const char16_t *chars = linearChars.twoByteRange().start().get();
|
||||
SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller()
|
||||
? SourceBufferHolder::GiveOwnership
|
||||
: SourceBufferHolder::NoOwnership;
|
||||
SourceBufferHolder srcBuf(chars, flatStr->length(), ownership);
|
||||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||
JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||
scopeobj, callerScript, staticScope,
|
||||
options, srcBuf, flatStr, staticLevel);
|
||||
options, srcBuf, linearStr, staticLevel);
|
||||
if (!compiled)
|
||||
return false;
|
||||
|
||||
@ -366,17 +366,17 @@ js::DirectEvalStringFromIon(JSContext *cx,
|
||||
|
||||
unsigned staticLevel = callerScript->staticLevel() + 1;
|
||||
|
||||
Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx));
|
||||
if (!flatStr)
|
||||
RootedLinearString linearStr(cx, str->ensureLinear(cx));
|
||||
if (!linearStr)
|
||||
return false;
|
||||
|
||||
EvalJSONResult ejr = TryEvalJSON(cx, flatStr, vp);
|
||||
EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp);
|
||||
if (ejr != EvalJSON_NotJSON)
|
||||
return ejr == EvalJSON_Success;
|
||||
|
||||
EvalScriptGuard esg(cx);
|
||||
|
||||
esg.lookupInEvalCache(flatStr, callerScript, pc);
|
||||
esg.lookupInEvalCache(linearStr, callerScript, pc);
|
||||
|
||||
if (!esg.foundScript()) {
|
||||
RootedScript maybeScript(cx);
|
||||
@ -405,18 +405,18 @@ js::DirectEvalStringFromIon(JSContext *cx,
|
||||
.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
|
||||
.maybeMakeStrictMode(IsStrictEvalPC(pc));
|
||||
|
||||
AutoStableStringChars flatChars(cx);
|
||||
if (!flatChars.initTwoByte(cx, flatStr))
|
||||
AutoStableStringChars linearChars(cx);
|
||||
if (!linearChars.initTwoByte(cx, linearStr))
|
||||
return false;
|
||||
|
||||
const char16_t *chars = flatChars.twoByteRange().start().get();
|
||||
SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller()
|
||||
const char16_t *chars = linearChars.twoByteRange().start().get();
|
||||
SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller()
|
||||
? SourceBufferHolder::GiveOwnership
|
||||
: SourceBufferHolder::NoOwnership;
|
||||
SourceBufferHolder srcBuf(chars, flatStr->length(), ownership);
|
||||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||
JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||
scopeobj, callerScript, staticScope,
|
||||
options, srcBuf, flatStr, staticLevel);
|
||||
options, srcBuf, linearStr, staticLevel);
|
||||
if (!compiled)
|
||||
return false;
|
||||
|
||||
|
@ -836,20 +836,20 @@ json_parse(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
JSFlatString *flat = str->ensureFlat(cx);
|
||||
if (!flat)
|
||||
JSLinearString *linear = str->ensureLinear(cx);
|
||||
if (!linear)
|
||||
return false;
|
||||
|
||||
AutoStableStringChars flatChars(cx);
|
||||
if (!flatChars.init(cx, flat))
|
||||
AutoStableStringChars linearChars(cx);
|
||||
if (!linearChars.init(cx, linear))
|
||||
return false;
|
||||
|
||||
RootedValue reviver(cx, args.get(1));
|
||||
HandleValue reviver = args.get(1);
|
||||
|
||||
/* Steps 2-5. */
|
||||
return flatChars.isLatin1()
|
||||
? ParseJSONWithReviver(cx, flatChars.latin1Range(), reviver, args.rval())
|
||||
: ParseJSONWithReviver(cx, flatChars.twoByteRange(), reviver, args.rval());
|
||||
return linearChars.isLatin1()
|
||||
? ParseJSONWithReviver(cx, linearChars.latin1Range(), reviver, args.rval())
|
||||
: ParseJSONWithReviver(cx, linearChars.twoByteRange(), reviver, args.rval());
|
||||
}
|
||||
|
||||
/* ES5 15.12.3. */
|
||||
|
@ -3537,18 +3537,18 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp)
|
||||
if (!serialize.init(builder))
|
||||
return false;
|
||||
|
||||
JSFlatString *flat = src->ensureFlat(cx);
|
||||
if (!flat)
|
||||
JSLinearString *linear = src->ensureLinear(cx);
|
||||
if (!linear)
|
||||
return false;
|
||||
|
||||
AutoStableStringChars flatChars(cx);
|
||||
if (!flatChars.initTwoByte(cx, flat))
|
||||
AutoStableStringChars linearChars(cx);
|
||||
if (!linearChars.initTwoByte(cx, linear))
|
||||
return false;
|
||||
|
||||
CompileOptions options(cx);
|
||||
options.setFileAndLine(filename, lineno);
|
||||
options.setCanLazilyParse(false);
|
||||
mozilla::Range<const char16_t> chars = flatChars.twoByteRange();
|
||||
mozilla::Range<const char16_t> chars = linearChars.twoByteRange();
|
||||
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars.start().get(),
|
||||
chars.length(), /* foldConstants = */ false, nullptr, nullptr);
|
||||
if (!parser.checkOptions())
|
||||
|
@ -3065,32 +3065,32 @@ CopySubstringsToFatInline(JSFatInlineString *dest, const CharT *src, const Strin
|
||||
}
|
||||
|
||||
static inline JSFatInlineString *
|
||||
FlattenSubstrings(JSContext *cx, Handle<JSFlatString*> flatStr, const StringRange *ranges,
|
||||
FlattenSubstrings(JSContext *cx, HandleLinearString str, const StringRange *ranges,
|
||||
size_t rangesLen, size_t outputLen)
|
||||
{
|
||||
JSFatInlineString *str = NewGCFatInlineString<CanGC>(cx);
|
||||
if (!str)
|
||||
JSFatInlineString *result = NewGCFatInlineString<CanGC>(cx);
|
||||
if (!result)
|
||||
return nullptr;
|
||||
|
||||
AutoCheckCannotGC nogc;
|
||||
if (flatStr->hasLatin1Chars())
|
||||
CopySubstringsToFatInline(str, flatStr->latin1Chars(nogc), ranges, rangesLen, outputLen);
|
||||
if (str->hasLatin1Chars())
|
||||
CopySubstringsToFatInline(result, str->latin1Chars(nogc), ranges, rangesLen, outputLen);
|
||||
else
|
||||
CopySubstringsToFatInline(str, flatStr->twoByteChars(nogc), ranges, rangesLen, outputLen);
|
||||
return str;
|
||||
CopySubstringsToFatInline(result, str->twoByteChars(nogc), ranges, rangesLen, outputLen);
|
||||
return result;
|
||||
}
|
||||
|
||||
static JSString *
|
||||
AppendSubstrings(JSContext *cx, Handle<JSFlatString*> flatStr,
|
||||
const StringRange *ranges, size_t rangesLen)
|
||||
AppendSubstrings(JSContext *cx, HandleLinearString str, const StringRange *ranges,
|
||||
size_t rangesLen)
|
||||
{
|
||||
MOZ_ASSERT(rangesLen);
|
||||
|
||||
/* For single substrings, construct a dependent string. */
|
||||
if (rangesLen == 1)
|
||||
return NewDependentString(cx, flatStr, ranges[0].start, ranges[0].length);
|
||||
return NewDependentString(cx, str, ranges[0].start, ranges[0].length);
|
||||
|
||||
bool isLatin1 = flatStr->hasLatin1Chars();
|
||||
bool isLatin1 = str->hasLatin1Chars();
|
||||
uint32_t fatInlineMaxLength = JSFatInlineString::MAX_LENGTH_TWO_BYTE;
|
||||
if (isLatin1)
|
||||
fatInlineMaxLength = JSFatInlineString::MAX_LENGTH_LATIN1;
|
||||
@ -3113,10 +3113,10 @@ AppendSubstrings(JSContext *cx, Handle<JSFlatString*> flatStr,
|
||||
if (i == end) {
|
||||
/* Not even one range fits JSFatInlineString, use DependentString */
|
||||
const StringRange &sr = ranges[i++];
|
||||
part = NewDependentString(cx, flatStr, sr.start, sr.length);
|
||||
part = NewDependentString(cx, str, sr.start, sr.length);
|
||||
} else {
|
||||
/* Copy the ranges (linearly) into a JSFatInlineString */
|
||||
part = FlattenSubstrings(cx, flatStr, ranges + i, end - i, substrLen);
|
||||
part = FlattenSubstrings(cx, str, ranges + i, end - i, substrLen);
|
||||
i = end;
|
||||
}
|
||||
|
||||
@ -3134,13 +3134,13 @@ AppendSubstrings(JSContext *cx, Handle<JSFlatString*> flatStr,
|
||||
static bool
|
||||
StrReplaceRegexpRemove(JSContext *cx, HandleString str, RegExpShared &re, MutableHandleValue rval)
|
||||
{
|
||||
Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx));
|
||||
if (!flatStr)
|
||||
RootedLinearString linearStr(cx, str->ensureLinear(cx));
|
||||
if (!linearStr)
|
||||
return false;
|
||||
|
||||
Vector<StringRange, 16, SystemAllocPolicy> ranges;
|
||||
|
||||
size_t charsLen = flatStr->length();
|
||||
size_t charsLen = linearStr->length();
|
||||
|
||||
ScopedMatchPairs matches(&cx->tempLifoAlloc());
|
||||
size_t startIndex = 0; /* Index used for iterating through the string. */
|
||||
@ -3152,7 +3152,7 @@ StrReplaceRegexpRemove(JSContext *cx, HandleString str, RegExpShared &re, Mutabl
|
||||
if (!CheckForInterrupt(cx))
|
||||
return false;
|
||||
|
||||
RegExpRunStatus status = re.execute(cx, flatStr, startIndex, &matches);
|
||||
RegExpRunStatus status = re.execute(cx, linearStr, startIndex, &matches);
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return false;
|
||||
if (status == RegExpRunStatus_Success_NotFound)
|
||||
@ -3183,7 +3183,7 @@ StrReplaceRegexpRemove(JSContext *cx, HandleString str, RegExpShared &re, Mutabl
|
||||
res = cx->global()->getRegExpStatics(cx);
|
||||
if (!res)
|
||||
return false;
|
||||
res->updateLazily(cx, flatStr, &re, lazyIndex);
|
||||
res->updateLazily(cx, linearStr, &re, lazyIndex);
|
||||
}
|
||||
rval.setString(str);
|
||||
return true;
|
||||
@ -3194,7 +3194,7 @@ StrReplaceRegexpRemove(JSContext *cx, HandleString str, RegExpShared &re, Mutabl
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
res->updateLazily(cx, flatStr, &re, lazyIndex);
|
||||
res->updateLazily(cx, linearStr, &re, lazyIndex);
|
||||
|
||||
/* Include any remaining part of the string. */
|
||||
if (lastIndex < charsLen) {
|
||||
@ -3208,7 +3208,7 @@ StrReplaceRegexpRemove(JSContext *cx, HandleString str, RegExpShared &re, Mutabl
|
||||
return true;
|
||||
}
|
||||
|
||||
JSString *result = AppendSubstrings(cx, flatStr, ranges.begin(), ranges.length());
|
||||
JSString *result = AppendSubstrings(cx, linearStr, ranges.begin(), ranges.length());
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
|
@ -6016,8 +6016,8 @@ DebuggerGenericEval(JSContext *cx, const char *fullMethodName, const Value &code
|
||||
fullMethodName, "string", InformalValueTypeName(code));
|
||||
return false;
|
||||
}
|
||||
Rooted<JSFlatString *> flat(cx, code.toString()->ensureFlat(cx));
|
||||
if (!flat)
|
||||
RootedLinearString linear(cx, code.toString()->ensureLinear(cx));
|
||||
if (!linear)
|
||||
return false;
|
||||
|
||||
/*
|
||||
@ -6128,7 +6128,7 @@ DebuggerGenericEval(JSContext *cx, const char *fullMethodName, const Value &code
|
||||
AbstractFramePtr frame = iter ? iter->abstractFramePtr() : NullFramePtr();
|
||||
jsbytecode *pc = iter ? iter->pc() : nullptr;
|
||||
AutoStableStringChars stableChars(cx);
|
||||
if (!stableChars.initTwoByte(cx, flat))
|
||||
if (!stableChars.initTwoByte(cx, linear))
|
||||
return false;
|
||||
|
||||
mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
|
||||
|
Loading…
Reference in New Issue
Block a user