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 |