ast.cc revision 9ac36c9faca11611ada13b4054edbaa0738661d0
1// Copyright 2010 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include "v8.h" 29 30#include "ast.h" 31#include "parser.h" 32#include "scopes.h" 33#include "string-stream.h" 34#include "ast-inl.h" 35#include "jump-target-inl.h" 36 37namespace v8 { 38namespace internal { 39 40 41VariableProxySentinel VariableProxySentinel::this_proxy_(true); 42VariableProxySentinel VariableProxySentinel::identifier_proxy_(false); 43ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_; 44Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0); 45Call Call::sentinel_(NULL, NULL, 0); 46 47 48// ---------------------------------------------------------------------------- 49// All the Accept member functions for each syntax tree node type. 50 51#define DECL_ACCEPT(type) \ 52 void type::Accept(AstVisitor* v) { v->Visit##type(this); } 53AST_NODE_LIST(DECL_ACCEPT) 54#undef DECL_ACCEPT 55 56 57// ---------------------------------------------------------------------------- 58// Implementation of other node functionality. 59 60Assignment* ExpressionStatement::StatementAsSimpleAssignment() { 61 return (expression()->AsAssignment() != NULL && 62 !expression()->AsAssignment()->is_compound()) 63 ? expression()->AsAssignment() 64 : NULL; 65} 66 67 68CountOperation* ExpressionStatement::StatementAsCountOperation() { 69 return expression()->AsCountOperation(); 70} 71 72 73VariableProxy::VariableProxy(Handle<String> name, 74 bool is_this, 75 bool inside_with) 76 : name_(name), 77 var_(NULL), 78 is_this_(is_this), 79 inside_with_(inside_with), 80 is_trivial_(false) { 81 // names must be canonicalized for fast equality checks 82 ASSERT(name->IsSymbol()); 83} 84 85 86VariableProxy::VariableProxy(bool is_this) 87 : var_(NULL), 88 is_this_(is_this), 89 inside_with_(false), 90 is_trivial_(false) { 91} 92 93 94void VariableProxy::BindTo(Variable* var) { 95 ASSERT(var_ == NULL); // must be bound only once 96 ASSERT(var != NULL); // must bind 97 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name())); 98 // Ideally CONST-ness should match. However, this is very hard to achieve 99 // because we don't know the exact semantics of conflicting (const and 100 // non-const) multiple variable declarations, const vars introduced via 101 // eval() etc. Const-ness and variable declarations are a complete mess 102 // in JS. Sigh... 103 var_ = var; 104 var->set_is_used(true); 105} 106 107 108Token::Value Assignment::binary_op() const { 109 switch (op_) { 110 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; 111 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; 112 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; 113 case Token::ASSIGN_SHL: return Token::SHL; 114 case Token::ASSIGN_SAR: return Token::SAR; 115 case Token::ASSIGN_SHR: return Token::SHR; 116 case Token::ASSIGN_ADD: return Token::ADD; 117 case Token::ASSIGN_SUB: return Token::SUB; 118 case Token::ASSIGN_MUL: return Token::MUL; 119 case Token::ASSIGN_DIV: return Token::DIV; 120 case Token::ASSIGN_MOD: return Token::MOD; 121 default: UNREACHABLE(); 122 } 123 return Token::ILLEGAL; 124} 125 126 127bool FunctionLiteral::AllowsLazyCompilation() { 128 return scope()->AllowsLazyCompilation(); 129} 130 131 132ObjectLiteral::Property::Property(Literal* key, Expression* value) { 133 key_ = key; 134 value_ = value; 135 Object* k = *key->handle(); 136 if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) { 137 kind_ = PROTOTYPE; 138 } else if (value_->AsMaterializedLiteral() != NULL) { 139 kind_ = MATERIALIZED_LITERAL; 140 } else if (value_->AsLiteral() != NULL) { 141 kind_ = CONSTANT; 142 } else { 143 kind_ = COMPUTED; 144 } 145} 146 147 148ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) { 149 key_ = new Literal(value->name()); 150 value_ = value; 151 kind_ = is_getter ? GETTER : SETTER; 152} 153 154 155bool ObjectLiteral::Property::IsCompileTimeValue() { 156 return kind_ == CONSTANT || 157 (kind_ == MATERIALIZED_LITERAL && 158 CompileTimeValue::IsCompileTimeValue(value_)); 159} 160 161 162void TargetCollector::AddTarget(BreakTarget* target) { 163 // Add the label to the collector, but discard duplicates. 164 int length = targets_->length(); 165 for (int i = 0; i < length; i++) { 166 if (targets_->at(i) == target) return; 167 } 168 targets_->Add(target); 169} 170 171 172bool Expression::GuaranteedSmiResult() { 173 BinaryOperation* node = AsBinaryOperation(); 174 if (node == NULL) return false; 175 Token::Value op = node->op(); 176 switch (op) { 177 case Token::COMMA: 178 case Token::OR: 179 case Token::AND: 180 case Token::ADD: 181 case Token::SUB: 182 case Token::MUL: 183 case Token::DIV: 184 case Token::MOD: 185 case Token::BIT_XOR: 186 case Token::SHL: 187 return false; 188 break; 189 case Token::BIT_OR: 190 case Token::BIT_AND: { 191 Literal* left = node->left()->AsLiteral(); 192 Literal* right = node->right()->AsLiteral(); 193 if (left != NULL && left->handle()->IsSmi()) { 194 int value = Smi::cast(*left->handle())->value(); 195 if (op == Token::BIT_OR && ((value & 0xc0000000) == 0xc0000000)) { 196 // Result of bitwise or is always a negative Smi. 197 return true; 198 } 199 if (op == Token::BIT_AND && ((value & 0xc0000000) == 0)) { 200 // Result of bitwise and is always a positive Smi. 201 return true; 202 } 203 } 204 if (right != NULL && right->handle()->IsSmi()) { 205 int value = Smi::cast(*right->handle())->value(); 206 if (op == Token::BIT_OR && ((value & 0xc0000000) == 0xc0000000)) { 207 // Result of bitwise or is always a negative Smi. 208 return true; 209 } 210 if (op == Token::BIT_AND && ((value & 0xc0000000) == 0)) { 211 // Result of bitwise and is always a positive Smi. 212 return true; 213 } 214 } 215 return false; 216 break; 217 } 218 case Token::SAR: 219 case Token::SHR: { 220 Literal* right = node->right()->AsLiteral(); 221 if (right != NULL && right->handle()->IsSmi()) { 222 int value = Smi::cast(*right->handle())->value(); 223 if ((value & 0x1F) > 1 || 224 (op == Token::SAR && (value & 0x1F) == 1)) { 225 return true; 226 } 227 } 228 return false; 229 break; 230 } 231 default: 232 UNREACHABLE(); 233 break; 234 } 235 return false; 236} 237 238 239void Expression::CopyAnalysisResultsFrom(Expression* other) { 240 bitfields_ = other->bitfields_; 241 type_ = other->type_; 242} 243 244 245bool UnaryOperation::ResultOverwriteAllowed() { 246 switch (op_) { 247 case Token::BIT_NOT: 248 case Token::SUB: 249 return true; 250 default: 251 return false; 252 } 253} 254 255 256bool BinaryOperation::ResultOverwriteAllowed() { 257 switch (op_) { 258 case Token::COMMA: 259 case Token::OR: 260 case Token::AND: 261 return false; 262 case Token::BIT_OR: 263 case Token::BIT_XOR: 264 case Token::BIT_AND: 265 case Token::SHL: 266 case Token::SAR: 267 case Token::SHR: 268 case Token::ADD: 269 case Token::SUB: 270 case Token::MUL: 271 case Token::DIV: 272 case Token::MOD: 273 return true; 274 default: 275 UNREACHABLE(); 276 } 277 return false; 278} 279 280 281BinaryOperation::BinaryOperation(Assignment* assignment) { 282 ASSERT(assignment->is_compound()); 283 op_ = assignment->binary_op(); 284 left_ = assignment->target(); 285 right_ = assignment->value(); 286 pos_ = assignment->position(); 287 CopyAnalysisResultsFrom(assignment); 288} 289 290 291// ---------------------------------------------------------------------------- 292// Implementation of AstVisitor 293 294bool AstVisitor::CheckStackOverflow() { 295 if (stack_overflow_) return true; 296 StackLimitCheck check; 297 if (!check.HasOverflowed()) return false; 298 return (stack_overflow_ = true); 299} 300 301 302void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) { 303 for (int i = 0; i < declarations->length(); i++) { 304 Visit(declarations->at(i)); 305 } 306} 307 308 309void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) { 310 for (int i = 0; i < statements->length(); i++) { 311 Visit(statements->at(i)); 312 } 313} 314 315 316void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) { 317 for (int i = 0; i < expressions->length(); i++) { 318 // The variable statement visiting code may pass NULL expressions 319 // to this code. Maybe this should be handled by introducing an 320 // undefined expression or literal? Revisit this code if this 321 // changes 322 Expression* expression = expressions->at(i); 323 if (expression != NULL) Visit(expression); 324 } 325} 326 327 328// ---------------------------------------------------------------------------- 329// Regular expressions 330 331#define MAKE_ACCEPT(Name) \ 332 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \ 333 return visitor->Visit##Name(this, data); \ 334 } 335FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT) 336#undef MAKE_ACCEPT 337 338#define MAKE_TYPE_CASE(Name) \ 339 RegExp##Name* RegExpTree::As##Name() { \ 340 return NULL; \ 341 } \ 342 bool RegExpTree::Is##Name() { return false; } 343FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) 344#undef MAKE_TYPE_CASE 345 346#define MAKE_TYPE_CASE(Name) \ 347 RegExp##Name* RegExp##Name::As##Name() { \ 348 return this; \ 349 } \ 350 bool RegExp##Name::Is##Name() { return true; } 351FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) 352#undef MAKE_TYPE_CASE 353 354RegExpEmpty RegExpEmpty::kInstance; 355 356 357static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) { 358 Interval result = Interval::Empty(); 359 for (int i = 0; i < children->length(); i++) 360 result = result.Union(children->at(i)->CaptureRegisters()); 361 return result; 362} 363 364 365Interval RegExpAlternative::CaptureRegisters() { 366 return ListCaptureRegisters(nodes()); 367} 368 369 370Interval RegExpDisjunction::CaptureRegisters() { 371 return ListCaptureRegisters(alternatives()); 372} 373 374 375Interval RegExpLookahead::CaptureRegisters() { 376 return body()->CaptureRegisters(); 377} 378 379 380Interval RegExpCapture::CaptureRegisters() { 381 Interval self(StartRegister(index()), EndRegister(index())); 382 return self.Union(body()->CaptureRegisters()); 383} 384 385 386Interval RegExpQuantifier::CaptureRegisters() { 387 return body()->CaptureRegisters(); 388} 389 390 391bool RegExpAssertion::IsAnchored() { 392 return type() == RegExpAssertion::START_OF_INPUT; 393} 394 395 396bool RegExpAlternative::IsAnchored() { 397 ZoneList<RegExpTree*>* nodes = this->nodes(); 398 for (int i = 0; i < nodes->length(); i++) { 399 RegExpTree* node = nodes->at(i); 400 if (node->IsAnchored()) { return true; } 401 if (node->max_match() > 0) { return false; } 402 } 403 return false; 404} 405 406 407bool RegExpDisjunction::IsAnchored() { 408 ZoneList<RegExpTree*>* alternatives = this->alternatives(); 409 for (int i = 0; i < alternatives->length(); i++) { 410 if (!alternatives->at(i)->IsAnchored()) 411 return false; 412 } 413 return true; 414} 415 416 417bool RegExpLookahead::IsAnchored() { 418 return is_positive() && body()->IsAnchored(); 419} 420 421 422bool RegExpCapture::IsAnchored() { 423 return body()->IsAnchored(); 424} 425 426 427// Convert regular expression trees to a simple sexp representation. 428// This representation should be different from the input grammar 429// in as many cases as possible, to make it more difficult for incorrect 430// parses to look as correct ones which is likely if the input and 431// output formats are alike. 432class RegExpUnparser: public RegExpVisitor { 433 public: 434 RegExpUnparser(); 435 void VisitCharacterRange(CharacterRange that); 436 SmartPointer<const char> ToString() { return stream_.ToCString(); } 437#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data); 438 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE) 439#undef MAKE_CASE 440 private: 441 StringStream* stream() { return &stream_; } 442 HeapStringAllocator alloc_; 443 StringStream stream_; 444}; 445 446 447RegExpUnparser::RegExpUnparser() : stream_(&alloc_) { 448} 449 450 451void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) { 452 stream()->Add("(|"); 453 for (int i = 0; i < that->alternatives()->length(); i++) { 454 stream()->Add(" "); 455 that->alternatives()->at(i)->Accept(this, data); 456 } 457 stream()->Add(")"); 458 return NULL; 459} 460 461 462void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) { 463 stream()->Add("(:"); 464 for (int i = 0; i < that->nodes()->length(); i++) { 465 stream()->Add(" "); 466 that->nodes()->at(i)->Accept(this, data); 467 } 468 stream()->Add(")"); 469 return NULL; 470} 471 472 473void RegExpUnparser::VisitCharacterRange(CharacterRange that) { 474 stream()->Add("%k", that.from()); 475 if (!that.IsSingleton()) { 476 stream()->Add("-%k", that.to()); 477 } 478} 479 480 481 482void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that, 483 void* data) { 484 if (that->is_negated()) 485 stream()->Add("^"); 486 stream()->Add("["); 487 for (int i = 0; i < that->ranges()->length(); i++) { 488 if (i > 0) stream()->Add(" "); 489 VisitCharacterRange(that->ranges()->at(i)); 490 } 491 stream()->Add("]"); 492 return NULL; 493} 494 495 496void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) { 497 switch (that->type()) { 498 case RegExpAssertion::START_OF_INPUT: 499 stream()->Add("@^i"); 500 break; 501 case RegExpAssertion::END_OF_INPUT: 502 stream()->Add("@$i"); 503 break; 504 case RegExpAssertion::START_OF_LINE: 505 stream()->Add("@^l"); 506 break; 507 case RegExpAssertion::END_OF_LINE: 508 stream()->Add("@$l"); 509 break; 510 case RegExpAssertion::BOUNDARY: 511 stream()->Add("@b"); 512 break; 513 case RegExpAssertion::NON_BOUNDARY: 514 stream()->Add("@B"); 515 break; 516 } 517 return NULL; 518} 519 520 521void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) { 522 stream()->Add("'"); 523 Vector<const uc16> chardata = that->data(); 524 for (int i = 0; i < chardata.length(); i++) { 525 stream()->Add("%k", chardata[i]); 526 } 527 stream()->Add("'"); 528 return NULL; 529} 530 531 532void* RegExpUnparser::VisitText(RegExpText* that, void* data) { 533 if (that->elements()->length() == 1) { 534 that->elements()->at(0).data.u_atom->Accept(this, data); 535 } else { 536 stream()->Add("(!"); 537 for (int i = 0; i < that->elements()->length(); i++) { 538 stream()->Add(" "); 539 that->elements()->at(i).data.u_atom->Accept(this, data); 540 } 541 stream()->Add(")"); 542 } 543 return NULL; 544} 545 546 547void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) { 548 stream()->Add("(# %i ", that->min()); 549 if (that->max() == RegExpTree::kInfinity) { 550 stream()->Add("- "); 551 } else { 552 stream()->Add("%i ", that->max()); 553 } 554 stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n "); 555 that->body()->Accept(this, data); 556 stream()->Add(")"); 557 return NULL; 558} 559 560 561void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) { 562 stream()->Add("(^ "); 563 that->body()->Accept(this, data); 564 stream()->Add(")"); 565 return NULL; 566} 567 568 569void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) { 570 stream()->Add("(-> "); 571 stream()->Add(that->is_positive() ? "+ " : "- "); 572 that->body()->Accept(this, data); 573 stream()->Add(")"); 574 return NULL; 575} 576 577 578void* RegExpUnparser::VisitBackReference(RegExpBackReference* that, 579 void* data) { 580 stream()->Add("(<- %i)", that->index()); 581 return NULL; 582} 583 584 585void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) { 586 stream()->Put('%'); 587 return NULL; 588} 589 590 591SmartPointer<const char> RegExpTree::ToString() { 592 RegExpUnparser unparser; 593 Accept(&unparser, NULL); 594 return unparser.ToString(); 595} 596 597 598RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives) 599 : alternatives_(alternatives) { 600 ASSERT(alternatives->length() > 1); 601 RegExpTree* first_alternative = alternatives->at(0); 602 min_match_ = first_alternative->min_match(); 603 max_match_ = first_alternative->max_match(); 604 for (int i = 1; i < alternatives->length(); i++) { 605 RegExpTree* alternative = alternatives->at(i); 606 min_match_ = Min(min_match_, alternative->min_match()); 607 max_match_ = Max(max_match_, alternative->max_match()); 608 } 609} 610 611 612RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes) 613 : nodes_(nodes) { 614 ASSERT(nodes->length() > 1); 615 min_match_ = 0; 616 max_match_ = 0; 617 for (int i = 0; i < nodes->length(); i++) { 618 RegExpTree* node = nodes->at(i); 619 min_match_ += node->min_match(); 620 int node_max_match = node->max_match(); 621 if (kInfinity - max_match_ < node_max_match) { 622 max_match_ = kInfinity; 623 } else { 624 max_match_ += node->max_match(); 625 } 626 } 627} 628 629 630WhileStatement::WhileStatement(ZoneStringList* labels) 631 : IterationStatement(labels), 632 cond_(NULL), 633 may_have_function_literal_(true) { 634} 635 636 637CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements) 638 : label_(label), statements_(statements) { 639} 640 641} } // namespace v8::internal 642