Home | History | Annotate | Download | only in ast
      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
      3 // found in the LICENSE file.
      4 
      5 #include "src/ast/ast.h"
      6 
      7 #include <cmath>  // For isfinite.
      8 
      9 #include "src/ast/prettyprinter.h"
     10 #include "src/ast/scopes.h"
     11 #include "src/base/hashmap.h"
     12 #include "src/builtins.h"
     13 #include "src/code-stubs.h"
     14 #include "src/contexts.h"
     15 #include "src/conversions.h"
     16 #include "src/parsing/parser.h"
     17 #include "src/property-details.h"
     18 #include "src/property.h"
     19 #include "src/string-stream.h"
     20 #include "src/type-info.h"
     21 
     22 namespace v8 {
     23 namespace internal {
     24 
     25 // ----------------------------------------------------------------------------
     26 // All the Accept member functions for each syntax tree node type.
     27 
     28 #define DECL_ACCEPT(type)                                       \
     29   void type::Accept(AstVisitor* v) { v->Visit##type(this); }
     30 AST_NODE_LIST(DECL_ACCEPT)
     31 #undef DECL_ACCEPT
     32 
     33 
     34 // ----------------------------------------------------------------------------
     35 // Implementation of other node functionality.
     36 
     37 #ifdef DEBUG
     38 
     39 void AstNode::Print(Isolate* isolate) {
     40   AstPrinter::PrintOut(isolate, this);
     41 }
     42 
     43 
     44 void AstNode::PrettyPrint(Isolate* isolate) {
     45   PrettyPrinter::PrintOut(isolate, this);
     46 }
     47 
     48 #endif  // DEBUG
     49 
     50 
     51 bool Expression::IsSmiLiteral() const {
     52   return IsLiteral() && AsLiteral()->value()->IsSmi();
     53 }
     54 
     55 
     56 bool Expression::IsStringLiteral() const {
     57   return IsLiteral() && AsLiteral()->value()->IsString();
     58 }
     59 
     60 
     61 bool Expression::IsNullLiteral() const {
     62   if (!IsLiteral()) return false;
     63   Handle<Object> value = AsLiteral()->value();
     64   return !value->IsSmi() &&
     65          value->IsNull(HeapObject::cast(*value)->GetIsolate());
     66 }
     67 
     68 bool Expression::IsUndefinedLiteral() const {
     69   if (IsLiteral()) {
     70     Handle<Object> value = AsLiteral()->value();
     71     if (!value->IsSmi() &&
     72         value->IsUndefined(HeapObject::cast(*value)->GetIsolate())) {
     73       return true;
     74     }
     75   }
     76 
     77   const VariableProxy* var_proxy = AsVariableProxy();
     78   if (var_proxy == NULL) return false;
     79   Variable* var = var_proxy->var();
     80   // The global identifier "undefined" is immutable. Everything
     81   // else could be reassigned.
     82   return var != NULL && var->IsUnallocatedOrGlobalSlot() &&
     83          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
     84 }
     85 
     86 
     87 bool Expression::IsValidReferenceExpressionOrThis() const {
     88   return IsValidReferenceExpression() ||
     89          (IsVariableProxy() && AsVariableProxy()->is_this());
     90 }
     91 
     92 
     93 VariableProxy::VariableProxy(Zone* zone, Variable* var, int start_position,
     94                              int end_position)
     95     : Expression(zone, start_position),
     96       bit_field_(IsThisField::encode(var->is_this()) |
     97                  IsAssignedField::encode(false) |
     98                  IsResolvedField::encode(false)),
     99       raw_name_(var->raw_name()),
    100       end_position_(end_position) {
    101   BindTo(var);
    102 }
    103 
    104 
    105 VariableProxy::VariableProxy(Zone* zone, const AstRawString* name,
    106                              Variable::Kind variable_kind, int start_position,
    107                              int end_position)
    108     : Expression(zone, start_position),
    109       bit_field_(IsThisField::encode(variable_kind == Variable::THIS) |
    110                  IsAssignedField::encode(false) |
    111                  IsResolvedField::encode(false)),
    112       raw_name_(name),
    113       end_position_(end_position) {}
    114 
    115 
    116 void VariableProxy::BindTo(Variable* var) {
    117   DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
    118   set_var(var);
    119   set_is_resolved();
    120   var->set_is_used();
    121 }
    122 
    123 
    124 void VariableProxy::AssignFeedbackVectorSlots(Isolate* isolate,
    125                                               FeedbackVectorSpec* spec,
    126                                               FeedbackVectorSlotCache* cache) {
    127   if (UsesVariableFeedbackSlot()) {
    128     // VariableProxies that point to the same Variable within a function can
    129     // make their loads from the same IC slot.
    130     if (var()->IsUnallocated() || var()->mode() == DYNAMIC_GLOBAL) {
    131       ZoneHashMap::Entry* entry = cache->Get(var());
    132       if (entry != NULL) {
    133         variable_feedback_slot_ = FeedbackVectorSlot(
    134             static_cast<int>(reinterpret_cast<intptr_t>(entry->value)));
    135         return;
    136       }
    137       variable_feedback_slot_ = spec->AddLoadGlobalICSlot(var()->name());
    138       cache->Put(var(), variable_feedback_slot_);
    139     } else {
    140       variable_feedback_slot_ = spec->AddLoadICSlot();
    141     }
    142   }
    143 }
    144 
    145 
    146 static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec,
    147                               FeedbackVectorSlot* out_slot) {
    148   Property* property = expr->AsProperty();
    149   LhsKind assign_type = Property::GetAssignType(property);
    150   if ((assign_type == VARIABLE &&
    151        expr->AsVariableProxy()->var()->IsUnallocated()) ||
    152       assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) {
    153     // TODO(ishell): consider using ICSlotCache for variables here.
    154     FeedbackVectorSlotKind kind = assign_type == KEYED_PROPERTY
    155                                       ? FeedbackVectorSlotKind::KEYED_STORE_IC
    156                                       : FeedbackVectorSlotKind::STORE_IC;
    157     *out_slot = spec->AddSlot(kind);
    158   }
    159 }
    160 
    161 void ForInStatement::AssignFeedbackVectorSlots(Isolate* isolate,
    162                                                FeedbackVectorSpec* spec,
    163                                                FeedbackVectorSlotCache* cache) {
    164   AssignVectorSlots(each(), spec, &each_slot_);
    165   for_in_feedback_slot_ = spec->AddGeneralSlot();
    166 }
    167 
    168 
    169 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target,
    170                        Expression* value, int pos)
    171     : Expression(zone, pos),
    172       bit_field_(
    173           IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) |
    174           StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)),
    175       target_(target),
    176       value_(value),
    177       binary_operation_(NULL) {}
    178 
    179 
    180 void Assignment::AssignFeedbackVectorSlots(Isolate* isolate,
    181                                            FeedbackVectorSpec* spec,
    182                                            FeedbackVectorSlotCache* cache) {
    183   AssignVectorSlots(target(), spec, &slot_);
    184 }
    185 
    186 
    187 void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate,
    188                                                FeedbackVectorSpec* spec,
    189                                                FeedbackVectorSlotCache* cache) {
    190   AssignVectorSlots(expression(), spec, &slot_);
    191 }
    192 
    193 
    194 Token::Value Assignment::binary_op() const {
    195   switch (op()) {
    196     case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
    197     case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
    198     case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
    199     case Token::ASSIGN_SHL: return Token::SHL;
    200     case Token::ASSIGN_SAR: return Token::SAR;
    201     case Token::ASSIGN_SHR: return Token::SHR;
    202     case Token::ASSIGN_ADD: return Token::ADD;
    203     case Token::ASSIGN_SUB: return Token::SUB;
    204     case Token::ASSIGN_MUL: return Token::MUL;
    205     case Token::ASSIGN_DIV: return Token::DIV;
    206     case Token::ASSIGN_MOD: return Token::MOD;
    207     default: UNREACHABLE();
    208   }
    209   return Token::ILLEGAL;
    210 }
    211 
    212 
    213 bool FunctionLiteral::AllowsLazyCompilation() {
    214   return scope()->AllowsLazyCompilation();
    215 }
    216 
    217 
    218 bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
    219   return scope()->AllowsLazyCompilationWithoutContext();
    220 }
    221 
    222 
    223 int FunctionLiteral::start_position() const {
    224   return scope()->start_position();
    225 }
    226 
    227 
    228 int FunctionLiteral::end_position() const {
    229   return scope()->end_position();
    230 }
    231 
    232 
    233 LanguageMode FunctionLiteral::language_mode() const {
    234   return scope()->language_mode();
    235 }
    236 
    237 
    238 bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
    239   if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
    240   DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
    241   return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
    242 }
    243 
    244 
    245 ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
    246                                              Kind kind, bool is_static,
    247                                              bool is_computed_name)
    248     : key_(key),
    249       value_(value),
    250       kind_(kind),
    251       emit_store_(true),
    252       is_static_(is_static),
    253       is_computed_name_(is_computed_name) {}
    254 
    255 
    256 ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
    257                                              Expression* key, Expression* value,
    258                                              bool is_static,
    259                                              bool is_computed_name)
    260     : key_(key),
    261       value_(value),
    262       emit_store_(true),
    263       is_static_(is_static),
    264       is_computed_name_(is_computed_name) {
    265   if (!is_computed_name &&
    266       key->AsLiteral()->raw_value()->EqualsString(
    267           ast_value_factory->proto_string())) {
    268     kind_ = PROTOTYPE;
    269   } else if (value_->AsMaterializedLiteral() != NULL) {
    270     kind_ = MATERIALIZED_LITERAL;
    271   } else if (value_->IsLiteral()) {
    272     kind_ = CONSTANT;
    273   } else {
    274     kind_ = COMPUTED;
    275   }
    276 }
    277 
    278 bool ObjectLiteralProperty::NeedsSetFunctionName() const {
    279   return is_computed_name_ &&
    280          (value_->IsAnonymousFunctionDefinition() ||
    281           (value_->IsFunctionLiteral() &&
    282            IsConciseMethod(value_->AsFunctionLiteral()->kind())));
    283 }
    284 
    285 void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
    286                                              FeedbackVectorSpec* spec,
    287                                              FeedbackVectorSlotCache* cache) {
    288   // This logic that computes the number of slots needed for vector store
    289   // ICs must mirror FullCodeGenerator::VisitClassLiteral.
    290   prototype_slot_ = spec->AddLoadICSlot();
    291   if (NeedsProxySlot()) {
    292     proxy_slot_ = spec->AddStoreICSlot();
    293   }
    294 
    295   for (int i = 0; i < properties()->length(); i++) {
    296     ObjectLiteral::Property* property = properties()->at(i);
    297     Expression* value = property->value();
    298     if (FunctionLiteral::NeedsHomeObject(value)) {
    299       property->SetSlot(spec->AddStoreICSlot());
    300     }
    301   }
    302 }
    303 
    304 
    305 bool ObjectLiteral::Property::IsCompileTimeValue() {
    306   return kind_ == CONSTANT ||
    307       (kind_ == MATERIALIZED_LITERAL &&
    308        CompileTimeValue::IsCompileTimeValue(value_));
    309 }
    310 
    311 
    312 void ObjectLiteral::Property::set_emit_store(bool emit_store) {
    313   emit_store_ = emit_store;
    314 }
    315 
    316 
    317 bool ObjectLiteral::Property::emit_store() {
    318   return emit_store_;
    319 }
    320 
    321 
    322 void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
    323                                               FeedbackVectorSpec* spec,
    324                                               FeedbackVectorSlotCache* cache) {
    325   // This logic that computes the number of slots needed for vector store
    326   // ics must mirror FullCodeGenerator::VisitObjectLiteral.
    327   int property_index = 0;
    328   for (; property_index < properties()->length(); property_index++) {
    329     ObjectLiteral::Property* property = properties()->at(property_index);
    330     if (property->is_computed_name()) break;
    331     if (property->IsCompileTimeValue()) continue;
    332 
    333     Literal* key = property->key()->AsLiteral();
    334     Expression* value = property->value();
    335     switch (property->kind()) {
    336       case ObjectLiteral::Property::CONSTANT:
    337         UNREACHABLE();
    338       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    339       // Fall through.
    340       case ObjectLiteral::Property::COMPUTED:
    341         // It is safe to use [[Put]] here because the boilerplate already
    342         // contains computed properties with an uninitialized value.
    343         if (key->value()->IsInternalizedString()) {
    344           if (property->emit_store()) {
    345             property->SetSlot(spec->AddStoreICSlot());
    346             if (FunctionLiteral::NeedsHomeObject(value)) {
    347               property->SetSlot(spec->AddStoreICSlot(), 1);
    348             }
    349           }
    350           break;
    351         }
    352         if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
    353           property->SetSlot(spec->AddStoreICSlot());
    354         }
    355         break;
    356       case ObjectLiteral::Property::PROTOTYPE:
    357         break;
    358       case ObjectLiteral::Property::GETTER:
    359         if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
    360           property->SetSlot(spec->AddStoreICSlot());
    361         }
    362         break;
    363       case ObjectLiteral::Property::SETTER:
    364         if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
    365           property->SetSlot(spec->AddStoreICSlot());
    366         }
    367         break;
    368     }
    369   }
    370 
    371   for (; property_index < properties()->length(); property_index++) {
    372     ObjectLiteral::Property* property = properties()->at(property_index);
    373 
    374     Expression* value = property->value();
    375     if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
    376       if (FunctionLiteral::NeedsHomeObject(value)) {
    377         property->SetSlot(spec->AddStoreICSlot());
    378       }
    379     }
    380   }
    381 }
    382 
    383 
    384 void ObjectLiteral::CalculateEmitStore(Zone* zone) {
    385   const auto GETTER = ObjectLiteral::Property::GETTER;
    386   const auto SETTER = ObjectLiteral::Property::SETTER;
    387 
    388   ZoneAllocationPolicy allocator(zone);
    389 
    390   ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity,
    391                     allocator);
    392   for (int i = properties()->length() - 1; i >= 0; i--) {
    393     ObjectLiteral::Property* property = properties()->at(i);
    394     if (property->is_computed_name()) continue;
    395     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
    396     Literal* literal = property->key()->AsLiteral();
    397     DCHECK(!literal->IsNullLiteral());
    398 
    399     // If there is an existing entry do not emit a store unless the previous
    400     // entry was also an accessor.
    401     uint32_t hash = literal->Hash();
    402     ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
    403     if (entry->value != NULL) {
    404       auto previous_kind =
    405           static_cast<ObjectLiteral::Property*>(entry->value)->kind();
    406       if (!((property->kind() == GETTER && previous_kind == SETTER) ||
    407             (property->kind() == SETTER && previous_kind == GETTER))) {
    408         property->set_emit_store(false);
    409       }
    410     }
    411     entry->value = property;
    412   }
    413 }
    414 
    415 
    416 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
    417   return property != NULL &&
    418          property->kind() != ObjectLiteral::Property::PROTOTYPE;
    419 }
    420 
    421 
    422 void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
    423   if (!constant_properties_.is_null()) return;
    424 
    425   // Allocate a fixed array to hold all the constant properties.
    426   Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray(
    427       boilerplate_properties_ * 2, TENURED);
    428 
    429   int position = 0;
    430   // Accumulate the value in local variables and store it at the end.
    431   bool is_simple = true;
    432   int depth_acc = 1;
    433   uint32_t max_element_index = 0;
    434   uint32_t elements = 0;
    435   for (int i = 0; i < properties()->length(); i++) {
    436     ObjectLiteral::Property* property = properties()->at(i);
    437     if (!IsBoilerplateProperty(property)) {
    438       is_simple = false;
    439       continue;
    440     }
    441 
    442     if (position == boilerplate_properties_ * 2) {
    443       DCHECK(property->is_computed_name());
    444       is_simple = false;
    445       break;
    446     }
    447     DCHECK(!property->is_computed_name());
    448 
    449     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
    450     if (m_literal != NULL) {
    451       m_literal->BuildConstants(isolate);
    452       if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1;
    453     }
    454 
    455     // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
    456     // value for COMPUTED properties, the real value is filled in at
    457     // runtime. The enumeration order is maintained.
    458     Handle<Object> key = property->key()->AsLiteral()->value();
    459     Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
    460 
    461     // Ensure objects that may, at any point in time, contain fields with double
    462     // representation are always treated as nested objects. This is true for
    463     // computed fields (value is undefined), and smi and double literals
    464     // (value->IsNumber()).
    465     // TODO(verwaest): Remove once we can store them inline.
    466     if (FLAG_track_double_fields &&
    467         (value->IsNumber() || value->IsUninitialized(isolate))) {
    468       may_store_doubles_ = true;
    469     }
    470 
    471     is_simple = is_simple && !value->IsUninitialized(isolate);
    472 
    473     // Keep track of the number of elements in the object literal and
    474     // the largest element index.  If the largest element index is
    475     // much larger than the number of elements, creating an object
    476     // literal with fast elements will be a waste of space.
    477     uint32_t element_index = 0;
    478     if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) {
    479       max_element_index = Max(element_index, max_element_index);
    480       elements++;
    481       key = isolate->factory()->NewNumberFromUint(element_index);
    482     } else if (key->ToArrayIndex(&element_index)) {
    483       max_element_index = Max(element_index, max_element_index);
    484       elements++;
    485     } else if (key->IsNumber()) {
    486       key = isolate->factory()->NumberToString(key);
    487     }
    488 
    489     // Add name, value pair to the fixed array.
    490     constant_properties->set(position++, *key);
    491     constant_properties->set(position++, *value);
    492   }
    493 
    494   constant_properties_ = constant_properties;
    495   fast_elements_ =
    496       (max_element_index <= 32) || ((2 * elements) >= max_element_index);
    497   has_elements_ = elements > 0;
    498   set_is_simple(is_simple);
    499   set_depth(depth_acc);
    500 }
    501 
    502 
    503 void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
    504   DCHECK_LT(first_spread_index_, 0);
    505 
    506   if (!constant_elements_.is_null()) return;
    507 
    508   int constants_length = values()->length();
    509 
    510   // Allocate a fixed array to hold all the object literals.
    511   Handle<JSArray> array = isolate->factory()->NewJSArray(
    512       FAST_HOLEY_SMI_ELEMENTS, constants_length, constants_length,
    513       INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
    514 
    515   // Fill in the literals.
    516   bool is_simple = true;
    517   int depth_acc = 1;
    518   bool is_holey = false;
    519   int array_index = 0;
    520   for (; array_index < constants_length; array_index++) {
    521     Expression* element = values()->at(array_index);
    522     DCHECK(!element->IsSpread());
    523     MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
    524     if (m_literal != NULL) {
    525       m_literal->BuildConstants(isolate);
    526       if (m_literal->depth() + 1 > depth_acc) {
    527         depth_acc = m_literal->depth() + 1;
    528       }
    529     }
    530 
    531     // New handle scope here, needs to be after BuildContants().
    532     HandleScope scope(isolate);
    533     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
    534     if (boilerplate_value->IsTheHole(isolate)) {
    535       is_holey = true;
    536       continue;
    537     }
    538 
    539     if (boilerplate_value->IsUninitialized(isolate)) {
    540       boilerplate_value = handle(Smi::FromInt(0), isolate);
    541       is_simple = false;
    542     }
    543 
    544     JSObject::AddDataElement(array, array_index, boilerplate_value, NONE)
    545         .Assert();
    546   }
    547 
    548   JSObject::ValidateElements(array);
    549   Handle<FixedArrayBase> element_values(array->elements());
    550 
    551   // Simple and shallow arrays can be lazily copied, we transform the
    552   // elements array to a copy-on-write array.
    553   if (is_simple && depth_acc == 1 && array_index > 0 &&
    554       array->HasFastSmiOrObjectElements()) {
    555     element_values->set_map(isolate->heap()->fixed_cow_array_map());
    556   }
    557 
    558   // Remember both the literal's constant values as well as the ElementsKind
    559   // in a 2-element FixedArray.
    560   Handle<FixedArray> literals = isolate->factory()->NewFixedArray(2, TENURED);
    561 
    562   ElementsKind kind = array->GetElementsKind();
    563   kind = is_holey ? GetHoleyElementsKind(kind) : GetPackedElementsKind(kind);
    564 
    565   literals->set(0, Smi::FromInt(kind));
    566   literals->set(1, *element_values);
    567 
    568   constant_elements_ = literals;
    569   set_is_simple(is_simple);
    570   set_depth(depth_acc);
    571 }
    572 
    573 
    574 void ArrayLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
    575                                              FeedbackVectorSpec* spec,
    576                                              FeedbackVectorSlotCache* cache) {
    577   // This logic that computes the number of slots needed for vector store
    578   // ics must mirror FullCodeGenerator::VisitArrayLiteral.
    579   int array_index = 0;
    580   for (; array_index < values()->length(); array_index++) {
    581     Expression* subexpr = values()->at(array_index);
    582     DCHECK(!subexpr->IsSpread());
    583     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
    584 
    585     // We'll reuse the same literal slot for all of the non-constant
    586     // subexpressions that use a keyed store IC.
    587     literal_slot_ = spec->AddKeyedStoreICSlot();
    588     return;
    589   }
    590 }
    591 
    592 
    593 Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
    594                                                         Isolate* isolate) {
    595   if (expression->IsLiteral()) {
    596     return expression->AsLiteral()->value();
    597   }
    598   if (CompileTimeValue::IsCompileTimeValue(expression)) {
    599     return CompileTimeValue::GetValue(isolate, expression);
    600   }
    601   return isolate->factory()->uninitialized_value();
    602 }
    603 
    604 
    605 void MaterializedLiteral::BuildConstants(Isolate* isolate) {
    606   if (IsArrayLiteral()) {
    607     return AsArrayLiteral()->BuildConstantElements(isolate);
    608   }
    609   if (IsObjectLiteral()) {
    610     return AsObjectLiteral()->BuildConstantProperties(isolate);
    611   }
    612   DCHECK(IsRegExpLiteral());
    613   DCHECK(depth() >= 1);  // Depth should be initialized.
    614 }
    615 
    616 
    617 void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
    618   // TODO(olivf) If this Operation is used in a test context, then the
    619   // expression has a ToBoolean stub and we want to collect the type
    620   // information. However the GraphBuilder expects it to be on the instruction
    621   // corresponding to the TestContext, therefore we have to store it here and
    622   // not on the operand.
    623   set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
    624 }
    625 
    626 
    627 void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
    628   // TODO(olivf) If this Operation is used in a test context, then the right
    629   // hand side has a ToBoolean stub and we want to collect the type information.
    630   // However the GraphBuilder expects it to be on the instruction corresponding
    631   // to the TestContext, therefore we have to store it here and not on the
    632   // right hand operand.
    633   set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
    634 }
    635 
    636 
    637 static bool IsTypeof(Expression* expr) {
    638   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
    639   return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
    640 }
    641 
    642 
    643 // Check for the pattern: typeof <expression> equals <string literal>.
    644 static bool MatchLiteralCompareTypeof(Expression* left,
    645                                       Token::Value op,
    646                                       Expression* right,
    647                                       Expression** expr,
    648                                       Handle<String>* check) {
    649   if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
    650     *expr = left->AsUnaryOperation()->expression();
    651     *check = Handle<String>::cast(right->AsLiteral()->value());
    652     return true;
    653   }
    654   return false;
    655 }
    656 
    657 
    658 bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
    659                                               Handle<String>* check) {
    660   return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) ||
    661       MatchLiteralCompareTypeof(right_, op_, left_, expr, check);
    662 }
    663 
    664 
    665 static bool IsVoidOfLiteral(Expression* expr) {
    666   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
    667   return maybe_unary != NULL &&
    668       maybe_unary->op() == Token::VOID &&
    669       maybe_unary->expression()->IsLiteral();
    670 }
    671 
    672 
    673 // Check for the pattern: void <literal> equals <expression> or
    674 // undefined equals <expression>
    675 static bool MatchLiteralCompareUndefined(Expression* left,
    676                                          Token::Value op,
    677                                          Expression* right,
    678                                          Expression** expr) {
    679   if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
    680     *expr = right;
    681     return true;
    682   }
    683   if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
    684     *expr = right;
    685     return true;
    686   }
    687   return false;
    688 }
    689 
    690 bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
    691   return MatchLiteralCompareUndefined(left_, op_, right_, expr) ||
    692          MatchLiteralCompareUndefined(right_, op_, left_, expr);
    693 }
    694 
    695 
    696 // Check for the pattern: null equals <expression>
    697 static bool MatchLiteralCompareNull(Expression* left,
    698                                     Token::Value op,
    699                                     Expression* right,
    700                                     Expression** expr) {
    701   if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
    702     *expr = right;
    703     return true;
    704   }
    705   return false;
    706 }
    707 
    708 
    709 bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
    710   return MatchLiteralCompareNull(left_, op_, right_, expr) ||
    711       MatchLiteralCompareNull(right_, op_, left_, expr);
    712 }
    713 
    714 
    715 // ----------------------------------------------------------------------------
    716 // Inlining support
    717 
    718 bool Declaration::IsInlineable() const {
    719   return proxy()->var()->IsStackAllocated();
    720 }
    721 
    722 bool FunctionDeclaration::IsInlineable() const {
    723   return false;
    724 }
    725 
    726 
    727 // ----------------------------------------------------------------------------
    728 // Recording of type feedback
    729 
    730 // TODO(rossberg): all RecordTypeFeedback functions should disappear
    731 // once we use the common type field in the AST consistently.
    732 
    733 void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
    734   set_to_boolean_types(oracle->ToBooleanTypes(test_id()));
    735 }
    736 
    737 
    738 bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const {
    739   CallType call_type = GetCallType(isolate);
    740   if (call_type == POSSIBLY_EVAL_CALL) {
    741     return false;
    742   }
    743   return true;
    744 }
    745 
    746 
    747 bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const {
    748   // SuperConstructorCall uses a CallConstructStub, which wants
    749   // a Slot, in addition to any IC slots requested elsewhere.
    750   return GetCallType(isolate) == SUPER_CALL;
    751 }
    752 
    753 
    754 void Call::AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
    755                                      FeedbackVectorSlotCache* cache) {
    756   if (IsUsingCallFeedbackICSlot(isolate)) {
    757     ic_slot_ = spec->AddCallICSlot();
    758   }
    759   if (IsUsingCallFeedbackSlot(isolate)) {
    760     stub_slot_ = spec->AddGeneralSlot();
    761   }
    762 }
    763 
    764 
    765 Call::CallType Call::GetCallType(Isolate* isolate) const {
    766   VariableProxy* proxy = expression()->AsVariableProxy();
    767   if (proxy != NULL) {
    768     if (proxy->var()->is_possibly_eval(isolate)) {
    769       return POSSIBLY_EVAL_CALL;
    770     } else if (proxy->var()->IsUnallocatedOrGlobalSlot()) {
    771       return GLOBAL_CALL;
    772     } else if (proxy->var()->IsLookupSlot()) {
    773       return LOOKUP_SLOT_CALL;
    774     }
    775   }
    776 
    777   if (expression()->IsSuperCallReference()) return SUPER_CALL;
    778 
    779   Property* property = expression()->AsProperty();
    780   if (property != nullptr) {
    781     bool is_super = property->IsSuperAccess();
    782     if (property->key()->IsPropertyName()) {
    783       return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
    784     } else {
    785       return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
    786     }
    787   }
    788 
    789   return OTHER_CALL;
    790 }
    791 
    792 
    793 // ----------------------------------------------------------------------------
    794 // Implementation of AstVisitor
    795 
    796 void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
    797   for (int i = 0; i < declarations->length(); i++) {
    798     Visit(declarations->at(i));
    799   }
    800 }
    801 
    802 
    803 void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
    804   for (int i = 0; i < statements->length(); i++) {
    805     Statement* stmt = statements->at(i);
    806     Visit(stmt);
    807     if (stmt->IsJump()) break;
    808   }
    809 }
    810 
    811 
    812 void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
    813   for (int i = 0; i < expressions->length(); i++) {
    814     // The variable statement visiting code may pass NULL expressions
    815     // to this code. Maybe this should be handled by introducing an
    816     // undefined expression or literal?  Revisit this code if this
    817     // changes
    818     Expression* expression = expressions->at(i);
    819     if (expression != NULL) Visit(expression);
    820   }
    821 }
    822 
    823 // ----------------------------------------------------------------------------
    824 // Implementation of AstTraversalVisitor
    825 
    826 #define RECURSE(call)               \
    827   do {                              \
    828     DCHECK(!HasStackOverflow());    \
    829     call;                           \
    830     if (HasStackOverflow()) return; \
    831   } while (false)
    832 
    833 #define RECURSE_EXPRESSION(call)    \
    834   do {                              \
    835     DCHECK(!HasStackOverflow());    \
    836     ++depth_;                       \
    837     call;                           \
    838     --depth_;                       \
    839     if (HasStackOverflow()) return; \
    840   } while (false)
    841 
    842 AstTraversalVisitor::AstTraversalVisitor(Isolate* isolate) : depth_(0) {
    843   InitializeAstVisitor(isolate);
    844 }
    845 
    846 AstTraversalVisitor::AstTraversalVisitor(uintptr_t stack_limit) : depth_(0) {
    847   InitializeAstVisitor(stack_limit);
    848 }
    849 
    850 void AstTraversalVisitor::VisitDeclarations(ZoneList<Declaration*>* decls) {
    851   for (int i = 0; i < decls->length(); ++i) {
    852     Declaration* decl = decls->at(i);
    853     RECURSE(Visit(decl));
    854   }
    855 }
    856 
    857 void AstTraversalVisitor::VisitStatements(ZoneList<Statement*>* stmts) {
    858   for (int i = 0; i < stmts->length(); ++i) {
    859     Statement* stmt = stmts->at(i);
    860     RECURSE(Visit(stmt));
    861     if (stmt->IsJump()) break;
    862   }
    863 }
    864 
    865 void AstTraversalVisitor::VisitVariableDeclaration(VariableDeclaration* decl) {}
    866 
    867 void AstTraversalVisitor::VisitFunctionDeclaration(FunctionDeclaration* decl) {
    868   RECURSE(Visit(decl->fun()));
    869 }
    870 
    871 void AstTraversalVisitor::VisitImportDeclaration(ImportDeclaration* decl) {}
    872 
    873 void AstTraversalVisitor::VisitExportDeclaration(ExportDeclaration* decl) {}
    874 
    875 void AstTraversalVisitor::VisitBlock(Block* stmt) {
    876   RECURSE(VisitStatements(stmt->statements()));
    877 }
    878 
    879 void AstTraversalVisitor::VisitExpressionStatement(ExpressionStatement* stmt) {
    880   RECURSE(Visit(stmt->expression()));
    881 }
    882 
    883 void AstTraversalVisitor::VisitEmptyStatement(EmptyStatement* stmt) {}
    884 
    885 void AstTraversalVisitor::VisitSloppyBlockFunctionStatement(
    886     SloppyBlockFunctionStatement* stmt) {
    887   RECURSE(Visit(stmt->statement()));
    888 }
    889 
    890 void AstTraversalVisitor::VisitIfStatement(IfStatement* stmt) {
    891   RECURSE(Visit(stmt->condition()));
    892   RECURSE(Visit(stmt->then_statement()));
    893   RECURSE(Visit(stmt->else_statement()));
    894 }
    895 
    896 void AstTraversalVisitor::VisitContinueStatement(ContinueStatement* stmt) {}
    897 
    898 void AstTraversalVisitor::VisitBreakStatement(BreakStatement* stmt) {}
    899 
    900 void AstTraversalVisitor::VisitReturnStatement(ReturnStatement* stmt) {
    901   RECURSE(Visit(stmt->expression()));
    902 }
    903 
    904 void AstTraversalVisitor::VisitWithStatement(WithStatement* stmt) {
    905   RECURSE(stmt->expression());
    906   RECURSE(stmt->statement());
    907 }
    908 
    909 void AstTraversalVisitor::VisitSwitchStatement(SwitchStatement* stmt) {
    910   RECURSE(Visit(stmt->tag()));
    911 
    912   ZoneList<CaseClause*>* clauses = stmt->cases();
    913 
    914   for (int i = 0; i < clauses->length(); ++i) {
    915     CaseClause* clause = clauses->at(i);
    916     if (!clause->is_default()) {
    917       Expression* label = clause->label();
    918       RECURSE(Visit(label));
    919     }
    920     ZoneList<Statement*>* stmts = clause->statements();
    921     RECURSE(VisitStatements(stmts));
    922   }
    923 }
    924 
    925 void AstTraversalVisitor::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
    926 
    927 void AstTraversalVisitor::VisitDoWhileStatement(DoWhileStatement* stmt) {
    928   RECURSE(Visit(stmt->body()));
    929   RECURSE(Visit(stmt->cond()));
    930 }
    931 
    932 void AstTraversalVisitor::VisitWhileStatement(WhileStatement* stmt) {
    933   RECURSE(Visit(stmt->cond()));
    934   RECURSE(Visit(stmt->body()));
    935 }
    936 
    937 void AstTraversalVisitor::VisitForStatement(ForStatement* stmt) {
    938   if (stmt->init() != NULL) {
    939     RECURSE(Visit(stmt->init()));
    940   }
    941   if (stmt->cond() != NULL) {
    942     RECURSE(Visit(stmt->cond()));
    943   }
    944   if (stmt->next() != NULL) {
    945     RECURSE(Visit(stmt->next()));
    946   }
    947   RECURSE(Visit(stmt->body()));
    948 }
    949 
    950 void AstTraversalVisitor::VisitForInStatement(ForInStatement* stmt) {
    951   RECURSE(Visit(stmt->enumerable()));
    952   RECURSE(Visit(stmt->body()));
    953 }
    954 
    955 void AstTraversalVisitor::VisitForOfStatement(ForOfStatement* stmt) {
    956   RECURSE(Visit(stmt->assign_iterator()));
    957   RECURSE(Visit(stmt->next_result()));
    958   RECURSE(Visit(stmt->result_done()));
    959   RECURSE(Visit(stmt->assign_each()));
    960   RECURSE(Visit(stmt->body()));
    961 }
    962 
    963 void AstTraversalVisitor::VisitTryCatchStatement(TryCatchStatement* stmt) {
    964   RECURSE(Visit(stmt->try_block()));
    965   RECURSE(Visit(stmt->catch_block()));
    966 }
    967 
    968 void AstTraversalVisitor::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
    969   RECURSE(Visit(stmt->try_block()));
    970   RECURSE(Visit(stmt->finally_block()));
    971 }
    972 
    973 void AstTraversalVisitor::VisitDebuggerStatement(DebuggerStatement* stmt) {}
    974 
    975 void AstTraversalVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
    976   Scope* scope = expr->scope();
    977   RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
    978   RECURSE_EXPRESSION(VisitStatements(expr->body()));
    979 }
    980 
    981 void AstTraversalVisitor::VisitNativeFunctionLiteral(
    982     NativeFunctionLiteral* expr) {}
    983 
    984 void AstTraversalVisitor::VisitDoExpression(DoExpression* expr) {
    985   RECURSE(VisitBlock(expr->block()));
    986   RECURSE(VisitVariableProxy(expr->result()));
    987 }
    988 
    989 void AstTraversalVisitor::VisitConditional(Conditional* expr) {
    990   RECURSE_EXPRESSION(Visit(expr->condition()));
    991   RECURSE_EXPRESSION(Visit(expr->then_expression()));
    992   RECURSE_EXPRESSION(Visit(expr->else_expression()));
    993 }
    994 
    995 void AstTraversalVisitor::VisitVariableProxy(VariableProxy* expr) {}
    996 
    997 void AstTraversalVisitor::VisitLiteral(Literal* expr) {}
    998 
    999 void AstTraversalVisitor::VisitRegExpLiteral(RegExpLiteral* expr) {}
   1000 
   1001 void AstTraversalVisitor::VisitObjectLiteral(ObjectLiteral* expr) {
   1002   ZoneList<ObjectLiteralProperty*>* props = expr->properties();
   1003   for (int i = 0; i < props->length(); ++i) {
   1004     ObjectLiteralProperty* prop = props->at(i);
   1005     if (!prop->key()->IsLiteral()) {
   1006       RECURSE_EXPRESSION(Visit(prop->key()));
   1007     }
   1008     RECURSE_EXPRESSION(Visit(prop->value()));
   1009   }
   1010 }
   1011 
   1012 void AstTraversalVisitor::VisitArrayLiteral(ArrayLiteral* expr) {
   1013   ZoneList<Expression*>* values = expr->values();
   1014   for (int i = 0; i < values->length(); ++i) {
   1015     Expression* value = values->at(i);
   1016     RECURSE_EXPRESSION(Visit(value));
   1017   }
   1018 }
   1019 
   1020 void AstTraversalVisitor::VisitAssignment(Assignment* expr) {
   1021   RECURSE_EXPRESSION(Visit(expr->target()));
   1022   RECURSE_EXPRESSION(Visit(expr->value()));
   1023 }
   1024 
   1025 void AstTraversalVisitor::VisitYield(Yield* expr) {
   1026   RECURSE_EXPRESSION(Visit(expr->generator_object()));
   1027   RECURSE_EXPRESSION(Visit(expr->expression()));
   1028 }
   1029 
   1030 void AstTraversalVisitor::VisitThrow(Throw* expr) {
   1031   RECURSE_EXPRESSION(Visit(expr->exception()));
   1032 }
   1033 
   1034 void AstTraversalVisitor::VisitProperty(Property* expr) {
   1035   RECURSE_EXPRESSION(Visit(expr->obj()));
   1036   RECURSE_EXPRESSION(Visit(expr->key()));
   1037 }
   1038 
   1039 void AstTraversalVisitor::VisitCall(Call* expr) {
   1040   RECURSE_EXPRESSION(Visit(expr->expression()));
   1041   ZoneList<Expression*>* args = expr->arguments();
   1042   for (int i = 0; i < args->length(); ++i) {
   1043     Expression* arg = args->at(i);
   1044     RECURSE_EXPRESSION(Visit(arg));
   1045   }
   1046 }
   1047 
   1048 void AstTraversalVisitor::VisitCallNew(CallNew* expr) {
   1049   RECURSE_EXPRESSION(Visit(expr->expression()));
   1050   ZoneList<Expression*>* args = expr->arguments();
   1051   for (int i = 0; i < args->length(); ++i) {
   1052     Expression* arg = args->at(i);
   1053     RECURSE_EXPRESSION(Visit(arg));
   1054   }
   1055 }
   1056 
   1057 void AstTraversalVisitor::VisitCallRuntime(CallRuntime* expr) {
   1058   ZoneList<Expression*>* args = expr->arguments();
   1059   for (int i = 0; i < args->length(); ++i) {
   1060     Expression* arg = args->at(i);
   1061     RECURSE_EXPRESSION(Visit(arg));
   1062   }
   1063 }
   1064 
   1065 void AstTraversalVisitor::VisitUnaryOperation(UnaryOperation* expr) {
   1066   RECURSE_EXPRESSION(Visit(expr->expression()));
   1067 }
   1068 
   1069 void AstTraversalVisitor::VisitCountOperation(CountOperation* expr) {
   1070   RECURSE_EXPRESSION(Visit(expr->expression()));
   1071 }
   1072 
   1073 void AstTraversalVisitor::VisitBinaryOperation(BinaryOperation* expr) {
   1074   RECURSE_EXPRESSION(Visit(expr->left()));
   1075   RECURSE_EXPRESSION(Visit(expr->right()));
   1076 }
   1077 
   1078 void AstTraversalVisitor::VisitCompareOperation(CompareOperation* expr) {
   1079   RECURSE_EXPRESSION(Visit(expr->left()));
   1080   RECURSE_EXPRESSION(Visit(expr->right()));
   1081 }
   1082 
   1083 void AstTraversalVisitor::VisitThisFunction(ThisFunction* expr) {}
   1084 
   1085 void AstTraversalVisitor::VisitClassLiteral(ClassLiteral* expr) {
   1086   if (expr->extends() != nullptr) {
   1087     RECURSE_EXPRESSION(Visit(expr->extends()));
   1088   }
   1089   RECURSE_EXPRESSION(Visit(expr->constructor()));
   1090   ZoneList<ObjectLiteralProperty*>* props = expr->properties();
   1091   for (int i = 0; i < props->length(); ++i) {
   1092     ObjectLiteralProperty* prop = props->at(i);
   1093     if (!prop->key()->IsLiteral()) {
   1094       RECURSE_EXPRESSION(Visit(prop->key()));
   1095     }
   1096     RECURSE_EXPRESSION(Visit(prop->value()));
   1097   }
   1098 }
   1099 
   1100 void AstTraversalVisitor::VisitSpread(Spread* expr) {
   1101   RECURSE_EXPRESSION(Visit(expr->expression()));
   1102 }
   1103 
   1104 void AstTraversalVisitor::VisitEmptyParentheses(EmptyParentheses* expr) {}
   1105 
   1106 void AstTraversalVisitor::VisitSuperPropertyReference(
   1107     SuperPropertyReference* expr) {
   1108   RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
   1109   RECURSE_EXPRESSION(Visit(expr->home_object()));
   1110 }
   1111 
   1112 void AstTraversalVisitor::VisitSuperCallReference(SuperCallReference* expr) {
   1113   RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
   1114   RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
   1115   RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
   1116 }
   1117 
   1118 void AstTraversalVisitor::VisitRewritableExpression(
   1119     RewritableExpression* expr) {
   1120   RECURSE(Visit(expr->expression()));
   1121 }
   1122 
   1123 #undef RECURSE_EXPRESSION
   1124 #undef RECURSE
   1125 
   1126 CaseClause::CaseClause(Zone* zone, Expression* label,
   1127                        ZoneList<Statement*>* statements, int pos)
   1128     : Expression(zone, pos),
   1129       label_(label),
   1130       statements_(statements),
   1131       compare_type_(Type::None()) {}
   1132 
   1133 uint32_t Literal::Hash() {
   1134   return raw_value()->IsString()
   1135              ? raw_value()->AsString()->hash()
   1136              : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
   1137 }
   1138 
   1139 
   1140 // static
   1141 bool Literal::Match(void* literal1, void* literal2) {
   1142   const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
   1143   const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
   1144   return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) ||
   1145          (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
   1146 }
   1147 
   1148 
   1149 }  // namespace internal
   1150 }  // namespace v8
   1151