Commit 43095278 authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

[ast] Avoid unnecessary creation of Literals in TemplateString handling

For the tagged case, we never use the Literal AST node, so don't bother
creating them in the first place. Instead, store AstRawStrings directly,
and only wrap with Literals when desugaring untagged templates into
binary ops.

This also makes the upcoming merge of Literal and AstValue simpler.

Bug: v8:6984
Change-Id: I9f12710b05c6d63d7e91f2707cd08093f7ff3f11
Reviewed-on: https://chromium-review.googlesource.com/736151Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48940}
parent c87875cd
......@@ -645,18 +645,23 @@ Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
bool raw_and_cooked_match = true;
for (int i = 0; i < raw_strings->length(); ++i) {
if (*this->raw_strings()->at(i)->value() !=
*this->cooked_strings()->at(i)->value()) {
if (this->cooked_strings()->at(i) == nullptr ||
*this->raw_strings()->at(i)->string() !=
*this->cooked_strings()->at(i)->string()) {
raw_and_cooked_match = false;
}
raw_strings->set(i, *this->raw_strings()->at(i)->value());
raw_strings->set(i, *this->raw_strings()->at(i)->string());
}
Handle<FixedArray> cooked_strings = raw_strings;
if (!raw_and_cooked_match) {
cooked_strings = isolate->factory()->NewFixedArray(
this->cooked_strings()->length(), TENURED);
for (int i = 0; i < cooked_strings->length(); ++i) {
cooked_strings->set(i, *this->cooked_strings()->at(i)->value());
if (this->cooked_strings()->at(i) != nullptr) {
cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
} else {
cooked_strings->set(i, isolate->heap()->undefined_value());
}
}
}
return isolate->factory()->NewTemplateObjectDescription(
......
......@@ -2596,8 +2596,12 @@ class GetIterator final : public Expression {
// (defined at https://tc39.github.io/ecma262/#sec-gettemplateobject).
class GetTemplateObject final : public Expression {
public:
ZoneList<Literal*>* cooked_strings() const { return cooked_strings_; }
ZoneList<Literal*>* raw_strings() const { return raw_strings_; }
const ZoneList<const AstRawString*>* cooked_strings() const {
return cooked_strings_;
}
const ZoneList<const AstRawString*>* raw_strings() const {
return raw_strings_;
}
int hash() const { return hash_; }
Handle<TemplateObjectDescription> GetOrBuildDescription(Isolate* isolate);
......@@ -2605,15 +2609,16 @@ class GetTemplateObject final : public Expression {
private:
friend class AstNodeFactory;
GetTemplateObject(ZoneList<Literal*>* cooked_strings,
ZoneList<Literal*>* raw_strings, int hash, int pos)
GetTemplateObject(const ZoneList<const AstRawString*>* cooked_strings,
const ZoneList<const AstRawString*>* raw_strings, int hash,
int pos)
: Expression(pos, kGetTemplateObject),
cooked_strings_(cooked_strings),
raw_strings_(raw_strings),
hash_(hash) {}
ZoneList<Literal*>* cooked_strings_;
ZoneList<Literal*>* raw_strings_;
const ZoneList<const AstRawString*>* cooked_strings_;
const ZoneList<const AstRawString*>* raw_strings_;
int hash_;
};
......@@ -3245,9 +3250,9 @@ class AstNodeFactory final BASE_EMBEDDED {
return new (zone_) GetIterator(iterable, hint, pos);
}
GetTemplateObject* NewGetTemplateObject(ZoneList<Literal*>* cooked_strings,
ZoneList<Literal*>* raw_strings,
int hash, int pos) {
GetTemplateObject* NewGetTemplateObject(
const ZoneList<const AstRawString*>* cooked_strings,
const ZoneList<const AstRawString*>* raw_strings, int hash, int pos) {
return new (zone_)
GetTemplateObject(cooked_strings, raw_strings, hash, pos);
}
......
......@@ -3504,17 +3504,13 @@ Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
void Parser::AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
bool tail) {
DCHECK(should_cook || allow_harmony_template_escapes());
int pos = scanner()->location().beg_pos;
int end = scanner()->location().end_pos - (tail ? 1 : 2);
const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
Literal* raw = factory()->NewStringLiteral(trv, pos);
const AstRawString* raw = scanner()->CurrentRawSymbol(ast_value_factory());
if (should_cook) {
const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
Literal* cooked = factory()->NewStringLiteral(tv, pos);
const AstRawString* cooked = scanner()->CurrentSymbol(ast_value_factory());
(*state)->AddTemplateSpan(cooked, raw, end, zone());
} else {
(*state)->AddTemplateSpan(factory()->NewUndefinedLiteral(pos), raw, end,
zone());
(*state)->AddTemplateSpan(nullptr, raw, end, zone());
}
}
......@@ -3529,19 +3525,21 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
Expression* tag) {
TemplateLiteral* lit = *state;
int pos = lit->position();
const ZoneList<Literal*>* cooked_strings = lit->cooked();
const ZoneList<Literal*>* raw_strings = lit->raw();
const ZoneList<const AstRawString*>* cooked_strings = lit->cooked();
const ZoneList<const AstRawString*>* raw_strings = lit->raw();
const ZoneList<Expression*>* expressions = lit->expressions();
DCHECK_EQ(cooked_strings->length(), raw_strings->length());
DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
if (!tag) {
// Build tree of BinaryOps to simplify code-generation
Expression* expr = cooked_strings->at(0);
Expression* expr =
factory()->NewStringLiteral(cooked_strings->at(0), kNoSourcePosition);
int i = 0;
while (i < expressions->length()) {
Expression* sub = expressions->at(i++);
Expression* cooked_str = cooked_strings->at(i);
const AstRawString* cooked_str = cooked_strings->at(i);
DCHECK_NOT_NULL(cooked_str);
// Let middle be ToString(sub).
ZoneList<Expression*>* args =
......@@ -3551,17 +3549,18 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
args, sub->position());
expr = factory()->NewBinaryOperation(
Token::ADD, factory()->NewBinaryOperation(
Token::ADD, expr, middle, expr->position()),
cooked_str, sub->position());
Token::ADD,
factory()->NewBinaryOperation(Token::ADD, expr, middle,
expr->position()),
factory()->NewStringLiteral(cooked_str, kNoSourcePosition),
sub->position());
}
return expr;
} else {
// GetTemplateObject
const int32_t hash = ComputeTemplateLiteralHash(lit);
Expression* template_object = factory()->NewGetTemplateObject(
const_cast<ZoneList<Literal*>*>(cooked_strings),
const_cast<ZoneList<Literal*>*>(raw_strings), hash, pos);
Expression* template_object =
factory()->NewGetTemplateObject(cooked_strings, raw_strings, hash, pos);
// Call TagFn
ZoneList<Expression*>* call_args =
......@@ -3587,7 +3586,7 @@ uint32_t HalfAvalance(uint32_t a) {
} // namespace
int32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
const ZoneList<Literal*>* raw_strings = lit->raw();
const ZoneList<const AstRawString*>* raw_strings = lit->raw();
int total = raw_strings->length();
DCHECK_GT(total, 0);
......@@ -3599,8 +3598,7 @@ int32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
running_hash, "${}", 3);
}
const AstRawString* raw_string =
raw_strings->at(index)->AsLiteral()->AsRawString();
const AstRawString* raw_string = raw_strings->at(index);
if (raw_string->is_one_byte()) {
const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
running_hash = StringHasher::ComputeRunningHashOneByte(
......
......@@ -495,13 +495,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
TemplateLiteral(Zone* zone, int pos)
: cooked_(8, zone), raw_(8, zone), expressions_(8, zone), pos_(pos) {}
const ZoneList<Literal*>* cooked() const { return &cooked_; }
const ZoneList<Literal*>* raw() const { return &raw_; }
const ZoneList<const AstRawString*>* cooked() const { return &cooked_; }
const ZoneList<const AstRawString*>* raw() const { return &raw_; }
const ZoneList<Expression*>* expressions() const { return &expressions_; }
int position() const { return pos_; }
void AddTemplateSpan(Literal* cooked, Literal* raw, int end, Zone* zone) {
DCHECK_NOT_NULL(cooked);
void AddTemplateSpan(const AstRawString* cooked, const AstRawString* raw,
int end, Zone* zone) {
DCHECK_NOT_NULL(raw);
cooked_.Add(cooked, zone);
raw_.Add(raw, zone);
......@@ -513,8 +513,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
}
private:
ZoneList<Literal*> cooked_;
ZoneList<Literal*> raw_;
ZoneList<const AstRawString*> cooked_;
ZoneList<const AstRawString*> raw_;
ZoneList<Expression*> expressions_;
int pos_;
};
......
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