| 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 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/builtins.h" | 9 #include "src/builtins.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| 11 #include "src/contexts.h" | 11 #include "src/contexts.h" |
| 12 #include "src/conversions.h" | 12 #include "src/conversions.h" |
| 13 #include "src/hashmap.h" | 13 #include "src/hashmap.h" |
| 14 #include "src/parsing/parser.h" | 14 #include "src/parsing/parser.h" |
| 15 #include "src/property.h" | 15 #include "src/property.h" |
| 16 #include "src/property-details.h" | 16 #include "src/property-details.h" |
| 17 #include "src/string-stream.h" | 17 #include "src/string-stream.h" |
| 18 #include "src/type-info.h" | 18 #include "src/type-info.h" |
| 19 | 19 |
| 20 namespace v8 { | 20 namespace v8 { |
| 21 namespace internal { | 21 namespace internal { |
| 22 | 22 |
| 23 // ---------------------------------------------------------------------------- | 23 // ---------------------------------------------------------------------------- |
| 24 // All the Accept member functions for each syntax tree node type. | 24 // All the Accept member functions for each syntax tree node type. |
| 25 | 25 |
| 26 #define DECL_ACCEPT(type) \ | 26 #define DECL_ACCEPT(type) \ |
| 27 void type::Accept(AstVisitor* v) { v->Visit##type(this); } | 27 void type::Accept(AstVisitor* v) { v->Visit##type(this); } |
| 28 AST_NODE_LIST(DECL_ACCEPT) | 28 AST_NODE_LIST(DECL_ACCEPT) |
| 29 #undef DECL_ACCEPT | 29 #undef DECL_ACCEPT |
| 30 | 30 |
| 31 | 31 |
| 32 // ---------------------------------------------------------------------------- | 32 // ---------------------------------------------------------------------------- |
| 33 // Implementation of other node functionality. | 33 // Implementation of other node functionality. |
| 34 | 34 |
| 35 | 35 |
| 36 bool Expression::IsSmiLiteral() const { | 36 bool Expression::IsSmiLiteral() const { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 | 161 |
| 162 void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate, | 162 void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate, |
| 163 FeedbackVectorSpec* spec, | 163 FeedbackVectorSpec* spec, |
| 164 FeedbackVectorSlotCache* cache) { | 164 FeedbackVectorSlotCache* cache) { |
| 165 AssignVectorSlots(expression(), spec, &slot_); | 165 AssignVectorSlots(expression(), spec, &slot_); |
| 166 } | 166 } |
| 167 | 167 |
| 168 | 168 |
| 169 Token::Value Assignment::binary_op() const { | 169 Token::Value Assignment::binary_op() const { |
| 170 switch (op()) { | 170 switch (op()) { |
| 171 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; | 171 case Token::ASSIGN_BIT_OR: |
| 172 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; | 172 return Token::BIT_OR; |
| 173 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; | 173 case Token::ASSIGN_BIT_XOR: |
| 174 case Token::ASSIGN_SHL: return Token::SHL; | 174 return Token::BIT_XOR; |
| 175 case Token::ASSIGN_SAR: return Token::SAR; | 175 case Token::ASSIGN_BIT_AND: |
| 176 case Token::ASSIGN_SHR: return Token::SHR; | 176 return Token::BIT_AND; |
| 177 case Token::ASSIGN_ADD: return Token::ADD; | 177 case Token::ASSIGN_SHL: |
| 178 case Token::ASSIGN_SUB: return Token::SUB; | 178 return Token::SHL; |
| 179 case Token::ASSIGN_MUL: return Token::MUL; | 179 case Token::ASSIGN_SAR: |
| 180 case Token::ASSIGN_DIV: return Token::DIV; | 180 return Token::SAR; |
| 181 case Token::ASSIGN_MOD: return Token::MOD; | 181 case Token::ASSIGN_SHR: |
| 182 default: UNREACHABLE(); | 182 return Token::SHR; |
| 183 case Token::ASSIGN_ADD: |
| 184 return Token::ADD; |
| 185 case Token::ASSIGN_SUB: |
| 186 return Token::SUB; |
| 187 case Token::ASSIGN_MUL: |
| 188 return Token::MUL; |
| 189 case Token::ASSIGN_DIV: |
| 190 return Token::DIV; |
| 191 case Token::ASSIGN_MOD: |
| 192 return Token::MOD; |
| 193 default: |
| 194 UNREACHABLE(); |
| 183 } | 195 } |
| 184 return Token::ILLEGAL; | 196 return Token::ILLEGAL; |
| 185 } | 197 } |
| 186 | 198 |
| 187 | 199 |
| 188 bool FunctionLiteral::AllowsLazyCompilation() { | 200 bool FunctionLiteral::AllowsLazyCompilation() { |
| 189 return scope()->AllowsLazyCompilation(); | 201 return scope()->AllowsLazyCompilation(); |
| 190 } | 202 } |
| 191 | 203 |
| 192 | 204 |
| 193 bool FunctionLiteral::AllowsLazyCompilationWithoutContext() { | 205 bool FunctionLiteral::AllowsLazyCompilationWithoutContext() { |
| 194 return scope()->AllowsLazyCompilationWithoutContext(); | 206 return scope()->AllowsLazyCompilationWithoutContext(); |
| 195 } | 207 } |
| 196 | 208 |
| 197 | 209 |
| 198 int FunctionLiteral::start_position() const { | 210 int FunctionLiteral::start_position() const { |
| 199 return scope()->start_position(); | 211 return scope()->start_position(); |
| 200 } | 212 } |
| 201 | 213 |
| 202 | 214 |
| 203 int FunctionLiteral::end_position() const { | 215 int FunctionLiteral::end_position() const { return scope()->end_position(); } |
| 204 return scope()->end_position(); | |
| 205 } | |
| 206 | 216 |
| 207 | 217 |
| 208 LanguageMode FunctionLiteral::language_mode() const { | 218 LanguageMode FunctionLiteral::language_mode() const { |
| 209 return scope()->language_mode(); | 219 return scope()->language_mode(); |
| 210 } | 220 } |
| 211 | 221 |
| 212 | 222 |
| 213 bool FunctionLiteral::NeedsHomeObject(Expression* expr) { | 223 bool FunctionLiteral::NeedsHomeObject(Expression* expr) { |
| 214 if (expr == nullptr || !expr->IsFunctionLiteral()) return false; | 224 if (expr == nullptr || !expr->IsFunctionLiteral()) return false; |
| 215 DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope()); | 225 DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 ObjectLiteral::Property* property = properties()->at(i); | 274 ObjectLiteral::Property* property = properties()->at(i); |
| 265 Expression* value = property->value(); | 275 Expression* value = property->value(); |
| 266 if (FunctionLiteral::NeedsHomeObject(value)) { | 276 if (FunctionLiteral::NeedsHomeObject(value)) { |
| 267 property->SetSlot(spec->AddStoreICSlot()); | 277 property->SetSlot(spec->AddStoreICSlot()); |
| 268 } | 278 } |
| 269 } | 279 } |
| 270 } | 280 } |
| 271 | 281 |
| 272 | 282 |
| 273 bool ObjectLiteral::Property::IsCompileTimeValue() { | 283 bool ObjectLiteral::Property::IsCompileTimeValue() { |
| 274 return kind_ == CONSTANT || | 284 return kind_ == CONSTANT || (kind_ == MATERIALIZED_LITERAL && |
| 275 (kind_ == MATERIALIZED_LITERAL && | 285 CompileTimeValue::IsCompileTimeValue(value_)); |
| 276 CompileTimeValue::IsCompileTimeValue(value_)); | |
| 277 } | 286 } |
| 278 | 287 |
| 279 | 288 |
| 280 void ObjectLiteral::Property::set_emit_store(bool emit_store) { | 289 void ObjectLiteral::Property::set_emit_store(bool emit_store) { |
| 281 emit_store_ = emit_store; | 290 emit_store_ = emit_store; |
| 282 } | 291 } |
| 283 | 292 |
| 284 | 293 |
| 285 bool ObjectLiteral::Property::emit_store() { | 294 bool ObjectLiteral::Property::emit_store() { return emit_store_; } |
| 286 return emit_store_; | |
| 287 } | |
| 288 | 295 |
| 289 | 296 |
| 290 void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, | 297 void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
| 291 FeedbackVectorSpec* spec, | 298 FeedbackVectorSpec* spec, |
| 292 FeedbackVectorSlotCache* cache) { | 299 FeedbackVectorSlotCache* cache) { |
| 293 // This logic that computes the number of slots needed for vector store | 300 // This logic that computes the number of slots needed for vector store |
| 294 // ics must mirror FullCodeGenerator::VisitObjectLiteral. | 301 // ics must mirror FullCodeGenerator::VisitObjectLiteral. |
| 295 int property_index = 0; | 302 int property_index = 0; |
| 296 for (; property_index < properties()->length(); property_index++) { | 303 for (; property_index < properties()->length(); property_index++) { |
| 297 ObjectLiteral::Property* property = properties()->at(property_index); | 304 ObjectLiteral::Property* property = properties()->at(property_index); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) { | 391 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) { |
| 385 return property != NULL && | 392 return property != NULL && |
| 386 property->kind() != ObjectLiteral::Property::PROTOTYPE; | 393 property->kind() != ObjectLiteral::Property::PROTOTYPE; |
| 387 } | 394 } |
| 388 | 395 |
| 389 | 396 |
| 390 void ObjectLiteral::BuildConstantProperties(Isolate* isolate) { | 397 void ObjectLiteral::BuildConstantProperties(Isolate* isolate) { |
| 391 if (!constant_properties_.is_null()) return; | 398 if (!constant_properties_.is_null()) return; |
| 392 | 399 |
| 393 // Allocate a fixed array to hold all the constant properties. | 400 // Allocate a fixed array to hold all the constant properties. |
| 394 Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray( | 401 Handle<FixedArray> constant_properties = |
| 395 boilerplate_properties_ * 2, TENURED); | 402 isolate->factory()->NewFixedArray(boilerplate_properties_ * 2, TENURED); |
| 396 | 403 |
| 397 int position = 0; | 404 int position = 0; |
| 398 // Accumulate the value in local variables and store it at the end. | 405 // Accumulate the value in local variables and store it at the end. |
| 399 bool is_simple = true; | 406 bool is_simple = true; |
| 400 int depth_acc = 1; | 407 int depth_acc = 1; |
| 401 uint32_t max_element_index = 0; | 408 uint32_t max_element_index = 0; |
| 402 uint32_t elements = 0; | 409 uint32_t elements = 0; |
| 403 for (int i = 0; i < properties()->length(); i++) { | 410 for (int i = 0; i < properties()->length(); i++) { |
| 404 ObjectLiteral::Property* property = properties()->at(i); | 411 ObjectLiteral::Property* property = properties()->at(i); |
| 405 if (!IsBoilerplateProperty(property)) { | 412 if (!IsBoilerplateProperty(property)) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 436 may_store_doubles_ = true; | 443 may_store_doubles_ = true; |
| 437 } | 444 } |
| 438 | 445 |
| 439 is_simple = is_simple && !value->IsUninitialized(); | 446 is_simple = is_simple && !value->IsUninitialized(); |
| 440 | 447 |
| 441 // Keep track of the number of elements in the object literal and | 448 // Keep track of the number of elements in the object literal and |
| 442 // the largest element index. If the largest element index is | 449 // the largest element index. If the largest element index is |
| 443 // much larger than the number of elements, creating an object | 450 // much larger than the number of elements, creating an object |
| 444 // literal with fast elements will be a waste of space. | 451 // literal with fast elements will be a waste of space. |
| 445 uint32_t element_index = 0; | 452 uint32_t element_index = 0; |
| 446 if (key->IsString() | 453 if (key->IsString() && |
| 447 && Handle<String>::cast(key)->AsArrayIndex(&element_index) | 454 Handle<String>::cast(key)->AsArrayIndex(&element_index) && |
| 448 && element_index > max_element_index) { | 455 element_index > max_element_index) { |
| 449 max_element_index = element_index; | 456 max_element_index = element_index; |
| 450 elements++; | 457 elements++; |
| 451 } else if (key->IsSmi()) { | 458 } else if (key->IsSmi()) { |
| 452 int key_value = Smi::cast(*key)->value(); | 459 int key_value = Smi::cast(*key)->value(); |
| 453 if (key_value > 0 | 460 if (key_value > 0 && |
| 454 && static_cast<uint32_t>(key_value) > max_element_index) { | 461 static_cast<uint32_t>(key_value) > max_element_index) { |
| 455 max_element_index = key_value; | 462 max_element_index = key_value; |
| 456 } | 463 } |
| 457 elements++; | 464 elements++; |
| 458 } | 465 } |
| 459 | 466 |
| 460 // Add name, value pair to the fixed array. | 467 // Add name, value pair to the fixed array. |
| 461 constant_properties->set(position++, *key); | 468 constant_properties->set(position++, *key); |
| 462 constant_properties->set(position++, *value); | 469 constant_properties->set(position++, *value); |
| 463 } | 470 } |
| 464 | 471 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 } | 611 } |
| 605 | 612 |
| 606 | 613 |
| 607 static bool IsTypeof(Expression* expr) { | 614 static bool IsTypeof(Expression* expr) { |
| 608 UnaryOperation* maybe_unary = expr->AsUnaryOperation(); | 615 UnaryOperation* maybe_unary = expr->AsUnaryOperation(); |
| 609 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF; | 616 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF; |
| 610 } | 617 } |
| 611 | 618 |
| 612 | 619 |
| 613 // Check for the pattern: typeof <expression> equals <string literal>. | 620 // Check for the pattern: typeof <expression> equals <string literal>. |
| 614 static bool MatchLiteralCompareTypeof(Expression* left, | 621 static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op, |
| 615 Token::Value op, | 622 Expression* right, Expression** expr, |
| 616 Expression* right, | |
| 617 Expression** expr, | |
| 618 Handle<String>* check) { | 623 Handle<String>* check) { |
| 619 if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) { | 624 if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) { |
| 620 *expr = left->AsUnaryOperation()->expression(); | 625 *expr = left->AsUnaryOperation()->expression(); |
| 621 *check = Handle<String>::cast(right->AsLiteral()->value()); | 626 *check = Handle<String>::cast(right->AsLiteral()->value()); |
| 622 return true; | 627 return true; |
| 623 } | 628 } |
| 624 return false; | 629 return false; |
| 625 } | 630 } |
| 626 | 631 |
| 627 | 632 |
| 628 bool CompareOperation::IsLiteralCompareTypeof(Expression** expr, | 633 bool CompareOperation::IsLiteralCompareTypeof(Expression** expr, |
| 629 Handle<String>* check) { | 634 Handle<String>* check) { |
| 630 return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) || | 635 return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) || |
| 631 MatchLiteralCompareTypeof(right_, op_, left_, expr, check); | 636 MatchLiteralCompareTypeof(right_, op_, left_, expr, check); |
| 632 } | 637 } |
| 633 | 638 |
| 634 | 639 |
| 635 static bool IsVoidOfLiteral(Expression* expr) { | 640 static bool IsVoidOfLiteral(Expression* expr) { |
| 636 UnaryOperation* maybe_unary = expr->AsUnaryOperation(); | 641 UnaryOperation* maybe_unary = expr->AsUnaryOperation(); |
| 637 return maybe_unary != NULL && | 642 return maybe_unary != NULL && maybe_unary->op() == Token::VOID && |
| 638 maybe_unary->op() == Token::VOID && | 643 maybe_unary->expression()->IsLiteral(); |
| 639 maybe_unary->expression()->IsLiteral(); | |
| 640 } | 644 } |
| 641 | 645 |
| 642 | 646 |
| 643 // Check for the pattern: void <literal> equals <expression> or | 647 // Check for the pattern: void <literal> equals <expression> or |
| 644 // undefined equals <expression> | 648 // undefined equals <expression> |
| 645 static bool MatchLiteralCompareUndefined(Expression* left, | 649 static bool MatchLiteralCompareUndefined(Expression* left, Token::Value op, |
| 646 Token::Value op, | 650 Expression* right, Expression** expr, |
| 647 Expression* right, | |
| 648 Expression** expr, | |
| 649 Isolate* isolate) { | 651 Isolate* isolate) { |
| 650 if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) { | 652 if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) { |
| 651 *expr = right; | 653 *expr = right; |
| 652 return true; | 654 return true; |
| 653 } | 655 } |
| 654 if (left->IsUndefinedLiteral(isolate) && Token::IsEqualityOp(op)) { | 656 if (left->IsUndefinedLiteral(isolate) && Token::IsEqualityOp(op)) { |
| 655 *expr = right; | 657 *expr = right; |
| 656 return true; | 658 return true; |
| 657 } | 659 } |
| 658 return false; | 660 return false; |
| 659 } | 661 } |
| 660 | 662 |
| 661 | 663 |
| 662 bool CompareOperation::IsLiteralCompareUndefined( | 664 bool CompareOperation::IsLiteralCompareUndefined(Expression** expr, |
| 663 Expression** expr, Isolate* isolate) { | 665 Isolate* isolate) { |
| 664 return MatchLiteralCompareUndefined(left_, op_, right_, expr, isolate) || | 666 return MatchLiteralCompareUndefined(left_, op_, right_, expr, isolate) || |
| 665 MatchLiteralCompareUndefined(right_, op_, left_, expr, isolate); | 667 MatchLiteralCompareUndefined(right_, op_, left_, expr, isolate); |
| 666 } | 668 } |
| 667 | 669 |
| 668 | 670 |
| 669 // Check for the pattern: null equals <expression> | 671 // Check for the pattern: null equals <expression> |
| 670 static bool MatchLiteralCompareNull(Expression* left, | 672 static bool MatchLiteralCompareNull(Expression* left, Token::Value op, |
| 671 Token::Value op, | 673 Expression* right, Expression** expr) { |
| 672 Expression* right, | |
| 673 Expression** expr) { | |
| 674 if (left->IsNullLiteral() && Token::IsEqualityOp(op)) { | 674 if (left->IsNullLiteral() && Token::IsEqualityOp(op)) { |
| 675 *expr = right; | 675 *expr = right; |
| 676 return true; | 676 return true; |
| 677 } | 677 } |
| 678 return false; | 678 return false; |
| 679 } | 679 } |
| 680 | 680 |
| 681 | 681 |
| 682 bool CompareOperation::IsLiteralCompareNull(Expression** expr) { | 682 bool CompareOperation::IsLiteralCompareNull(Expression** expr) { |
| 683 return MatchLiteralCompareNull(left_, op_, right_, expr) || | 683 return MatchLiteralCompareNull(left_, op_, right_, expr) || |
| 684 MatchLiteralCompareNull(right_, op_, left_, expr); | 684 MatchLiteralCompareNull(right_, op_, left_, expr); |
| 685 } | 685 } |
| 686 | 686 |
| 687 | 687 |
| 688 // ---------------------------------------------------------------------------- | 688 // ---------------------------------------------------------------------------- |
| 689 // Inlining support | 689 // Inlining support |
| 690 | 690 |
| 691 bool Declaration::IsInlineable() const { | 691 bool Declaration::IsInlineable() const { |
| 692 return proxy()->var()->IsStackAllocated(); | 692 return proxy()->var()->IsStackAllocated(); |
| 693 } | 693 } |
| 694 | 694 |
| 695 bool FunctionDeclaration::IsInlineable() const { | 695 bool FunctionDeclaration::IsInlineable() const { return false; } |
| 696 return false; | |
| 697 } | |
| 698 | 696 |
| 699 | 697 |
| 700 // ---------------------------------------------------------------------------- | 698 // ---------------------------------------------------------------------------- |
| 701 // Recording of type feedback | 699 // Recording of type feedback |
| 702 | 700 |
| 703 // TODO(rossberg): all RecordTypeFeedback functions should disappear | 701 // TODO(rossberg): all RecordTypeFeedback functions should disappear |
| 704 // once we use the common type field in the AST consistently. | 702 // once we use the common type field in the AST consistently. |
| 705 | 703 |
| 706 void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { | 704 void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { |
| 707 set_to_boolean_types(oracle->ToBooleanTypes(test_id())); | 705 set_to_boolean_types(oracle->ToBooleanTypes(test_id())); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 // changes | 788 // changes |
| 791 Expression* expression = expressions->at(i); | 789 Expression* expression = expressions->at(i); |
| 792 if (expression != NULL) Visit(expression); | 790 if (expression != NULL) Visit(expression); |
| 793 } | 791 } |
| 794 } | 792 } |
| 795 | 793 |
| 796 | 794 |
| 797 // ---------------------------------------------------------------------------- | 795 // ---------------------------------------------------------------------------- |
| 798 // Regular expressions | 796 // Regular expressions |
| 799 | 797 |
| 800 #define MAKE_ACCEPT(Name) \ | 798 #define MAKE_ACCEPT(Name) \ |
| 801 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \ | 799 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \ |
| 802 return visitor->Visit##Name(this, data); \ | 800 return visitor->Visit##Name(this, data); \ |
| 803 } | 801 } |
| 804 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT) | 802 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT) |
| 805 #undef MAKE_ACCEPT | 803 #undef MAKE_ACCEPT |
| 806 | 804 |
| 807 #define MAKE_TYPE_CASE(Name) \ | 805 #define MAKE_TYPE_CASE(Name) \ |
| 808 RegExp##Name* RegExpTree::As##Name() { \ | 806 RegExp##Name* RegExpTree::As##Name() { return NULL; } \ |
| 809 return NULL; \ | |
| 810 } \ | |
| 811 bool RegExpTree::Is##Name() { return false; } | 807 bool RegExpTree::Is##Name() { return false; } |
| 812 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) | 808 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) |
| 813 #undef MAKE_TYPE_CASE | 809 #undef MAKE_TYPE_CASE |
| 814 | 810 |
| 815 #define MAKE_TYPE_CASE(Name) \ | 811 #define MAKE_TYPE_CASE(Name) \ |
| 816 RegExp##Name* RegExp##Name::As##Name() { \ | 812 RegExp##Name* RegExp##Name::As##Name() { return this; } \ |
| 817 return this; \ | |
| 818 } \ | |
| 819 bool RegExp##Name::Is##Name() { return true; } | 813 bool RegExp##Name::Is##Name() { return true; } |
| 820 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) | 814 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) |
| 821 #undef MAKE_TYPE_CASE | 815 #undef MAKE_TYPE_CASE |
| 822 | 816 |
| 823 | 817 |
| 824 static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) { | 818 static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) { |
| 825 Interval result = Interval::Empty(); | 819 Interval result = Interval::Empty(); |
| 826 for (int i = 0; i < children->length(); i++) | 820 for (int i = 0; i < children->length(); i++) |
| 827 result = result.Union(children->at(i)->CaptureRegisters()); | 821 result = result.Union(children->at(i)->CaptureRegisters()); |
| 828 return result; | 822 return result; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 | 856 |
| 863 bool RegExpAssertion::IsAnchoredAtEnd() { | 857 bool RegExpAssertion::IsAnchoredAtEnd() { |
| 864 return assertion_type() == RegExpAssertion::END_OF_INPUT; | 858 return assertion_type() == RegExpAssertion::END_OF_INPUT; |
| 865 } | 859 } |
| 866 | 860 |
| 867 | 861 |
| 868 bool RegExpAlternative::IsAnchoredAtStart() { | 862 bool RegExpAlternative::IsAnchoredAtStart() { |
| 869 ZoneList<RegExpTree*>* nodes = this->nodes(); | 863 ZoneList<RegExpTree*>* nodes = this->nodes(); |
| 870 for (int i = 0; i < nodes->length(); i++) { | 864 for (int i = 0; i < nodes->length(); i++) { |
| 871 RegExpTree* node = nodes->at(i); | 865 RegExpTree* node = nodes->at(i); |
| 872 if (node->IsAnchoredAtStart()) { return true; } | 866 if (node->IsAnchoredAtStart()) { |
| 873 if (node->max_match() > 0) { return false; } | 867 return true; |
| 868 } |
| 869 if (node->max_match() > 0) { |
| 870 return false; |
| 871 } |
| 874 } | 872 } |
| 875 return false; | 873 return false; |
| 876 } | 874 } |
| 877 | 875 |
| 878 | 876 |
| 879 bool RegExpAlternative::IsAnchoredAtEnd() { | 877 bool RegExpAlternative::IsAnchoredAtEnd() { |
| 880 ZoneList<RegExpTree*>* nodes = this->nodes(); | 878 ZoneList<RegExpTree*>* nodes = this->nodes(); |
| 881 for (int i = nodes->length() - 1; i >= 0; i--) { | 879 for (int i = nodes->length() - 1; i >= 0; i--) { |
| 882 RegExpTree* node = nodes->at(i); | 880 RegExpTree* node = nodes->at(i); |
| 883 if (node->IsAnchoredAtEnd()) { return true; } | 881 if (node->IsAnchoredAtEnd()) { |
| 884 if (node->max_match() > 0) { return false; } | 882 return true; |
| 883 } |
| 884 if (node->max_match() > 0) { |
| 885 return false; |
| 886 } |
| 885 } | 887 } |
| 886 return false; | 888 return false; |
| 887 } | 889 } |
| 888 | 890 |
| 889 | 891 |
| 890 bool RegExpDisjunction::IsAnchoredAtStart() { | 892 bool RegExpDisjunction::IsAnchoredAtStart() { |
| 891 ZoneList<RegExpTree*>* alternatives = this->alternatives(); | 893 ZoneList<RegExpTree*>* alternatives = this->alternatives(); |
| 892 for (int i = 0; i < alternatives->length(); i++) { | 894 for (int i = 0; i < alternatives->length(); i++) { |
| 893 if (!alternatives->at(i)->IsAnchoredAtStart()) | 895 if (!alternatives->at(i)->IsAnchoredAtStart()) return false; |
| 894 return false; | |
| 895 } | 896 } |
| 896 return true; | 897 return true; |
| 897 } | 898 } |
| 898 | 899 |
| 899 | 900 |
| 900 bool RegExpDisjunction::IsAnchoredAtEnd() { | 901 bool RegExpDisjunction::IsAnchoredAtEnd() { |
| 901 ZoneList<RegExpTree*>* alternatives = this->alternatives(); | 902 ZoneList<RegExpTree*>* alternatives = this->alternatives(); |
| 902 for (int i = 0; i < alternatives->length(); i++) { | 903 for (int i = 0; i < alternatives->length(); i++) { |
| 903 if (!alternatives->at(i)->IsAnchoredAtEnd()) | 904 if (!alternatives->at(i)->IsAnchoredAtEnd()) return false; |
| 904 return false; | |
| 905 } | 905 } |
| 906 return true; | 906 return true; |
| 907 } | 907 } |
| 908 | 908 |
| 909 | 909 |
| 910 bool RegExpLookaround::IsAnchoredAtStart() { | 910 bool RegExpLookaround::IsAnchoredAtStart() { |
| 911 return is_positive() && type() == LOOKAHEAD && body()->IsAnchoredAtStart(); | 911 return is_positive() && type() == LOOKAHEAD && body()->IsAnchoredAtStart(); |
| 912 } | 912 } |
| 913 | 913 |
| 914 | 914 |
| 915 bool RegExpCapture::IsAnchoredAtStart() { | 915 bool RegExpCapture::IsAnchoredAtStart() { return body()->IsAnchoredAtStart(); } |
| 916 return body()->IsAnchoredAtStart(); | |
| 917 } | |
| 918 | 916 |
| 919 | 917 |
| 920 bool RegExpCapture::IsAnchoredAtEnd() { | 918 bool RegExpCapture::IsAnchoredAtEnd() { return body()->IsAnchoredAtEnd(); } |
| 921 return body()->IsAnchoredAtEnd(); | |
| 922 } | |
| 923 | 919 |
| 924 | 920 |
| 925 // Convert regular expression trees to a simple sexp representation. | 921 // Convert regular expression trees to a simple sexp representation. |
| 926 // This representation should be different from the input grammar | 922 // This representation should be different from the input grammar |
| 927 // in as many cases as possible, to make it more difficult for incorrect | 923 // in as many cases as possible, to make it more difficult for incorrect |
| 928 // parses to look as correct ones which is likely if the input and | 924 // parses to look as correct ones which is likely if the input and |
| 929 // output formats are alike. | 925 // output formats are alike. |
| 930 class RegExpUnparser final : public RegExpVisitor { | 926 class RegExpUnparser final : public RegExpVisitor { |
| 931 public: | 927 public: |
| 932 RegExpUnparser(std::ostream& os, Zone* zone) : os_(os), zone_(zone) {} | 928 RegExpUnparser(std::ostream& os, Zone* zone) : os_(os), zone_(zone) {} |
| 933 void VisitCharacterRange(CharacterRange that); | 929 void VisitCharacterRange(CharacterRange that); |
| 934 #define MAKE_CASE(Name) void* Visit##Name(RegExp##Name*, void* data) override; | 930 #define MAKE_CASE(Name) void* Visit##Name(RegExp##Name*, void* data) override; |
| 935 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE) | 931 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE) |
| 936 #undef MAKE_CASE | 932 #undef MAKE_CASE |
| 937 private: | 933 private: |
| 938 std::ostream& os_; | 934 std::ostream& os_; |
| 939 Zone* zone_; | 935 Zone* zone_; |
| 940 }; | 936 }; |
| 941 | 937 |
| 942 | 938 |
| 943 void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) { | 939 void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) { |
| 944 os_ << "(|"; | 940 os_ << "(|"; |
| 945 for (int i = 0; i < that->alternatives()->length(); i++) { | 941 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 946 os_ << " "; | 942 os_ << " "; |
| 947 that->alternatives()->at(i)->Accept(this, data); | 943 that->alternatives()->at(i)->Accept(this, data); |
| 948 } | 944 } |
| 949 os_ << ")"; | 945 os_ << ")"; |
| 950 return NULL; | 946 return NULL; |
| 951 } | 947 } |
| 952 | 948 |
| 953 | 949 |
| 954 void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) { | 950 void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) { |
| 955 os_ << "(:"; | 951 os_ << "(:"; |
| 956 for (int i = 0; i < that->nodes()->length(); i++) { | 952 for (int i = 0; i < that->nodes()->length(); i++) { |
| 957 os_ << " "; | 953 os_ << " "; |
| 958 that->nodes()->at(i)->Accept(this, data); | 954 that->nodes()->at(i)->Accept(this, data); |
| 959 } | 955 } |
| 960 os_ << ")"; | 956 os_ << ")"; |
| 961 return NULL; | 957 return NULL; |
| 962 } | 958 } |
| 963 | 959 |
| 964 | 960 |
| 965 void RegExpUnparser::VisitCharacterRange(CharacterRange that) { | 961 void RegExpUnparser::VisitCharacterRange(CharacterRange that) { |
| 966 os_ << AsUC16(that.from()); | 962 os_ << AsUC16(that.from()); |
| 967 if (!that.IsSingleton()) { | 963 if (!that.IsSingleton()) { |
| 968 os_ << "-" << AsUC16(that.to()); | 964 os_ << "-" << AsUC16(that.to()); |
| 969 } | 965 } |
| 970 } | 966 } |
| 971 | 967 |
| 972 | 968 |
| 973 | |
| 974 void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that, | 969 void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that, |
| 975 void* data) { | 970 void* data) { |
| 976 if (that->is_negated()) os_ << "^"; | 971 if (that->is_negated()) os_ << "^"; |
| 977 os_ << "["; | 972 os_ << "["; |
| 978 for (int i = 0; i < that->ranges(zone_)->length(); i++) { | 973 for (int i = 0; i < that->ranges(zone_)->length(); i++) { |
| 979 if (i > 0) os_ << " "; | 974 if (i > 0) os_ << " "; |
| 980 VisitCharacterRange(that->ranges(zone_)->at(i)); | 975 VisitCharacterRange(that->ranges(zone_)->at(i)); |
| 981 } | 976 } |
| 982 os_ << "]"; | 977 os_ << "]"; |
| 983 return NULL; | 978 return NULL; |
| 984 } | 979 } |
| 985 | 980 |
| 986 | 981 |
| 987 void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) { | 982 void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) { |
| 988 switch (that->assertion_type()) { | 983 switch (that->assertion_type()) { |
| 989 case RegExpAssertion::START_OF_INPUT: | 984 case RegExpAssertion::START_OF_INPUT: |
| 990 os_ << "@^i"; | 985 os_ << "@^i"; |
| 991 break; | 986 break; |
| 992 case RegExpAssertion::END_OF_INPUT: | 987 case RegExpAssertion::END_OF_INPUT: |
| 993 os_ << "@$i"; | 988 os_ << "@$i"; |
| 994 break; | 989 break; |
| 995 case RegExpAssertion::START_OF_LINE: | 990 case RegExpAssertion::START_OF_LINE: |
| 996 os_ << "@^l"; | 991 os_ << "@^l"; |
| 997 break; | 992 break; |
| 998 case RegExpAssertion::END_OF_LINE: | 993 case RegExpAssertion::END_OF_LINE: |
| 999 os_ << "@$l"; | 994 os_ << "@$l"; |
| 1000 break; | 995 break; |
| 1001 case RegExpAssertion::BOUNDARY: | 996 case RegExpAssertion::BOUNDARY: |
| 1002 os_ << "@b"; | 997 os_ << "@b"; |
| 1003 break; | 998 break; |
| 1004 case RegExpAssertion::NON_BOUNDARY: | 999 case RegExpAssertion::NON_BOUNDARY: |
| 1005 os_ << "@B"; | 1000 os_ << "@B"; |
| 1006 break; | 1001 break; |
| 1007 } | 1002 } |
| 1008 return NULL; | 1003 return NULL; |
| 1009 } | 1004 } |
| 1010 | 1005 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 bool Literal::Match(void* literal1, void* literal2) { | 1138 bool Literal::Match(void* literal1, void* literal2) { |
| 1144 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); | 1139 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); |
| 1145 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); | 1140 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); |
| 1146 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || | 1141 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || |
| 1147 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); | 1142 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); |
| 1148 } | 1143 } |
| 1149 | 1144 |
| 1150 | 1145 |
| 1151 } // namespace internal | 1146 } // namespace internal |
| 1152 } // namespace v8 | 1147 } // namespace v8 |
| OLD | NEW |