Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1343)

Side by Side Diff: runtime/vm/parser.cc

Issue 24203004: Dart VM: Simplify code generation for equality operators. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/stub_code.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after
1916 const Function& super_operator = Function::ZoneHandle( 1916 const Function& super_operator = Function::ZoneHandle(
1917 GetSuperFunction(operator_pos, 1917 GetSuperFunction(operator_pos,
1918 operator_function_name, 1918 operator_function_name,
1919 op_arguments, 1919 op_arguments,
1920 kResolveGetter, 1920 kResolveGetter,
1921 &is_no_such_method)); 1921 &is_no_such_method));
1922 if (is_no_such_method) { 1922 if (is_no_such_method) {
1923 op_arguments = BuildNoSuchMethodArguments( 1923 op_arguments = BuildNoSuchMethodArguments(
1924 operator_pos, operator_function_name, *op_arguments); 1924 operator_pos, operator_function_name, *op_arguments);
1925 } 1925 }
1926 if (super_operator.name() == Symbols::EqualOperator().raw()) { 1926 super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
1927 // Expand super.== call to match correct == semantics into:
1928 // Let t1 = left, t2 = right {
1929 // (t1 === null || t2 === null) ? t1 === t2
1930 // : static_call(super.==, t1, t2)
1931 // }
1932 // Normal == calls are not expanded at the AST level to produce
1933 // more compact code and enable more optimization opportunities.
1934 ASSERT(!is_no_such_method); // == is always found.
1935 EnsureExpressionTemp(); // Needed for ConditionalExprNode.
1936 LetNode* result = new LetNode(operator_pos);
1937 AstNode* left =
1938 new LoadLocalNode(operator_pos,
1939 result->AddInitializer(op_arguments->NodeAt(0)));
1940 AstNode* right =
1941 new LoadLocalNode(operator_pos,
1942 result->AddInitializer(op_arguments->NodeAt(1)));
1943 LiteralNode* null_operand =
1944 new LiteralNode(operator_pos, Instance::ZoneHandle());
1945 ComparisonNode* is_left_null = new ComparisonNode(operator_pos,
1946 Token::kEQ_STRICT,
1947 left,
1948 null_operand);
1949 ComparisonNode* is_right_null = new ComparisonNode(operator_pos,
1950 Token::kEQ_STRICT,
1951 right,
1952 null_operand);
1953 BinaryOpNode* null_check = new BinaryOpNode(operator_pos,
1954 Token::kOR,
1955 is_left_null,
1956 is_right_null);
1957 ArgumentListNode* new_arguments = new ArgumentListNode(operator_pos);
1958 new_arguments->Add(left);
1959 new_arguments->Add(right);
1960 StaticCallNode* call = new StaticCallNode(operator_pos,
1961 super_operator,
1962 new_arguments);
1963 ComparisonNode* strict_eq = new ComparisonNode(operator_pos,
1964 Token::kEQ_STRICT,
1965 left,
1966 right);
1967 result->AddNode(new ConditionalExprNode(operator_pos,
1968 null_check,
1969 strict_eq,
1970 call));
1971 super_op = result;
1972 } else {
1973 super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
1974 }
1975 if (negate_result) { 1927 if (negate_result) {
1976 super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op); 1928 super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op);
1977 } 1929 }
1978 } 1930 }
1979 return super_op; 1931 return super_op;
1980 } 1932 }
1981 1933
1982 1934
1983 AstNode* Parser::CreateImplicitClosureNode(const Function& func, 1935 AstNode* Parser::CreateImplicitClosureNode(const Function& func,
1984 intptr_t token_pos, 1936 intptr_t token_pos,
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
2872 // instantiate types. 2824 // instantiate types.
2873 CaptureInstantiator(); 2825 CaptureInstantiator();
2874 } 2826 }
2875 } 2827 }
2876 } 2828 }
2877 2829
2878 OpenBlock(); // Open a nested scope for the outermost function block. 2830 OpenBlock(); // Open a nested scope for the outermost function block.
2879 intptr_t end_token_pos = 0; 2831 intptr_t end_token_pos = 0;
2880 if (CurrentToken() == Token::kLBRACE) { 2832 if (CurrentToken() == Token::kLBRACE) {
2881 ConsumeToken(); 2833 ConsumeToken();
2834 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) {
2835 const Class& owner = Class::Handle(func.Owner());
2836 if (!owner.IsObjectClass()) {
2837 AddEqualityNullCheck();
2838 }
2839 }
2882 ParseStatementSequence(); 2840 ParseStatementSequence();
2883 end_token_pos = TokenPos(); 2841 end_token_pos = TokenPos();
2884 ExpectToken(Token::kRBRACE); 2842 ExpectToken(Token::kRBRACE);
2885 } else if (CurrentToken() == Token::kARROW) { 2843 } else if (CurrentToken() == Token::kARROW) {
2886 ConsumeToken(); 2844 ConsumeToken();
2845 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) {
2846 const Class& owner = Class::Handle(func.Owner());
2847 if (!owner.IsObjectClass()) {
2848 AddEqualityNullCheck();
2849 }
2850 }
2887 const intptr_t expr_pos = TokenPos(); 2851 const intptr_t expr_pos = TokenPos();
2888 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); 2852 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
2889 ASSERT(expr != NULL); 2853 ASSERT(expr != NULL);
2890 current_block_->statements->Add(new ReturnNode(expr_pos, expr)); 2854 current_block_->statements->Add(new ReturnNode(expr_pos, expr));
2891 end_token_pos = TokenPos(); 2855 end_token_pos = TokenPos();
2892 } else if (IsLiteral("native")) { 2856 } else if (IsLiteral("native")) {
2857 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) {
2858 const Class& owner = Class::Handle(func.Owner());
2859 if (!owner.IsObjectClass()) {
2860 AddEqualityNullCheck();
2861 }
2862 }
2893 ParseNativeFunctionBlock(&params, func); 2863 ParseNativeFunctionBlock(&params, func);
2894 end_token_pos = TokenPos(); 2864 end_token_pos = TokenPos();
2895 ExpectSemicolon(); 2865 ExpectSemicolon();
2896 } else if (func.is_external()) { 2866 } else if (func.is_external()) {
2897 // Body of an external method contains a single throw. 2867 // Body of an external method contains a single throw.
2898 const String& function_name = String::ZoneHandle(func.name()); 2868 const String& function_name = String::ZoneHandle(func.name());
2899 // TODO(regis): For an instance function, pass the receiver to 2869 // TODO(regis): For an instance function, pass the receiver to
2900 // NoSuchMethodError. 2870 // NoSuchMethodError.
2901 current_block_->statements->Add( 2871 current_block_->statements->Add(
2902 ThrowNoSuchMethodError(TokenPos(), 2872 ThrowNoSuchMethodError(TokenPos(),
(...skipping 14 matching lines...) Expand all
2917 func.end_token_pos() == end_token_pos); 2887 func.end_token_pos() == end_token_pos);
2918 func.set_end_token_pos(end_token_pos); 2888 func.set_end_token_pos(end_token_pos);
2919 SequenceNode* body = CloseBlock(); 2889 SequenceNode* body = CloseBlock();
2920 current_block_->statements->Add(body); 2890 current_block_->statements->Add(body);
2921 innermost_function_ = saved_innermost_function.raw(); 2891 innermost_function_ = saved_innermost_function.raw();
2922 last_used_try_index_ = saved_try_index; 2892 last_used_try_index_ = saved_try_index;
2923 return CloseBlock(); 2893 return CloseBlock();
2924 } 2894 }
2925 2895
2926 2896
2897 void Parser::AddEqualityNullCheck() {
2898 const intptr_t token_pos = Scanner::kDummyTokenIndex;
2899 AstNode* argument =
2900 new LoadLocalNode(token_pos,
2901 current_block_->scope->parent()->VariableAt(1));
2902 LiteralNode* null_operand =
2903 new LiteralNode(token_pos, Instance::ZoneHandle());
2904 ComparisonNode* check_arg = new ComparisonNode(token_pos,
2905 Token::kEQ_STRICT,
2906 argument,
2907 null_operand);
2908 ComparisonNode* result = new ComparisonNode(token_pos,
2909 Token::kEQ_STRICT,
2910 LoadReceiver(token_pos),
2911 null_operand);
2912 SequenceNode* arg_is_null = new SequenceNode(token_pos, NULL);
2913 arg_is_null->Add(new ReturnNode(token_pos, result));
2914 IfNode* if_arg_null = new IfNode(token_pos,
2915 check_arg,
2916 arg_is_null,
2917 NULL);
2918 current_block_->statements->Add(if_arg_null);
2919 }
2920
2921
2927 void Parser::SkipIf(Token::Kind token) { 2922 void Parser::SkipIf(Token::Kind token) {
2928 if (CurrentToken() == token) { 2923 if (CurrentToken() == token) {
2929 ConsumeToken(); 2924 ConsumeToken();
2930 } 2925 }
2931 } 2926 }
2932 2927
2933 2928
2934 // Skips tokens up to matching closing parenthesis. 2929 // Skips tokens up to matching closing parenthesis.
2935 void Parser::SkipToMatchingParenthesis() { 2930 void Parser::SkipToMatchingParenthesis() {
2936 ASSERT(CurrentToken() == Token::kLPAREN); 2931 ASSERT(CurrentToken() == Token::kLPAREN);
(...skipping 7672 matching lines...) Expand 10 before | Expand all | Expand 10 after
10609 void Parser::SkipQualIdent() { 10604 void Parser::SkipQualIdent() {
10610 ASSERT(IsIdentifier()); 10605 ASSERT(IsIdentifier());
10611 ConsumeToken(); 10606 ConsumeToken();
10612 if (CurrentToken() == Token::kPERIOD) { 10607 if (CurrentToken() == Token::kPERIOD) {
10613 ConsumeToken(); // Consume the kPERIOD token. 10608 ConsumeToken(); // Consume the kPERIOD token.
10614 ExpectIdentifier("identifier expected after '.'"); 10609 ExpectIdentifier("identifier expected after '.'");
10615 } 10610 }
10616 } 10611 }
10617 10612
10618 } // namespace dart 10613 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/stub_code.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698