Bug 1440309: Call String_repeat with int32 values to avoid repeated bailouts. r=jandem

--HG--
extra : rebase_source : ba212385115460e23dcc344ba862c911beae6467
This commit is contained in:
André Bargull 2018-02-27 06:45:26 -08:00
Родитель 929f26580a
Коммит 762378da15
4 изменённых файлов: 28 добавлений и 10 удалений

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

@ -23,6 +23,9 @@
// NB: keep this in sync with the copy in vm/ArgumentsObject.h.
#define MAX_ARGS_LENGTH (500 * 1000)
// NB: keep this in sync with the copy in vm/String.h.
#define MAX_STRING_LENGTH ((1 << 28) - 1)
// Spread non-empty argument list of up to 15 elements.
#define SPREAD(v, n) SPREAD_##n(v)
#define SPREAD_1(v) v[0]

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

@ -68,8 +68,7 @@ function String_generic_match(thisValue, regexp) {
* A helper function implementing the logic for both String.prototype.padStart
* and String.prototype.padEnd as described in ES7 Draft March 29, 2016
*/
function String_pad(maxLength, fillString, padEnd = false) {
function String_pad(maxLength, fillString, padEnd) {
// Steps 1-2.
RequireObjectCoercible(this);
let str = ToString(this);
@ -89,15 +88,21 @@ function String_pad(maxLength, fillString, padEnd = false) {
if (filler === "")
return str;
// Throw an error if the final string length exceeds the maximum string
// length. Perform this check early so we can use int32 operations below.
if (intMaxLength > MAX_STRING_LENGTH)
ThrowRangeError(JSMSG_RESULTING_STRING_TOO_LARGE);
// Step 9.
let fillLen = intMaxLength - strLen;
// Step 10.
// Perform an int32 division to ensure String_repeat is not called with a
// double to avoid repeated bailouts in ToInteger.
let truncatedStringFiller = callFunction(String_repeat, filler,
fillLen / filler.length);
(fillLen / filler.length) | 0);
truncatedStringFiller += callFunction(String_substr, filler, 0,
fillLen % filler.length);
truncatedStringFiller += Substring(filler, 0, fillLen % filler.length);
// Step 11.
if (padEnd === true)
@ -503,11 +508,14 @@ function String_repeat(count) {
if (n < 0)
ThrowRangeError(JSMSG_NEGATIVE_REPETITION_COUNT);
if (!(n * S.length < (1 << 28)))
// Inverted condition to handle |Infinity * 0 = NaN| correctly.
if (!(n * S.length <= MAX_STRING_LENGTH))
ThrowRangeError(JSMSG_RESULTING_STRING_TOO_LARGE);
// Communicate |n|'s possible range to the compiler.
n = n & ((1 << 28) - 1);
assert((MAX_STRING_LENGTH & (MAX_STRING_LENGTH + 1)) === 0,
"MAX_STRING_LENGTH can be used as a bitmask");
n = n & MAX_STRING_LENGTH;
// Steps 8-9.
var T = "";

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

@ -1683,11 +1683,11 @@ js::ReportInNotObjectError(JSContext* cx, HandleValue lref, int lindex,
HandleValue rref, int rindex)
{
auto uniqueCharsFromString = [](JSContext* cx, HandleValue ref) -> UniqueChars {
static const size_t MAX_STRING_LENGTH = 16;
static const size_t MaxStringLength = 16;
RootedString str(cx, ref.toString());
if (str->length() > MAX_STRING_LENGTH) {
if (str->length() > MaxStringLength) {
StringBuffer buf(cx);
if (!buf.appendSubstring(str, 0, MAX_STRING_LENGTH))
if (!buf.appendSubstring(str, 0, MaxStringLength))
return nullptr;
if (!buf.append("..."))
return nullptr;

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

@ -42,6 +42,7 @@
#include "js/CharacterEncoding.h"
#include "js/Date.h"
#include "js/Wrapper.h"
#include "vm/ArgumentsObject.h"
#include "vm/Compression.h"
#include "vm/GeneratorObject.h"
#include "vm/Interpreter.h"
@ -3194,3 +3195,9 @@ js::GetSelfHostedFunctionName(JSFunction* fun)
static_assert(JSString::MAX_LENGTH <= INT32_MAX,
"StringIteratorNext in builtin/String.js assumes the stored index "
"into the string is an Int32Value");
static_assert(JSString::MAX_LENGTH == MAX_STRING_LENGTH,
"JSString::MAX_LENGTH matches self-hosted constant for maximum string length");
static_assert(ARGS_LENGTH_MAX == MAX_ARGS_LENGTH,
"ARGS_LENGTH_MAX matches self-hosted constant for maximum arguments length");