1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/ast/ast-function-literal-id-reindexer.h"
6 #include "src/objects/objects-inl.h"
7
8 #include "src/ast/ast.h"
9
10 namespace v8 {
11 namespace internal {
12
AstFunctionLiteralIdReindexer(size_t stack_limit,int delta)13 AstFunctionLiteralIdReindexer::AstFunctionLiteralIdReindexer(size_t stack_limit,
14 int delta)
15 : AstTraversalVisitor(stack_limit), delta_(delta) {}
16
17 AstFunctionLiteralIdReindexer::~AstFunctionLiteralIdReindexer() = default;
18
Reindex(Expression * pattern)19 void AstFunctionLiteralIdReindexer::Reindex(Expression* pattern) {
20 #ifdef DEBUG
21 visited_.clear();
22 #endif
23 Visit(pattern);
24 CheckVisited(pattern);
25 }
26
VisitFunctionLiteral(FunctionLiteral * lit)27 void AstFunctionLiteralIdReindexer::VisitFunctionLiteral(FunctionLiteral* lit) {
28 // Make sure we're not already in the visited set.
29 DCHECK(visited_.insert(lit).second);
30
31 AstTraversalVisitor::VisitFunctionLiteral(lit);
32 lit->set_function_literal_id(lit->function_literal_id() + delta_);
33 }
34
VisitClassLiteral(ClassLiteral * expr)35 void AstFunctionLiteralIdReindexer::VisitClassLiteral(ClassLiteral* expr) {
36 // Manually visit the class literal so that we can change the property walk.
37 // This should be kept in-sync with AstTraversalVisitor::VisitClassLiteral.
38
39 if (expr->extends() != nullptr) {
40 Visit(expr->extends());
41 }
42 Visit(expr->constructor());
43 if (expr->static_initializer() != nullptr) {
44 Visit(expr->static_initializer());
45 }
46 if (expr->instance_members_initializer_function() != nullptr) {
47 Visit(expr->instance_members_initializer_function());
48 }
49 ZonePtrList<ClassLiteral::Property>* private_members =
50 expr->private_members();
51 for (int i = 0; i < private_members->length(); ++i) {
52 ClassLiteralProperty* prop = private_members->at(i);
53
54 // Private fields have their key and value present in
55 // instance_members_initializer_function, so they will
56 // already have been visited.
57 if (prop->kind() == ClassLiteralProperty::Kind::FIELD) {
58 CheckVisited(prop->value());
59 } else {
60 Visit(prop->value());
61 }
62 }
63 ZonePtrList<ClassLiteral::Property>* props = expr->public_members();
64 for (int i = 0; i < props->length(); ++i) {
65 ClassLiteralProperty* prop = props->at(i);
66
67 // Public fields with computed names have their key
68 // and value present in instance_members_initializer_function, so they will
69 // already have been visited.
70 if (prop->is_computed_name() &&
71 prop->kind() == ClassLiteralProperty::Kind::FIELD) {
72 if (!prop->key()->IsLiteral()) {
73 CheckVisited(prop->key());
74 }
75 CheckVisited(prop->value());
76 } else {
77 if (!prop->key()->IsLiteral()) {
78 Visit(prop->key());
79 }
80 Visit(prop->value());
81 }
82 }
83 }
84
85 #ifdef DEBUG
86 namespace {
87
88 class AstFunctionLiteralIdReindexChecker final
89 : public AstTraversalVisitor<AstFunctionLiteralIdReindexChecker> {
90 public:
AstFunctionLiteralIdReindexChecker(size_t stack_limit,const std::set<FunctionLiteral * > * visited)91 AstFunctionLiteralIdReindexChecker(size_t stack_limit,
92 const std::set<FunctionLiteral*>* visited)
93 : AstTraversalVisitor(stack_limit), visited_(visited) {}
94
VisitFunctionLiteral(FunctionLiteral * lit)95 void VisitFunctionLiteral(FunctionLiteral* lit) {
96 // TODO(leszeks): It would be nice to print the unvisited function literal
97 // here, but that requires more advanced DCHECK support with formatting.
98 DCHECK(visited_->find(lit) != visited_->end());
99 }
100
101 private:
102 const std::set<FunctionLiteral*>* visited_;
103 };
104
105 } // namespace
106
CheckVisited(Expression * expr)107 void AstFunctionLiteralIdReindexer::CheckVisited(Expression* expr) {
108 AstFunctionLiteralIdReindexChecker(stack_limit(), &visited_).Visit(expr);
109 }
110 #endif
111
112 } // namespace internal
113 } // namespace v8
114