Commit ad47996d authored by Zhang, Shiyu's avatar Zhang, Shiyu Committed by Commit Bot

Avoid a FixedArray allocation in date parser

During date parsing, a FixedArray is allocated to store intermediate values,
which is slow. This CL holds the values on stack instead to save time.

This increases the score of JetStream2 Date-format-tofte-SP case by ~2%
on WhiskeyLake Chromebook.

Contributed by hao.a.xu@intel.com

Change-Id: I0d7a20a3ad9c57e3a225fff03efc2e434b20fbbc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1726744
Commit-Queue: Shiyu Zhang <shiyu.zhang@intel.com>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63039}
parent f557b2e4
......@@ -111,24 +111,23 @@ const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
// ES6 section 20.3.1.16 Date Time String Format
double ParseDateTimeString(Isolate* isolate, Handle<String> str) {
str = String::Flatten(isolate, str);
// TODO(bmeurer): Change DateParser to not use the FixedArray.
Handle<FixedArray> tmp =
isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
double out[DateParser::OUTPUT_SIZE];
DisallowHeapAllocation no_gc;
String::FlatContent str_content = str->GetFlatContent(no_gc);
bool result;
if (str_content.IsOneByte()) {
result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp);
result = DateParser::Parse(isolate, str_content.ToOneByteVector(), out);
} else {
result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp);
result = DateParser::Parse(isolate, str_content.ToUC16Vector(), out);
}
if (!result) return std::numeric_limits<double>::quiet_NaN();
double const day =
MakeDay(tmp->get(0).Number(), tmp->get(1).Number(), tmp->get(2).Number());
double const time = MakeTime(tmp->get(3).Number(), tmp->get(4).Number(),
tmp->get(5).Number(), tmp->get(6).Number());
double const day = MakeDay(out[DateParser::YEAR], out[DateParser::MONTH],
out[DateParser::DAY]);
double const time =
MakeTime(out[DateParser::HOUR], out[DateParser::MINUTE],
out[DateParser::SECOND], out[DateParser::MILLISECOND]);
double date = MakeDate(day, time);
if (tmp->get(7).IsNull(isolate)) {
if (std::isnan(out[DateParser::UTC_OFFSET])) {
if (date >= -DateCache::kMaxTimeBeforeUTCInMs &&
date <= DateCache::kMaxTimeBeforeUTCInMs) {
date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
......@@ -136,7 +135,7 @@ double ParseDateTimeString(Isolate* isolate, Handle<String> str) {
return std::numeric_limits<double>::quiet_NaN();
}
} else {
date -= tmp->get(7).Number() * 1000.0;
date -= out[DateParser::UTC_OFFSET] * 1000.0;
}
return DateCache::TimeClip(date);
}
......
......@@ -13,8 +13,7 @@ namespace v8 {
namespace internal {
template <typename Char>
bool DateParser::Parse(Isolate* isolate, Vector<Char> str, FixedArray out) {
DCHECK(out.length() >= OUTPUT_SIZE);
bool DateParser::Parse(Isolate* isolate, Vector<Char> str, double* out) {
InputReader<Char> in(str);
DateStringTokenizer<Char> scanner(&in);
TimeZoneComposer tz;
......
......@@ -10,7 +10,7 @@
namespace v8 {
namespace internal {
bool DateParser::DayComposer::Write(FixedArray output) {
bool DateParser::DayComposer::Write(double* output) {
if (index_ < 1) return false;
// Day and month defaults to 1.
while (index_ < kSize) {
......@@ -58,13 +58,13 @@ bool DateParser::DayComposer::Write(FixedArray output) {
if (!Smi::IsValid(year) || !IsMonth(month) || !IsDay(day)) return false;
output.set(YEAR, Smi::FromInt(year));
output.set(MONTH, Smi::FromInt(month - 1)); // 0-based
output.set(DAY, Smi::FromInt(day));
output[YEAR] = year;
output[MONTH] = month - 1; // 0-based
output[DAY] = day;
return true;
}
bool DateParser::TimeComposer::Write(FixedArray output) {
bool DateParser::TimeComposer::Write(double* output) {
// All time slots default to 0
while (index_ < kSize) {
comp_[index_++] = 0;
......@@ -89,14 +89,14 @@ bool DateParser::TimeComposer::Write(FixedArray output) {
}
}
output.set(HOUR, Smi::FromInt(hour));
output.set(MINUTE, Smi::FromInt(minute));
output.set(SECOND, Smi::FromInt(second));
output.set(MILLISECOND, Smi::FromInt(millisecond));
output[HOUR] = hour;
output[MINUTE] = minute;
output[SECOND] = second;
output[MILLISECOND] = millisecond;
return true;
}
bool DateParser::TimeZoneComposer::Write(FixedArray output) {
bool DateParser::TimeZoneComposer::Write(double* output) {
if (sign_ != kNone) {
if (hour_ == kNone) hour_ = 0;
if (minute_ == kNone) minute_ = 0;
......@@ -109,9 +109,9 @@ bool DateParser::TimeZoneComposer::Write(FixedArray output) {
total_seconds = -total_seconds;
}
DCHECK(Smi::IsValid(total_seconds));
output.set(UTC_OFFSET, Smi::FromInt(total_seconds));
output[UTC_OFFSET] = total_seconds;
} else {
output.set_null(UTC_OFFSET);
output[UTC_OFFSET] = std::numeric_limits<double>::quiet_NaN();
}
return true;
}
......
......@@ -13,6 +13,18 @@ namespace internal {
class DateParser : public AllStatic {
public:
enum {
YEAR,
MONTH,
DAY,
HOUR,
MINUTE,
SECOND,
MILLISECOND,
UTC_OFFSET,
OUTPUT_SIZE
};
// Parse the string as a date. If parsing succeeds, return true after
// filling out the output array as follows (all integers are Smis):
// [0]: year
......@@ -25,19 +37,7 @@ class DateParser : public AllStatic {
// [7]: UTC offset in seconds, or null value if no timezone specified
// If parsing fails, return false (content of output array is not defined).
template <typename Char>
static bool Parse(Isolate* isolate, Vector<Char> str, FixedArray output);
enum {
YEAR,
MONTH,
DAY,
HOUR,
MINUTE,
SECOND,
MILLISECOND,
UTC_OFFSET,
OUTPUT_SIZE
};
static bool Parse(Isolate* isolate, Vector<Char> str, double* output);
private:
// Range testing
......@@ -274,7 +274,7 @@ class DateParser : public AllStatic {
return hour_ != kNone && minute_ == kNone && TimeComposer::IsMinute(n);
}
bool IsUTC() const { return hour_ == 0 && minute_ == 0; }
bool Write(FixedArray output);
bool Write(double* output);
bool IsEmpty() { return hour_ == kNone; }
private:
......@@ -300,7 +300,7 @@ class DateParser : public AllStatic {
return true;
}
void SetHourOffset(int n) { hour_offset_ = n; }
bool Write(FixedArray output);
bool Write(double* output);
static bool IsMinute(int x) { return Between(x, 0, 59); }
static bool IsHour(int x) { return Between(x, 0, 23); }
......@@ -329,7 +329,7 @@ class DateParser : public AllStatic {
return false;
}
void SetNamedMonth(int n) { named_month_ = n; }
bool Write(FixedArray output);
bool Write(double* output);
void set_iso_date() { is_iso_date_ = true; }
static bool IsMonth(int x) { return Between(x, 1, 12); }
static bool IsDay(int x) { return Between(x, 1, 31); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment