blob: 8c9318bfe7475d3c9b8cc2bdb50786b9118fd4a0 [file] [log] [blame]
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ast/ast-function-literal-id-reindexer.h"
#include "src/objects/objects-inl.h"
#include "src/ast/ast.h"
namespace v8 {
namespace internal {
AstFunctionLiteralIdReindexer::AstFunctionLiteralIdReindexer(size_t stack_limit,
int delta)
: AstTraversalVisitor(stack_limit), delta_(delta) {}
AstFunctionLiteralIdReindexer::~AstFunctionLiteralIdReindexer() = default;
void AstFunctionLiteralIdReindexer::Reindex(Expression* pattern) {
#ifdef DEBUG
visited_.clear();
#endif
Visit(pattern);
CheckVisited(pattern);
}
void AstFunctionLiteralIdReindexer::VisitFunctionLiteral(FunctionLiteral* lit) {
// Make sure we're not already in the visited set.
DCHECK(visited_.insert(lit).second);
AstTraversalVisitor::VisitFunctionLiteral(lit);
lit->set_function_literal_id(lit->function_literal_id() + delta_);
}
void AstFunctionLiteralIdReindexer::VisitClassLiteral(ClassLiteral* expr) {
// Manually visit the class literal so that we can change the property walk.
// This should be kept in-sync with AstTraversalVisitor::VisitClassLiteral.
if (expr->extends() != nullptr) {
Visit(expr->extends());
}
Visit(expr->constructor());
if (expr->static_fields_initializer() != nullptr) {
Visit(expr->static_fields_initializer());
}
if (expr->instance_members_initializer_function() != nullptr) {
Visit(expr->instance_members_initializer_function());
}
ZonePtrList<ClassLiteral::Property>* private_members =
expr->private_members();
for (int i = 0; i < private_members->length(); ++i) {
ClassLiteralProperty* prop = private_members->at(i);
// Private fields have their key and value present in
// instance_members_initializer_function, so they will
// already have been visited.
if (prop->kind() == ClassLiteralProperty::Kind::FIELD) {
CheckVisited(prop->value());
} else {
Visit(prop->value());
}
}
ZonePtrList<ClassLiteral::Property>* props = expr->public_members();
for (int i = 0; i < props->length(); ++i) {
ClassLiteralProperty* prop = props->at(i);
// Public fields with computed names have their key
// and value present in instance_members_initializer_function, so they will
// already have been visited.
if (prop->is_computed_name() &&
prop->kind() == ClassLiteralProperty::Kind::FIELD) {
if (!prop->key()->IsLiteral()) {
CheckVisited(prop->key());
}
CheckVisited(prop->value());
} else {
if (!prop->key()->IsLiteral()) {
Visit(prop->key());
}
Visit(prop->value());
}
}
}
#ifdef DEBUG
namespace {
class AstFunctionLiteralIdReindexChecker final
: public AstTraversalVisitor<AstFunctionLiteralIdReindexChecker> {
public:
AstFunctionLiteralIdReindexChecker(size_t stack_limit,
const std::set<FunctionLiteral*>* visited)
: AstTraversalVisitor(stack_limit), visited_(visited) {}
void VisitFunctionLiteral(FunctionLiteral* lit) {
// TODO(leszeks): It would be nice to print the unvisited function literal
// here, but that requires more advanced DCHECK support with formatting.
DCHECK(visited_->find(lit) != visited_->end());
}
private:
const std::set<FunctionLiteral*>* visited_;
};
} // namespace
void AstFunctionLiteralIdReindexer::CheckVisited(Expression* expr) {
AstFunctionLiteralIdReindexChecker(stack_limit(), &visited_).Visit(expr);
}
#endif
} // namespace internal
} // namespace v8