| // 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 |