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

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

Issue 10915022: Implement argument definition test in the vm. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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
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 "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 } 112 }
113 113
114 114
115 void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) { 115 void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) {
116 ASSERT(node_sequence_ == NULL); 116 ASSERT(node_sequence_ == NULL);
117 ASSERT(node_sequence != NULL); 117 ASSERT(node_sequence != NULL);
118 node_sequence_ = node_sequence; 118 node_sequence_ = node_sequence;
119 } 119 }
120 120
121 121
122 LocalVariable* ParsedFunction::GetSavedArgumentsDescriptorVar() const {
123 const int num_parameters = function().NumberOfParameters();
124 LocalScope* scope = node_sequence()->scope();
125 if (scope->num_variables() > num_parameters) {
126 LocalVariable* saved_args_desc_var = scope->VariableAt(num_parameters);
127 ASSERT(saved_args_desc_var != NULL);
128 // The scope of the formal parameters may also contain at this position
129 // an alias for the saved arguments descriptor variable of the enclosing
130 // function (check its scope owner) or an internal variable such as the
131 // expression temp variable or the saved entry context variable (check its
132 // name).
133 if ((saved_args_desc_var->owner() == scope) &&
134 saved_args_desc_var->name().StartsWith(
135 String::Handle(Symbols::SavedArgDescVarPrefix()))) {
136 return saved_args_desc_var;
137 }
138 }
139 return NULL;
140 }
141
142
122 void ParsedFunction::AllocateVariables() { 143 void ParsedFunction::AllocateVariables() {
123 LocalScope* scope = node_sequence()->scope(); 144 LocalScope* scope = node_sequence()->scope();
124 const int fixed_parameter_count = function().num_fixed_parameters(); 145 const int fixed_parameter_count = function().num_fixed_parameters();
125 const int optional_parameter_count = function().num_optional_parameters(); 146 const int optional_parameter_count = function().num_optional_parameters();
126 const int parameter_count = fixed_parameter_count + optional_parameter_count; 147 int parameter_count = fixed_parameter_count + optional_parameter_count;
127 const bool is_native_instance_closure = 148 const bool is_native_instance_closure =
128 function().is_native() && function().IsImplicitInstanceClosureFunction(); 149 function().is_native() && function().IsImplicitInstanceClosureFunction();
129 // Compute start indices to parameters and locals, and the number of 150 // Compute start indices to parameters and locals, and the number of
130 // parameters to copy. 151 // parameters to copy.
131 if (optional_parameter_count == 0 && !is_native_instance_closure) { 152 if ((optional_parameter_count == 0) && !is_native_instance_closure) {
132 // Parameter i will be at fp[1 + parameter_count - i] and local variable 153 // Parameter i will be at fp[1 + parameter_count - i] and local variable
133 // j will be at fp[kFirstLocalSlotIndex - j]. 154 // j will be at fp[kFirstLocalSlotIndex - j].
155 ASSERT(GetSavedArgumentsDescriptorVar() == NULL);
134 first_parameter_index_ = 1 + parameter_count; 156 first_parameter_index_ = 1 + parameter_count;
135 first_stack_local_index_ = kFirstLocalSlotIndex; 157 first_stack_local_index_ = kFirstLocalSlotIndex;
136 copied_parameter_count_ = 0; 158 copied_parameter_count_ = 0;
137 } else { 159 } else {
138 // Parameter i will be at fp[kFirstLocalSlotIndex - i] and local variable 160 // Parameter i will be at fp[kFirstLocalSlotIndex - i] and local variable
139 // j will be at fp[kFirstLocalSlotIndex - parameter_count - j]. 161 // j will be at fp[kFirstLocalSlotIndex - parameter_count - j].
162 // The saved argument descriptor variable must be allocated similarly to
163 // a parameter, so that it gets both a frame slot and a context slot when
164 // captured.
165 if (GetSavedArgumentsDescriptorVar() != NULL) {
166 parameter_count += 1;
167 }
140 first_parameter_index_ = kFirstLocalSlotIndex; 168 first_parameter_index_ = kFirstLocalSlotIndex;
141 first_stack_local_index_ = first_parameter_index_ - parameter_count; 169 first_stack_local_index_ = first_parameter_index_ - parameter_count;
142 copied_parameter_count_ = parameter_count; 170 copied_parameter_count_ = parameter_count;
143 if (is_native_instance_closure) { 171 if (is_native_instance_closure) {
144 copied_parameter_count_ += 1; 172 copied_parameter_count_ += 1;
145 first_parameter_index_ -= 1; 173 first_parameter_index_ -= 1;
146 first_stack_local_index_ -= 1; 174 first_stack_local_index_ -= 1;
147 } 175 }
148 } 176 }
149 177
150 // Allocate parameters and local variables, either in the local frame or 178 // Allocate parameters and local variables, either in the local frame or
151 // in the context(s). 179 // in the context(s).
152 LocalScope* context_owner = NULL; // No context needed yet. 180 LocalScope* context_owner = NULL; // No context needed yet.
153 int next_free_frame_index = 181 int next_free_frame_index =
154 scope->AllocateVariables(first_parameter_index_, 182 scope->AllocateVariables(first_parameter_index_,
155 parameter_count, 183 parameter_count,
156 first_stack_local_index_, 184 first_stack_local_index_,
157 scope, 185 scope,
158 &context_owner); 186 &context_owner);
159 187
160 // If this function is not a closure function and if it contains captured 188 // If this function is not a closure function and if it contains captured
161 // variables, the context needs to be saved on entry and restored on exit. 189 // variables, the context needs to be saved on entry and restored on exit.
162 // Add and allocate a local variable to this purpose. 190 // Add and allocate a local variable to this purpose.
163 if ((context_owner != NULL) && !function().IsClosureFunction()) { 191 if ((context_owner != NULL) && !function().IsClosureFunction()) {
164 const String& context_var_name = String::ZoneHandle( 192 const String& context_var_name =
165 Symbols::New(LocalVariable::kSavedContextVarName)); 193 String::ZoneHandle(Symbols::SavedEntryContextVar());
166 LocalVariable* context_var = 194 LocalVariable* context_var =
167 new LocalVariable(function().token_pos(), 195 new LocalVariable(function().token_pos(),
168 context_var_name, 196 context_var_name,
169 Type::ZoneHandle(Type::DynamicType())); 197 Type::ZoneHandle(Type::DynamicType()));
170 context_var->set_index(next_free_frame_index--); 198 context_var->set_index(next_free_frame_index--);
171 scope->AddVariable(context_var); 199 scope->AddVariable(context_var);
172 set_saved_context_var(context_var); 200 set_saved_context_var(context_var);
173 } 201 }
174 202
175 // Frame indices are relative to the frame pointer and are decreasing. 203 // Frame indices are relative to the frame pointer and are decreasing.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 token_kind_(Token::kILLEGAL), 282 token_kind_(Token::kILLEGAL),
255 current_block_(NULL), 283 current_block_(NULL),
256 is_top_level_(false), 284 is_top_level_(false),
257 current_member_(NULL), 285 current_member_(NULL),
258 allow_function_literals_(true), 286 allow_function_literals_(true),
259 current_function_(function), 287 current_function_(function),
260 innermost_function_(Function::Handle(function.raw())), 288 innermost_function_(Function::Handle(function.raw())),
261 current_class_(Class::Handle(current_function_.Owner())), 289 current_class_(Class::Handle(current_function_.Owner())),
262 library_(Library::Handle(current_class_.library())), 290 library_(Library::Handle(current_class_.library())),
263 try_blocks_list_(NULL), 291 try_blocks_list_(NULL),
264 expression_temp_(NULL) { 292 expression_temp_(NULL) {
265 ASSERT(tokens_iterator_.IsValid()); 293 ASSERT(tokens_iterator_.IsValid());
266 ASSERT(!function.IsNull()); 294 ASSERT(!function.IsNull());
267 if (FLAG_enable_type_checks) { 295 if (FLAG_enable_type_checks) {
268 EnsureExpressionTemp(); 296 EnsureExpressionTemp();
269 } 297 }
270 } 298 }
271 299
272 300
273 bool Parser::SetAllowFunctionLiterals(bool value) { 301 bool Parser::SetAllowFunctionLiterals(bool value) {
274 bool current_value = allow_function_literals_; 302 bool current_value = allow_function_literals_;
(...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 } 1154 }
1127 1155
1128 1156
1129 void Parser::ParseFormalParameterList(bool allow_explicit_default_values, 1157 void Parser::ParseFormalParameterList(bool allow_explicit_default_values,
1130 ParamList* params) { 1158 ParamList* params) {
1131 TRACE_PARSER("ParseFormalParameterList"); 1159 TRACE_PARSER("ParseFormalParameterList");
1132 ASSERT(CurrentToken() == Token::kLPAREN); 1160 ASSERT(CurrentToken() == Token::kLPAREN);
1133 1161
1134 if (LookaheadToken(1) != Token::kRPAREN) { 1162 if (LookaheadToken(1) != Token::kRPAREN) {
1135 // Parse positional parameters. 1163 // Parse positional parameters.
1136 ParseFormalParameters(allow_explicit_default_values, 1164 ParseFormalParameters(allow_explicit_default_values, params);
1137 params);
1138 if (params->has_named_optional_parameters) { 1165 if (params->has_named_optional_parameters) {
1139 // Parse named optional parameters. 1166 // Parse named optional parameters.
1140 ParseFormalParameters(allow_explicit_default_values, 1167 ParseFormalParameters(allow_explicit_default_values, params);
1141 params);
1142 if (CurrentToken() != Token::kRBRACK) { 1168 if (CurrentToken() != Token::kRBRACK) {
1143 ErrorMsg("',' or ']' expected"); 1169 ErrorMsg("',' or ']' expected");
1144 } 1170 }
1145 ExpectToken(Token::kRBRACK); 1171 ExpectToken(Token::kRBRACK);
1146 } 1172 }
1147 if ((CurrentToken() != Token::kRPAREN) && 1173 if ((CurrentToken() != Token::kRPAREN) &&
1148 !params->has_named_optional_parameters) { 1174 !params->has_named_optional_parameters) {
1149 ErrorMsg("',' or ')' expected"); 1175 ErrorMsg("',' or ')' expected");
1150 } 1176 }
1151 } else { 1177 } else {
(...skipping 6197 matching lines...) Expand 10 before | Expand all | Expand 10 after
7349 LocalVariable* Parser::LookupLocalScope(const String& ident) { 7375 LocalVariable* Parser::LookupLocalScope(const String& ident) {
7350 if (current_block_ == NULL) { 7376 if (current_block_ == NULL) {
7351 return NULL; 7377 return NULL;
7352 } 7378 }
7353 // A found name is treated as accessed and possibly marked as captured. 7379 // A found name is treated as accessed and possibly marked as captured.
7354 const bool kTestOnly = false; 7380 const bool kTestOnly = false;
7355 return current_block_->scope->LookupVariable(ident, kTestOnly); 7381 return current_block_->scope->LookupVariable(ident, kTestOnly);
7356 } 7382 }
7357 7383
7358 7384
7385 // Returns true if ident resolves to a formal parameter of the current function
7386 // or of one of its enclosing functions.
7387 // Make sure not to capture the formal parameter, since it is not accessed.
7388 bool Parser::IsFormalParameter(const String& ident,
7389 Function* owner_function,
7390 LocalScope** owner_scope,
7391 intptr_t* local_index) {
7392 if (current_block_ == NULL) {
7393 return false;
7394 }
7395 if (ident.Equals(String::Handle(Symbols::This()))) {
7396 // 'this' is not a formal parameter.
7397 return false;
7398 }
7399 // Since an argument definition test does not use the value of the formal
7400 // parameter, there is no reason to capture it.
7401 const bool kTestOnly = true; // No capturing.
7402 LocalVariable* local =
7403 current_block_->scope->LookupVariable(ident, kTestOnly);
7404 if (local == NULL) {
7405 if (!current_function().IsLocalFunction()) {
7406 // We are not generating code for a local function, so all locals,
7407 // captured or not, are in scope. However, 'ident' was not found, so it
7408 // does not exist.
7409 return false;
7410 }
7411 // The formal parameter may belong to an enclosing function and may not have
7412 // been captured, so it was not included in the context scope and it cannot
7413 // be found by LookupVariable.
7414 // 'ident' necessarily refers to the formal parameter of one of the
7415 // enclosing functions, or a compile error would have prevented the
7416 // outermost enclosing function to be executed and we would not be compiling
7417 // this local function.
7418 // Therefore, look for ident directly in the formal parameter lists of the
7419 // enclosing functions.
7420 // There is no need to return the owner_scope, since the caller will not
7421 // create the saved_arguments_descriptor variable, which already exists.
7422 Function& function = Function::Handle(innermost_function().raw());
7423 String& param_name = String::Handle();
7424 do {
7425 const int num_parameters = function.NumberOfParameters();
7426 for (intptr_t i = 0; i < num_parameters; i++) {
7427 param_name = function.ParameterNameAt(i);
7428 if (ident.Equals(param_name)) {
7429 *owner_function = function.raw();
7430 *owner_scope = NULL;
7431 *local_index = i;
7432 return true;
7433 }
7434 }
7435 function = function.parent_function();
7436 } while (!function.IsNull());
7437 UNREACHABLE();
hausner 2012/08/31 00:34:55 Is this really unreachable? What if the name refer
regis 2012/08/31 01:36:18 Indeed, you missed the comment on line 7414 explai
7438 }
7439 // Verify that local is a formal parameter of the current function or of one
7440 // of its enclosing functions.
7441 // Note that scopes are not yet associated to functions.
7442 Function& function = Function::Handle(innermost_function().raw());
7443 LocalScope* scope = current_block_->scope;
7444 while (scope != NULL) {
7445 ASSERT(!function.IsNull());
7446 // Find the top scope for this function level.
7447 while ((scope->parent() != NULL) &&
7448 (scope->parent()->function_level() == scope->function_level())) {
7449 scope = scope->parent();
7450 }
7451 if (scope == local->owner()) {
7452 // Scope contains 'local' and the formal parameters of 'function'.
7453 const int num_parameters = function.NumberOfParameters();
7454 for (intptr_t i = 0; i < num_parameters; i++) {
7455 if (scope->VariableAt(i) == local) {
7456 *owner_function = function.raw();
7457 *owner_scope = scope;
7458 *local_index = i;
7459 return true;
7460 }
7461 }
7462 // The variable 'local' is not a formal parameter.
7463 return false;
7464 }
7465 scope = scope->parent();
7466 function = function.parent_function();
7467 }
7468 // The variable 'local' does not belong to a function top scope.
7469 return false;
7470 }
7471
7472
7359 void Parser::CheckInstanceFieldAccess(intptr_t field_pos, 7473 void Parser::CheckInstanceFieldAccess(intptr_t field_pos,
7360 const String& field_name) { 7474 const String& field_name) {
7361 // Fields are not accessible from a static function, except from a 7475 // Fields are not accessible from a static function, except from a
7362 // constructor, which is considered as non-static by the compiler. 7476 // constructor, which is considered as non-static by the compiler.
7363 if (current_function().is_static()) { 7477 if (current_function().is_static()) {
7364 ErrorMsg(field_pos, 7478 ErrorMsg(field_pos,
7365 "cannot access instance field '%s' from a static function", 7479 "cannot access instance field '%s' from a static function",
7366 field_name.ToCString()); 7480 field_name.ToCString());
7367 } 7481 }
7368 } 7482 }
(...skipping 1452 matching lines...) Expand 10 before | Expand all | Expand 10 after
8821 ConsumeToken(); 8935 ConsumeToken();
8822 } 8936 }
8823 } 8937 }
8824 // A string literal always ends with a kSTRING token. 8938 // A string literal always ends with a kSTRING token.
8825 ASSERT(CurrentToken() == Token::kSTRING); 8939 ASSERT(CurrentToken() == Token::kSTRING);
8826 } 8940 }
8827 return &result; 8941 return &result;
8828 } 8942 }
8829 8943
8830 8944
8945 AstNode* Parser::ParseArgumentDefinitionTest() {
8946 const intptr_t test_pos = TokenPos();
8947 ConsumeToken();
8948 const intptr_t ident_pos = TokenPos();
8949 String* ident = ExpectIdentifier("parameter name expected");
8950 Function& owner_function = Function::Handle();
8951 LocalScope* owner_scope;
8952 intptr_t param_index;
8953 if (!IsFormalParameter(*ident, &owner_function, &owner_scope, &param_index)) {
8954 ErrorMsg(ident_pos, "formal parameter name expected");
8955 }
8956 if (param_index < owner_function.num_fixed_parameters()) {
8957 // The formal parameter is not optional, therefore the corresponding
8958 // argument is always passed and defined.
8959 return new LiteralNode(test_pos, Bool::ZoneHandle(Bool::True()));
8960 }
8961 char name[64];
8962 OS::SNPrint(name, 64, "%s_%d",
8963 Symbols::Name(Symbols::kSavedArgDescVarPrefix),
8964 owner_function.token_pos());
8965 const String& saved_args_desc_name = String::ZoneHandle(Symbols::New(name));
8966 LocalVariable* saved_args_desc_var = LookupLocalScope(saved_args_desc_name);
8967 if (saved_args_desc_var == NULL) {
8968 ASSERT(owner_scope != NULL);
8969 ASSERT(owner_function.raw() == current_function().raw());
8970 // We currently generate code for 'owner_function', otherwise the variable
8971 // would have been created when compiling the enclosing function of the
8972 // currently being compiled local function.
8973 saved_args_desc_var =
8974 new LocalVariable(owner_function.token_pos(),
8975 saved_args_desc_name,
8976 Type::ZoneHandle(Type::ListInterface()));
8977 saved_args_desc_var->set_is_final();
8978 // The saved arguments descriptor variable must be added just after the
8979 // formal parameters. This simplifies the 2-step saving of a captured
8980 // arguments descriptor.
8981 // At this time, the owner scope should only contain formal parameters.
8982 ASSERT(owner_scope->num_variables() == owner_function.NumberOfParameters());
8983 bool success = owner_scope->AddVariable(saved_args_desc_var);
8984 ASSERT(success);
8985 // Capture the saved argument descriptor variable if necessary.
8986 if (current_function().raw() != innermost_function().raw()) {
8987 LocalVariable* local = LookupLocalScope(saved_args_desc_name);
8988 ASSERT(local == saved_args_desc_var);
8989 ASSERT(local->is_captured());
8990 }
8991 } else {
8992 // If we currently generate code for a local function of the owner function,
8993 // the saved arguments descriptor variable must have been captured by the
8994 // above lookup.
8995 ASSERT((owner_function.raw() == current_function().raw()) ||
8996 saved_args_desc_var->is_captured());
8997 }
8998 const String& param_name = String::ZoneHandle(Symbols::New(*ident));
8999 return new ArgumentDefinitionTestNode(
9000 test_pos, param_index, param_name, saved_args_desc_var);
9001 }
9002
9003
8831 AstNode* Parser::ParsePrimary() { 9004 AstNode* Parser::ParsePrimary() {
8832 TRACE_PARSER("ParsePrimary"); 9005 TRACE_PARSER("ParsePrimary");
8833 ASSERT(!is_top_level_); 9006 ASSERT(!is_top_level_);
8834 AstNode* primary = NULL; 9007 AstNode* primary = NULL;
8835 if (IsFunctionLiteral()) { 9008 if (IsFunctionLiteral()) {
8836 // The name of a literal function is visible from inside the function, but 9009 // The name of a literal function is visible from inside the function, but
8837 // must not collide with names in the scope declaring the literal. 9010 // must not collide with names in the scope declaring the literal.
8838 OpenBlock(); 9011 OpenBlock();
8839 primary = ParseFunctionStatement(true); 9012 primary = ParseFunctionStatement(true);
8840 CloseBlock(); 9013 CloseBlock();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
8940 primary = ParseSuperCall(ident); 9113 primary = ParseSuperCall(ident);
8941 } else { 9114 } else {
8942 primary = ParseSuperFieldAccess(ident); 9115 primary = ParseSuperFieldAccess(ident);
8943 } 9116 }
8944 } else if ((CurrentToken() == Token::kLBRACK) || 9117 } else if ((CurrentToken() == Token::kLBRACK) ||
8945 Token::CanBeOverloaded(CurrentToken())) { 9118 Token::CanBeOverloaded(CurrentToken())) {
8946 primary = ParseSuperOperator(); 9119 primary = ParseSuperOperator();
8947 } else { 9120 } else {
8948 ErrorMsg("illegal super call"); 9121 ErrorMsg("illegal super call");
8949 } 9122 }
9123 } else if (CurrentToken() == Token::kCONDITIONAL) {
9124 primary = ParseArgumentDefinitionTest();
8950 } else { 9125 } else {
8951 UnexpectedToken(); 9126 UnexpectedToken();
8952 } 9127 }
8953 return primary; 9128 return primary;
8954 } 9129 }
8955 9130
8956 9131
8957 // Evaluate expression in expr and return the value. The expression must 9132 // Evaluate expression in expr and return the value. The expression must
8958 // be a compile time constant. 9133 // be a compile time constant.
8959 const Instance& Parser::EvaluateConstExpr(AstNode* expr) { 9134 const Instance& Parser::EvaluateConstExpr(AstNode* expr) {
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
9240 void Parser::SkipQualIdent() { 9415 void Parser::SkipQualIdent() {
9241 ASSERT(IsIdentifier()); 9416 ASSERT(IsIdentifier());
9242 ConsumeToken(); 9417 ConsumeToken();
9243 if (CurrentToken() == Token::kPERIOD) { 9418 if (CurrentToken() == Token::kPERIOD) {
9244 ConsumeToken(); // Consume the kPERIOD token. 9419 ConsumeToken(); // Consume the kPERIOD token.
9245 ExpectIdentifier("identifier expected after '.'"); 9420 ExpectIdentifier("identifier expected after '.'");
9246 } 9421 }
9247 } 9422 }
9248 9423
9249 } // namespace dart 9424 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scopes.h » ('j') | runtime/vm/scopes.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698