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

Side by Side Diff: src/parser.cc

Issue 27128: Go into slow case when encountering object initialization on the top level to... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 9 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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 62
63 63
64 // Returns NULL if parsing failed. 64 // Returns NULL if parsing failed.
65 FunctionLiteral* ParseProgram(Handle<String> source, 65 FunctionLiteral* ParseProgram(Handle<String> source,
66 unibrow::CharacterStream* stream, 66 unibrow::CharacterStream* stream,
67 bool in_global_context); 67 bool in_global_context);
68 FunctionLiteral* ParseLazy(Handle<String> source, 68 FunctionLiteral* ParseLazy(Handle<String> source,
69 Handle<String> name, 69 Handle<String> name,
70 int start_position, bool is_expression); 70 int start_position, bool is_expression);
71 71
72 // The minimum number of contiguous assignment that is needed to
73 // be treated as an initialization block.
74 static const int kMinInitializationBlock = 3;
Mads Ager (chromium) 2009/02/25 13:11:07 Is this limit based on benchmarking? We should ma
olehougaard 2009/02/26 07:31:44 It's based on benchmarking. I've added a comment t
75
72 protected: 76 protected:
73 77
74 enum Mode { 78 enum Mode {
75 PARSE_LAZILY, 79 PARSE_LAZILY,
76 PARSE_EAGERLY 80 PARSE_EAGERLY
77 }; 81 };
78 82
79 // Report syntax error 83 // Report syntax error
80 void ReportUnexpectedToken(Token::Value token); 84 void ReportUnexpectedToken(Token::Value token);
81 85
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 } 1212 }
1209 1213
1210 1214
1211 void PreParser::ReportMessageAt(Scanner::Location source_location, 1215 void PreParser::ReportMessageAt(Scanner::Location source_location,
1212 const char* type, 1216 const char* type,
1213 Vector<const char*> args) { 1217 Vector<const char*> args) {
1214 recorder()->LogMessage(source_location, type, args); 1218 recorder()->LogMessage(source_location, type, args);
1215 } 1219 }
1216 1220
1217 1221
1222 // An InitializationBlockFinder finds and marks sequences of statements of the
1223 // form x.y.z.a = ...; x.y.z.b = ...; etc.
1224 class InitializationBlockFinder {
1225 public:
1226 InitializationBlockFinder()
1227 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
1228
1229 ~InitializationBlockFinder() {
1230 if (InBlock()) EndBlock();
1231 }
1232
1233 void Update(Statement* stat) {
1234 Assignment* assignment = AsAssignment(stat);
1235 if (InBlock()) {
1236 if (BlockContinues(assignment)) {
1237 UpdateBlock(assignment);
1238 } else {
1239 EndBlock();
1240 }
1241 }
1242 if (!InBlock() && (assignment != NULL)) StartBlock(assignment);
Mads Ager (chromium) 2009/02/25 13:11:07 In BlockContinues, you check if the operation is T
olehougaard 2009/02/26 07:31:44 Fixed.
1243 }
1244
1245 private:
1246 static Assignment* AsAssignment(Statement* stat) {
1247 if (stat == NULL) return NULL;
1248 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
1249 if (exp_stat == NULL) return NULL;
1250 return exp_stat->expression()->AsAssignment();
1251 }
1252
1253 // Returns true if the expressions appear to denote the same object.
1254 // In the context of initialization blocks, we only consider expressions
1255 // of the form 'x.y.z'.
1256 static bool SameObject(Expression* e1, Expression* e2);
1257
1258 // Returns true if the expressions appear to denote different properties
1259 // of the same object.
1260 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
1261 Property* p1 = e1->AsProperty();
1262 Property* p2 = e2->AsProperty();
1263 if (p1 == NULL || p2 == NULL) return false;
1264 return SameObject(p1->obj(), p2->obj());
1265 }
1266
1267 bool BlockContinues(Assignment* assignment) {
1268 if (assignment == NULL || first_in_block_ == NULL) return false;
1269 if (assignment->op() != Token::ASSIGN) return false;
iposva 2009/02/25 12:54:45 You check here that only ASSIGN statements are add
olehougaard 2009/02/26 07:31:44 Fixed.
1270 return PropertyOfSameObject(first_in_block_->target(),
1271 assignment->target());
1272 }
1273
1274 void StartBlock(Assignment* assignment) {
1275 first_in_block_ = assignment;
1276 last_in_block_ = assignment;
1277 block_size_ = 1;
1278 }
1279
1280 void UpdateBlock(Assignment* assignment) {
1281 last_in_block_ = assignment;
1282 ++block_size_;
1283 }
1284
1285 void EndBlock() {
1286 if (block_size_ >= Parser::kMinInitializationBlock) {
1287 first_in_block_->mark_block_start();
1288 last_in_block_->mark_block_end();
1289 }
1290 last_in_block_ = first_in_block_ = NULL;
1291 block_size_ = 0;
1292 }
1293
1294 bool InBlock() { return first_in_block_ != NULL; }
1295
1296 Assignment* first_in_block_;
1297 Assignment* last_in_block_;
1298 int block_size_;
1299
1300 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
1301 };
1302
1303
1304 bool InitializationBlockFinder::SameObject(Expression* e1, Expression* e2) {
iposva 2009/02/25 12:54:45 What made you put this method outside the class de
olehougaard 2009/02/26 07:31:44 I've put all the code in the declaration for consi
1305 VariableProxy* v1 = e1->AsVariableProxy();
1306 VariableProxy* v2 = e2->AsVariableProxy();
1307 if (v1 != NULL && v2 != NULL) {
iposva 2009/02/25 12:54:45 In general I find code more readable when () are a
olehougaard 2009/02/26 07:31:44 Fixed where found.
1308 return v1->name()->Equals(*v2->name());
1309 }
1310 Property* p1 = e1->AsProperty();
1311 Property* p2 = e2->AsProperty();
1312 if (p1 == NULL || p2 == NULL) return false;
1313 Literal* key1 = p1->key()->AsLiteral();
1314 Literal* key2 = p2->key()->AsLiteral();
1315 if (key1 == NULL || key2 == NULL) return false;
1316 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
1317 return false;
1318 }
1319 String* name1 = String::cast(*key1->handle());
1320 String* name2 = String::cast(*key2->handle());
1321 if (!name1->Equals(name2)) return false;
1322 return SameObject(p1->obj(), p2->obj());
1323 }
1324
1325
1218 void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor, 1326 void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,
1219 int end_token, 1327 int end_token,
1220 bool* ok) { 1328 bool* ok) {
1221 // SourceElements :: 1329 // SourceElements ::
1222 // (Statement)* <end_token> 1330 // (Statement)* <end_token>
1223 1331
1224 // Allocate a target stack to use for this set of source 1332 // Allocate a target stack to use for this set of source
1225 // elements. This way, all scripts and functions get their own 1333 // elements. This way, all scripts and functions get their own
1226 // target stack thus avoiding illegal breaks and continues across 1334 // target stack thus avoiding illegal breaks and continues across
1227 // functions. 1335 // functions.
1228 TargetScope scope(this); 1336 TargetScope scope(this);
1229 1337
1230 ASSERT(processor != NULL); 1338 ASSERT(processor != NULL);
1339 InitializationBlockFinder block_finder;
1231 while (peek() != end_token) { 1340 while (peek() != end_token) {
1232 Statement* stat = ParseStatement(NULL, CHECK_OK); 1341 Statement* stat = ParseStatement(NULL, CHECK_OK);
1233 if (stat && !stat->IsEmpty()) processor->Add(stat); 1342 if (stat == NULL || stat->IsEmpty()) continue;
1343 // We find and mark the initialization blocks on top level code only.
1344 // The optimizations of initialization blocks may result in a performance
1345 // degradation in any other scopes.
Mads Ager (chromium) 2009/02/25 13:11:07 You should write here that the reason for only doi
olehougaard 2009/02/26 07:31:44 Fixed.
1346 if (top_scope_->is_global_scope()) block_finder.Update(stat);
1347 processor->Add(stat);
1234 } 1348 }
1235 return 0; 1349 return 0;
1236 } 1350 }
1237 1351
1238 1352
1239 Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { 1353 Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1240 // Statement :: 1354 // Statement ::
1241 // Block 1355 // Block
1242 // VariableStatement 1356 // VariableStatement
1243 // EmptyStatement 1357 // EmptyStatement
(...skipping 3152 matching lines...) Expand 10 before | Expand all | Expand 10 after
4396 start_position, 4510 start_position,
4397 is_expression); 4511 is_expression);
4398 return result; 4512 return result;
4399 } 4513 }
4400 4514
4401 4515
4402 #undef NEW 4516 #undef NEW
4403 4517
4404 4518
4405 } } // namespace v8::internal 4519 } } // namespace v8::internal
OLDNEW
« src/codegen-ia32.cc ('K') | « src/codegen-ia32.cc ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698