Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/ast/ast.h" | 5 #include "src/ast/ast.h" |
| 6 | 6 |
| 7 #include <cmath> // For isfinite. | 7 #include <cmath> // For isfinite. |
| 8 | 8 |
| 9 #include "src/ast/prettyprinter.h" | 9 #include "src/ast/prettyprinter.h" |
| 10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
| 11 #include "src/base/hashmap.h" | 11 #include "src/base/hashmap.h" |
| 12 #include "src/builtins.h" | 12 #include "src/builtins.h" |
| 13 #include "src/code-stubs.h" | 13 #include "src/code-stubs.h" |
| 14 #include "src/contexts.h" | 14 #include "src/contexts.h" |
| 15 #include "src/conversions.h" | 15 #include "src/conversions.h" |
| 16 #include "src/parsing/parser.h" | 16 #include "src/parsing/parser.h" |
| 17 #include "src/property-details.h" | 17 #include "src/property-details.h" |
| 18 #include "src/property.h" | 18 #include "src/property.h" |
| 19 #include "src/string-stream.h" | 19 #include "src/string-stream.h" |
| 20 #include "src/type-info.h" | 20 #include "src/type-info.h" |
| 21 | 21 |
| 22 namespace v8 { | 22 namespace v8 { |
| 23 namespace internal { | 23 namespace internal { |
| 24 | 24 |
| 25 // ---------------------------------------------------------------------------- | 25 // ---------------------------------------------------------------------------- |
| 26 // All the Accept member functions for each syntax tree node type. | |
| 27 | |
| 28 #define DECL_ACCEPT(type) \ | |
| 29 void type::Accept(AstVisitor* v) { v->Visit##type(this); } | |
| 30 AST_NODE_LIST(DECL_ACCEPT) | |
| 31 #undef DECL_ACCEPT | |
| 32 | |
| 33 | |
| 34 // ---------------------------------------------------------------------------- | |
| 35 // Implementation of other node functionality. | 26 // Implementation of other node functionality. |
| 36 | 27 |
| 37 #ifdef DEBUG | 28 #ifdef DEBUG |
| 38 | 29 |
| 39 void AstNode::Print(Isolate* isolate) { | 30 void AstNode::Print(Isolate* isolate) { |
| 40 AstPrinter::PrintOut(isolate, this); | 31 AstPrinter::PrintOut(isolate, this); |
| 41 } | 32 } |
| 42 | 33 |
| 43 | 34 |
| 44 void AstNode::PrettyPrint(Isolate* isolate) { | 35 void AstNode::PrettyPrint(Isolate* isolate) { |
| 45 PrettyPrinter::PrintOut(isolate, this); | 36 PrettyPrinter::PrintOut(isolate, this); |
| 46 } | 37 } |
| 47 | 38 |
| 48 #endif // DEBUG | 39 #endif // DEBUG |
| 49 | 40 |
| 41 #define RETURN_NODE(Node) \ | |
|
Igor Sheludko
2016/07/14 16:39:54
This and below changes should have already been in
Toon Verwaest
2016/07/15 07:07:19
Acknowledged.
| |
| 42 case k##Node: \ | |
| 43 return reinterpret_cast<Node*>(this); | |
| 44 | |
| 50 IterationStatement* AstNode::AsIterationStatement() { | 45 IterationStatement* AstNode::AsIterationStatement() { |
| 51 #define TEST_ITERATION(Name) \ | 46 switch (node_type()) { |
| 52 if (Is##Name()) return As##Name(); | 47 ITERATION_NODE_LIST(RETURN_NODE); |
| 53 ITERATION_NODE_LIST(TEST_ITERATION) | 48 default: |
| 54 #undef TEST_ITERATION | 49 return nullptr; |
| 55 return nullptr; | 50 } |
| 56 } | 51 } |
| 57 | 52 |
| 58 BreakableStatement* AstNode::AsBreakableStatement() { | 53 BreakableStatement* AstNode::AsBreakableStatement() { |
| 59 #define TEST_BREAKABLE(Name) \ | 54 switch (node_type()) { |
| 60 if (Is##Name()) return As##Name(); | 55 BREAKABLE_NODE_LIST(RETURN_NODE); |
| 61 BREAKABLE_NODE_LIST(TEST_BREAKABLE) | 56 ITERATION_NODE_LIST(RETURN_NODE); |
| 62 #undef TEST_BREAKABLE | 57 default: |
| 63 return AsIterationStatement(); | 58 return nullptr; |
| 59 } | |
| 64 } | 60 } |
| 65 | 61 |
| 66 MaterializedLiteral* AstNode::AsMaterializedLiteral() { | 62 MaterializedLiteral* AstNode::AsMaterializedLiteral() { |
| 67 #define TEST_LITERAL(Name) \ | 63 switch (node_type()) { |
| 68 if (Is##Name()) return As##Name(); | 64 LITERAL_NODE_LIST(RETURN_NODE); |
| 69 LITERAL_NODE_LIST(TEST_LITERAL) | 65 default: |
| 70 #undef TEST_LITERAL | 66 return nullptr; |
| 71 return nullptr; | 67 } |
| 72 } | 68 } |
| 73 | 69 |
| 70 #undef RETURN_NODE | |
| 71 | |
| 74 InitializationFlag Declaration::initialization() const { | 72 InitializationFlag Declaration::initialization() const { |
| 75 switch (node_type()) { | 73 switch (node_type()) { |
| 76 #define GENERATE_CASE(Name) \ | 74 #define GENERATE_CASE(Node) \ |
| 77 case k##Name: \ | 75 case k##Node: \ |
| 78 return reinterpret_cast<const Name*>(this)->initialization(); | 76 return reinterpret_cast<const Node*>(this)->initialization(); |
| 79 DECLARATION_NODE_LIST(GENERATE_CASE); | 77 DECLARATION_NODE_LIST(GENERATE_CASE); |
| 80 #undef GENERATE_CASE | 78 #undef GENERATE_CASE |
| 81 default: | 79 default: |
| 82 UNREACHABLE(); | 80 UNREACHABLE(); |
| 83 return kNeedsInitialization; | 81 return kNeedsInitialization; |
| 84 } | 82 } |
| 85 } | 83 } |
| 86 | 84 |
| 87 bool Expression::IsSmiLiteral() const { | 85 bool Expression::IsSmiLiteral() const { |
| 88 return IsLiteral() && AsLiteral()->value()->IsSmi(); | 86 return IsLiteral() && AsLiteral()->value()->IsSmi(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 159 | 157 |
| 160 bool Statement::IsJump() const { | 158 bool Statement::IsJump() const { |
| 161 return (IsBlock() && AsBlock()->IsJump()) || | 159 return (IsBlock() && AsBlock()->IsJump()) || |
| 162 (IsExpressionStatement() && AsExpressionStatement()->IsJump()) || | 160 (IsExpressionStatement() && AsExpressionStatement()->IsJump()) || |
| 163 IsContinueStatement() || IsBreakStatement() || IsReturnStatement() || | 161 IsContinueStatement() || IsBreakStatement() || IsReturnStatement() || |
| 164 (IsIfStatement() && AsIfStatement()->IsJump()); | 162 (IsIfStatement() && AsIfStatement()->IsJump()); |
| 165 } | 163 } |
| 166 | 164 |
| 167 VariableProxy::VariableProxy(Zone* zone, Variable* var, int start_position, | 165 VariableProxy::VariableProxy(Zone* zone, Variable* var, int start_position, |
| 168 int end_position) | 166 int end_position) |
| 169 : Expression(zone, start_position), | 167 : Expression(zone, start_position, kVariableProxy), |
| 170 bit_field_(IsThisField::encode(var->is_this()) | | 168 bit_field_(IsThisField::encode(var->is_this()) | |
| 171 IsAssignedField::encode(false) | | 169 IsAssignedField::encode(false) | |
| 172 IsResolvedField::encode(false)), | 170 IsResolvedField::encode(false)), |
| 173 raw_name_(var->raw_name()), | 171 raw_name_(var->raw_name()), |
| 174 end_position_(end_position) { | 172 end_position_(end_position) { |
| 175 BindTo(var); | 173 BindTo(var); |
| 176 } | 174 } |
| 177 | 175 |
| 178 | |
| 179 VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, | 176 VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, |
| 180 Variable::Kind variable_kind, int start_position, | 177 Variable::Kind variable_kind, int start_position, |
| 181 int end_position) | 178 int end_position) |
| 182 : Expression(zone, start_position), | 179 : Expression(zone, start_position, kVariableProxy), |
| 183 bit_field_(IsThisField::encode(variable_kind == Variable::THIS) | | 180 bit_field_(IsThisField::encode(variable_kind == Variable::THIS) | |
| 184 IsAssignedField::encode(false) | | 181 IsAssignedField::encode(false) | |
| 185 IsResolvedField::encode(false)), | 182 IsResolvedField::encode(false)), |
| 186 raw_name_(name), | 183 raw_name_(name), |
| 187 end_position_(end_position) {} | 184 end_position_(end_position) {} |
| 188 | 185 |
| 189 | |
| 190 void VariableProxy::BindTo(Variable* var) { | 186 void VariableProxy::BindTo(Variable* var) { |
| 191 DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name()); | 187 DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name()); |
| 192 set_var(var); | 188 set_var(var); |
| 193 set_is_resolved(); | 189 set_is_resolved(); |
| 194 var->set_is_used(); | 190 var->set_is_used(); |
| 195 } | 191 } |
| 196 | 192 |
| 197 | 193 |
| 198 void VariableProxy::AssignFeedbackVectorSlots(Isolate* isolate, | 194 void VariableProxy::AssignFeedbackVectorSlots(Isolate* isolate, |
| 199 FeedbackVectorSpec* spec, | 195 FeedbackVectorSpec* spec, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 } | 228 } |
| 233 } | 229 } |
| 234 | 230 |
| 235 void ForInStatement::AssignFeedbackVectorSlots(Isolate* isolate, | 231 void ForInStatement::AssignFeedbackVectorSlots(Isolate* isolate, |
| 236 FeedbackVectorSpec* spec, | 232 FeedbackVectorSpec* spec, |
| 237 FeedbackVectorSlotCache* cache) { | 233 FeedbackVectorSlotCache* cache) { |
| 238 AssignVectorSlots(each(), spec, &each_slot_); | 234 AssignVectorSlots(each(), spec, &each_slot_); |
| 239 for_in_feedback_slot_ = spec->AddGeneralSlot(); | 235 for_in_feedback_slot_ = spec->AddGeneralSlot(); |
| 240 } | 236 } |
| 241 | 237 |
| 242 | |
| 243 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, | 238 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, |
| 244 Expression* value, int pos) | 239 Expression* value, int pos) |
| 245 : Expression(zone, pos), | 240 : Expression(zone, pos, kAssignment), |
| 246 bit_field_( | 241 bit_field_( |
| 247 IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) | | 242 IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) | |
| 248 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), | 243 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), |
| 249 target_(target), | 244 target_(target), |
| 250 value_(value), | 245 value_(value), |
| 251 binary_operation_(NULL) {} | 246 binary_operation_(NULL) {} |
| 252 | 247 |
| 253 | |
| 254 void Assignment::AssignFeedbackVectorSlots(Isolate* isolate, | 248 void Assignment::AssignFeedbackVectorSlots(Isolate* isolate, |
| 255 FeedbackVectorSpec* spec, | 249 FeedbackVectorSpec* spec, |
| 256 FeedbackVectorSlotCache* cache) { | 250 FeedbackVectorSlotCache* cache) { |
| 257 AssignVectorSlots(target(), spec, &slot_); | 251 AssignVectorSlots(target(), spec, &slot_); |
| 258 } | 252 } |
| 259 | 253 |
| 260 | 254 |
| 261 void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate, | 255 void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate, |
| 262 FeedbackVectorSpec* spec, | 256 FeedbackVectorSpec* spec, |
| 263 FeedbackVectorSlotCache* cache) { | 257 FeedbackVectorSlotCache* cache) { |
| (...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 852 } else { | 846 } else { |
| 853 return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL; | 847 return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL; |
| 854 } | 848 } |
| 855 } | 849 } |
| 856 | 850 |
| 857 return OTHER_CALL; | 851 return OTHER_CALL; |
| 858 } | 852 } |
| 859 | 853 |
| 860 | 854 |
| 861 // ---------------------------------------------------------------------------- | 855 // ---------------------------------------------------------------------------- |
| 862 // Implementation of AstVisitor | |
| 863 | |
| 864 void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) { | |
| 865 for (int i = 0; i < declarations->length(); i++) { | |
| 866 Visit(declarations->at(i)); | |
| 867 } | |
| 868 } | |
| 869 | |
| 870 | |
| 871 void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) { | |
| 872 for (int i = 0; i < statements->length(); i++) { | |
| 873 Statement* stmt = statements->at(i); | |
| 874 Visit(stmt); | |
| 875 if (stmt->IsJump()) break; | |
| 876 } | |
| 877 } | |
| 878 | |
| 879 | |
| 880 void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) { | |
| 881 for (int i = 0; i < expressions->length(); i++) { | |
| 882 // The variable statement visiting code may pass NULL expressions | |
| 883 // to this code. Maybe this should be handled by introducing an | |
| 884 // undefined expression or literal? Revisit this code if this | |
| 885 // changes | |
| 886 Expression* expression = expressions->at(i); | |
| 887 if (expression != NULL) Visit(expression); | |
| 888 } | |
| 889 } | |
| 890 | |
| 891 // ---------------------------------------------------------------------------- | |
| 892 // Implementation of AstTraversalVisitor | 856 // Implementation of AstTraversalVisitor |
| 893 | 857 |
| 894 #define RECURSE(call) \ | 858 #define RECURSE(call) \ |
| 895 do { \ | 859 do { \ |
| 896 DCHECK(!HasStackOverflow()); \ | 860 DCHECK(!HasStackOverflow()); \ |
| 897 call; \ | 861 call; \ |
| 898 if (HasStackOverflow()) return; \ | 862 if (HasStackOverflow()) return; \ |
| 899 } while (false) | 863 } while (false) |
| 900 | 864 |
| 901 #define RECURSE_EXPRESSION(call) \ | 865 #define RECURSE_EXPRESSION(call) \ |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1184 void AstTraversalVisitor::VisitRewritableExpression( | 1148 void AstTraversalVisitor::VisitRewritableExpression( |
| 1185 RewritableExpression* expr) { | 1149 RewritableExpression* expr) { |
| 1186 RECURSE(Visit(expr->expression())); | 1150 RECURSE(Visit(expr->expression())); |
| 1187 } | 1151 } |
| 1188 | 1152 |
| 1189 #undef RECURSE_EXPRESSION | 1153 #undef RECURSE_EXPRESSION |
| 1190 #undef RECURSE | 1154 #undef RECURSE |
| 1191 | 1155 |
| 1192 CaseClause::CaseClause(Zone* zone, Expression* label, | 1156 CaseClause::CaseClause(Zone* zone, Expression* label, |
| 1193 ZoneList<Statement*>* statements, int pos) | 1157 ZoneList<Statement*>* statements, int pos) |
| 1194 : Expression(zone, pos), | 1158 : Expression(zone, pos, kCaseClause), |
| 1195 label_(label), | 1159 label_(label), |
| 1196 statements_(statements), | 1160 statements_(statements), |
| 1197 compare_type_(Type::None()) {} | 1161 compare_type_(Type::None()) {} |
| 1198 | 1162 |
| 1199 uint32_t Literal::Hash() { | 1163 uint32_t Literal::Hash() { |
| 1200 return raw_value()->IsString() | 1164 return raw_value()->IsString() |
| 1201 ? raw_value()->AsString()->hash() | 1165 ? raw_value()->AsString()->hash() |
| 1202 : ComputeLongHash(double_to_uint64(raw_value()->AsNumber())); | 1166 : ComputeLongHash(double_to_uint64(raw_value()->AsNumber())); |
| 1203 } | 1167 } |
| 1204 | 1168 |
| 1205 | 1169 |
| 1206 // static | 1170 // static |
| 1207 bool Literal::Match(void* literal1, void* literal2) { | 1171 bool Literal::Match(void* literal1, void* literal2) { |
| 1208 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); | 1172 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); |
| 1209 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); | 1173 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); |
| 1210 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || | 1174 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || |
| 1211 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); | 1175 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); |
| 1212 } | 1176 } |
| 1213 | 1177 |
| 1214 | 1178 |
| 1215 } // namespace internal | 1179 } // namespace internal |
| 1216 } // namespace v8 | 1180 } // namespace v8 |
| OLD | NEW |