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 #include <vector>
      9 
     10 #include "src/ast/prettyprinter.h"
     11 #include "src/ast/scopes.h"
     12 #include "src/base/hashmap.h"
     13 #include "src/builtins/builtins-constructor.h"
     14 #include "src/builtins/builtins.h"
     15 #include "src/code-stubs.h"
     16 #include "src/contexts.h"
     17 #include "src/conversions-inl.h"
     18 #include "src/double.h"
     19 #include "src/elements.h"
     20 #include "src/objects-inl.h"
     21 #include "src/objects/literal-objects-inl.h"
     22 #include "src/objects/literal-objects.h"
     23 #include "src/objects/map.h"
     24 #include "src/property-details.h"
     25 #include "src/property.h"
     26 #include "src/string-stream.h"
     27 
     28 namespace v8 {
     29 namespace internal {
     30 
     31 // ----------------------------------------------------------------------------
     32 // Implementation of other node functionality.
     33 
     34 #ifdef DEBUG
     35 
     36 static const char* NameForNativeContextIntrinsicIndex(uint32_t idx) {
     37   switch (idx) {
     38 #define NATIVE_CONTEXT_FIELDS_IDX(NAME, Type, name) \
     39   case Context::NAME:                               \
     40     return #name;
     41 
     42     NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELDS_IDX)
     43 #undef NATIVE_CONTEXT_FIELDS_IDX
     44 
     45     default:
     46       break;
     47   }
     48 
     49   return "UnknownIntrinsicIndex";
     50 }
     51 
     52 void AstNode::Print() { Print(Isolate::Current()); }
     53 
     54 void AstNode::Print(Isolate* isolate) {
     55   AllowHandleDereference allow_deref;
     56   AstPrinter::PrintOut(isolate, this);
     57 }
     58 
     59 
     60 #endif  // DEBUG
     61 
     62 #define RETURN_NODE(Node) \
     63   case k##Node:           \
     64     return static_cast<Node*>(this);
     65 
     66 IterationStatement* AstNode::AsIterationStatement() {
     67   switch (node_type()) {
     68     ITERATION_NODE_LIST(RETURN_NODE);
     69     default:
     70       return nullptr;
     71   }
     72 }
     73 
     74 BreakableStatement* AstNode::AsBreakableStatement() {
     75   switch (node_type()) {
     76     BREAKABLE_NODE_LIST(RETURN_NODE);
     77     ITERATION_NODE_LIST(RETURN_NODE);
     78     default:
     79       return nullptr;
     80   }
     81 }
     82 
     83 MaterializedLiteral* AstNode::AsMaterializedLiteral() {
     84   switch (node_type()) {
     85     LITERAL_NODE_LIST(RETURN_NODE);
     86     default:
     87       return nullptr;
     88   }
     89 }
     90 
     91 #undef RETURN_NODE
     92 
     93 bool Expression::IsSmiLiteral() const {
     94   return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
     95 }
     96 
     97 bool Expression::IsNumberLiteral() const {
     98   return IsLiteral() && AsLiteral()->IsNumber();
     99 }
    100 
    101 bool Expression::IsStringLiteral() const {
    102   return IsLiteral() && AsLiteral()->type() == Literal::kString;
    103 }
    104 
    105 bool Expression::IsPropertyName() const {
    106   return IsLiteral() && AsLiteral()->IsPropertyName();
    107 }
    108 
    109 bool Expression::IsNullLiteral() const {
    110   return IsLiteral() && AsLiteral()->type() == Literal::kNull;
    111 }
    112 
    113 bool Expression::IsTheHoleLiteral() const {
    114   return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
    115 }
    116 
    117 bool Expression::IsCompileTimeValue() {
    118   if (IsLiteral()) return true;
    119   MaterializedLiteral* literal = AsMaterializedLiteral();
    120   if (literal == nullptr) return false;
    121   return literal->IsSimple();
    122 }
    123 
    124 bool Expression::IsUndefinedLiteral() const {
    125   if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
    126 
    127   const VariableProxy* var_proxy = AsVariableProxy();
    128   if (var_proxy == nullptr) return false;
    129   Variable* var = var_proxy->var();
    130   // The global identifier "undefined" is immutable. Everything
    131   // else could be reassigned.
    132   return var != nullptr && var->IsUnallocated() &&
    133          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
    134 }
    135 
    136 bool Expression::ToBooleanIsTrue() const {
    137   return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
    138 }
    139 
    140 bool Expression::ToBooleanIsFalse() const {
    141   return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
    142 }
    143 
    144 bool Expression::IsValidReferenceExpression() const {
    145   // We don't want expressions wrapped inside RewritableExpression to be
    146   // considered as valid reference expressions, as they will be rewritten
    147   // to something (most probably involving a do expression).
    148   if (IsRewritableExpression()) return false;
    149   return IsProperty() ||
    150          (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
    151 }
    152 
    153 bool Expression::IsAnonymousFunctionDefinition() const {
    154   return (IsFunctionLiteral() &&
    155           AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
    156          (IsClassLiteral() &&
    157           AsClassLiteral()->IsAnonymousFunctionDefinition());
    158 }
    159 
    160 bool Expression::IsConciseMethodDefinition() const {
    161   return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
    162 }
    163 
    164 bool Expression::IsAccessorFunctionDefinition() const {
    165   return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
    166 }
    167 
    168 bool Statement::IsJump() const {
    169   switch (node_type()) {
    170 #define JUMP_NODE_LIST(V) \
    171   V(Block)                \
    172   V(ExpressionStatement)  \
    173   V(ContinueStatement)    \
    174   V(BreakStatement)       \
    175   V(ReturnStatement)      \
    176   V(IfStatement)
    177 #define GENERATE_CASE(Node) \
    178   case k##Node:             \
    179     return static_cast<const Node*>(this)->IsJump();
    180     JUMP_NODE_LIST(GENERATE_CASE)
    181 #undef GENERATE_CASE
    182 #undef JUMP_NODE_LIST
    183     default:
    184       return false;
    185   }
    186 }
    187 
    188 VariableProxy::VariableProxy(Variable* var, int start_position)
    189     : Expression(start_position, kVariableProxy),
    190       raw_name_(var->raw_name()),
    191       next_unresolved_(nullptr) {
    192   bit_field_ |= IsThisField::encode(var->is_this()) |
    193                 IsAssignedField::encode(false) |
    194                 IsResolvedField::encode(false) |
    195                 HoleCheckModeField::encode(HoleCheckMode::kElided);
    196   BindTo(var);
    197 }
    198 
    199 VariableProxy::VariableProxy(const VariableProxy* copy_from)
    200     : Expression(copy_from->position(), kVariableProxy),
    201       next_unresolved_(nullptr) {
    202   bit_field_ = copy_from->bit_field_;
    203   DCHECK(!copy_from->is_resolved());
    204   raw_name_ = copy_from->raw_name_;
    205 }
    206 
    207 void VariableProxy::BindTo(Variable* var) {
    208   DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
    209   set_var(var);
    210   set_is_resolved();
    211   var->set_is_used();
    212   if (is_assigned()) var->set_maybe_assigned();
    213 }
    214 
    215 Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
    216                        Expression* value, int pos)
    217     : Expression(pos, node_type), target_(target), value_(value) {
    218   bit_field_ |= TokenField::encode(op);
    219 }
    220 
    221 void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
    222   DCHECK(!inferred_name.is_null());
    223   inferred_name_ = inferred_name;
    224   DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
    225   raw_inferred_name_ = nullptr;
    226   scope()->set_has_inferred_function_name(true);
    227 }
    228 
    229 void FunctionLiteral::set_raw_inferred_name(
    230     const AstConsString* raw_inferred_name) {
    231   DCHECK_NOT_NULL(raw_inferred_name);
    232   raw_inferred_name_ = raw_inferred_name;
    233   DCHECK(inferred_name_.is_null());
    234   inferred_name_ = Handle<String>();
    235   scope()->set_has_inferred_function_name(true);
    236 }
    237 
    238 bool FunctionLiteral::ShouldEagerCompile() const {
    239   return scope()->ShouldEagerCompile();
    240 }
    241 
    242 void FunctionLiteral::SetShouldEagerCompile() {
    243   scope()->set_should_eager_compile();
    244 }
    245 
    246 bool FunctionLiteral::AllowsLazyCompilation() {
    247   return scope()->AllowsLazyCompilation();
    248 }
    249 
    250 Handle<String> FunctionLiteral::name(Isolate* isolate) const {
    251   return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
    252 }
    253 
    254 int FunctionLiteral::start_position() const {
    255   return scope()->start_position();
    256 }
    257 
    258 
    259 int FunctionLiteral::end_position() const {
    260   return scope()->end_position();
    261 }
    262 
    263 
    264 LanguageMode FunctionLiteral::language_mode() const {
    265   return scope()->language_mode();
    266 }
    267 
    268 FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
    269 
    270 bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
    271   if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
    272   DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
    273   return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
    274 }
    275 
    276 std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
    277   const AstConsString* cons_string;
    278   if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
    279     cons_string = raw_name_;
    280   } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
    281     cons_string = raw_inferred_name_;
    282   } else if (!inferred_name_.is_null()) {
    283     AllowHandleDereference allow_deref;
    284     return inferred_name_->ToCString();
    285   } else {
    286     char* empty_str = new char[1];
    287     empty_str[0] = 0;
    288     return std::unique_ptr<char[]>(empty_str);
    289   }
    290 
    291   // TODO(rmcilroy): Deal with two-character strings.
    292   std::vector<char> result_vec;
    293   std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
    294   for (const AstRawString* string : strings) {
    295     if (!string->is_one_byte()) break;
    296     for (int i = 0; i < string->length(); i++) {
    297       result_vec.push_back(string->raw_data()[i]);
    298     }
    299   }
    300   std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
    301   memcpy(result.get(), result_vec.data(), result_vec.size());
    302   result[result_vec.size()] = '\0';
    303   return result;
    304 }
    305 
    306 ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
    307                                              Kind kind, bool is_computed_name)
    308     : LiteralProperty(key, value, is_computed_name),
    309       kind_(kind),
    310       emit_store_(true) {}
    311 
    312 ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
    313                                              Expression* key, Expression* value,
    314                                              bool is_computed_name)
    315     : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
    316   if (!is_computed_name && key->AsLiteral()->IsString() &&
    317       key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
    318     kind_ = PROTOTYPE;
    319   } else if (value_->AsMaterializedLiteral() != nullptr) {
    320     kind_ = MATERIALIZED_LITERAL;
    321   } else if (value_->IsLiteral()) {
    322     kind_ = CONSTANT;
    323   } else {
    324     kind_ = COMPUTED;
    325   }
    326 }
    327 
    328 bool LiteralProperty::NeedsSetFunctionName() const {
    329   return is_computed_name_ && (value_->IsAnonymousFunctionDefinition() ||
    330                                value_->IsConciseMethodDefinition() ||
    331                                value_->IsAccessorFunctionDefinition());
    332 }
    333 
    334 ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
    335                                            Kind kind, bool is_static,
    336                                            bool is_computed_name)
    337     : LiteralProperty(key, value, is_computed_name),
    338       kind_(kind),
    339       is_static_(is_static),
    340       private_or_computed_name_var_(nullptr) {}
    341 
    342 bool ObjectLiteral::Property::IsCompileTimeValue() const {
    343   return kind_ == CONSTANT ||
    344          (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
    345 }
    346 
    347 
    348 void ObjectLiteral::Property::set_emit_store(bool emit_store) {
    349   emit_store_ = emit_store;
    350 }
    351 
    352 bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
    353 
    354 void ObjectLiteral::CalculateEmitStore(Zone* zone) {
    355   const auto GETTER = ObjectLiteral::Property::GETTER;
    356   const auto SETTER = ObjectLiteral::Property::SETTER;
    357 
    358   ZoneAllocationPolicy allocator(zone);
    359 
    360   CustomMatcherZoneHashMap table(
    361       Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
    362   for (int i = properties()->length() - 1; i >= 0; i--) {
    363     ObjectLiteral::Property* property = properties()->at(i);
    364     if (property->is_computed_name()) continue;
    365     if (property->IsPrototype()) continue;
    366     Literal* literal = property->key()->AsLiteral();
    367     DCHECK(!literal->IsNullLiteral());
    368 
    369     uint32_t hash = literal->Hash();
    370     ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
    371     if (entry->value == nullptr) {
    372       entry->value = property;
    373     } else {
    374       // We already have a later definition of this property, so we don't need
    375       // to emit a store for the current one.
    376       //
    377       // There are two subtleties here.
    378       //
    379       // (1) Emitting a store might actually be incorrect. For example, in {get
    380       // foo() {}, foo: 42}, the getter store would override the data property
    381       // (which, being a non-computed compile-time valued property, is already
    382       // part of the initial literal object.
    383       //
    384       // (2) If the later definition is an accessor (say, a getter), and the
    385       // current definition is a complementary accessor (here, a setter), then
    386       // we still must emit a store for the current definition.
    387 
    388       auto later_kind =
    389           static_cast<ObjectLiteral::Property*>(entry->value)->kind();
    390       bool complementary_accessors =
    391           (property->kind() == GETTER && later_kind == SETTER) ||
    392           (property->kind() == SETTER && later_kind == GETTER);
    393       if (!complementary_accessors) {
    394         property->set_emit_store(false);
    395         if (later_kind == GETTER || later_kind == SETTER) {
    396           entry->value = property;
    397         }
    398       }
    399     }
    400   }
    401 }
    402 
    403 void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
    404   // We still check for __proto__:null after computed property names.
    405   for (; i < properties()->length(); i++) {
    406     if (properties()->at(i)->IsNullPrototype()) {
    407       set_has_null_protoype(true);
    408       break;
    409     }
    410   }
    411 }
    412 
    413 int ObjectLiteral::InitDepthAndFlags() {
    414   if (is_initialized()) return depth();
    415   bool is_simple = true;
    416   bool has_seen_prototype = false;
    417   bool needs_initial_allocation_site = false;
    418   int depth_acc = 1;
    419   uint32_t nof_properties = 0;
    420   uint32_t elements = 0;
    421   uint32_t max_element_index = 0;
    422   for (int i = 0; i < properties()->length(); i++) {
    423     ObjectLiteral::Property* property = properties()->at(i);
    424     if (property->IsPrototype()) {
    425       has_seen_prototype = true;
    426       // __proto__:null has no side-effects and is set directly on the
    427       // boilerplate.
    428       if (property->IsNullPrototype()) {
    429         set_has_null_protoype(true);
    430         continue;
    431       }
    432       DCHECK(!has_null_prototype());
    433       is_simple = false;
    434       continue;
    435     }
    436     if (nof_properties == boilerplate_properties_) {
    437       DCHECK(property->is_computed_name());
    438       is_simple = false;
    439       if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
    440       break;
    441     }
    442     DCHECK(!property->is_computed_name());
    443 
    444     MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
    445     if (literal != nullptr) {
    446       int subliteral_depth = literal->InitDepthAndFlags() + 1;
    447       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
    448       needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
    449     }
    450 
    451     Literal* key = property->key()->AsLiteral();
    452     Expression* value = property->value();
    453 
    454     bool is_compile_time_value = value->IsCompileTimeValue();
    455     is_simple = is_simple && is_compile_time_value;
    456 
    457     // Keep track of the number of elements in the object literal and
    458     // the largest element index.  If the largest element index is
    459     // much larger than the number of elements, creating an object
    460     // literal with fast elements will be a waste of space.
    461     uint32_t element_index = 0;
    462     if (key->AsArrayIndex(&element_index)) {
    463       max_element_index = Max(element_index, max_element_index);
    464       elements++;
    465     } else {
    466       DCHECK(key->IsPropertyName());
    467     }
    468 
    469     nof_properties++;
    470   }
    471 
    472   set_depth(depth_acc);
    473   set_is_simple(is_simple);
    474   set_needs_initial_allocation_site(needs_initial_allocation_site);
    475   set_has_elements(elements > 0);
    476   set_fast_elements((max_element_index <= 32) ||
    477                     ((2 * elements) >= max_element_index));
    478   return depth_acc;
    479 }
    480 
    481 void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
    482   if (!boilerplate_description_.is_null()) return;
    483 
    484   int index_keys = 0;
    485   bool has_seen_proto = false;
    486   for (int i = 0; i < properties()->length(); i++) {
    487     ObjectLiteral::Property* property = properties()->at(i);
    488     if (property->IsPrototype()) {
    489       has_seen_proto = true;
    490       continue;
    491     }
    492     if (property->is_computed_name()) {
    493       continue;
    494     }
    495 
    496     Literal* key = property->key()->AsLiteral();
    497 
    498     if (!key->IsPropertyName()) {
    499       index_keys++;
    500     }
    501   }
    502 
    503   Handle<ObjectBoilerplateDescription> boilerplate_description =
    504       isolate->factory()->NewObjectBoilerplateDescription(
    505           boilerplate_properties_, properties()->length(), index_keys,
    506           has_seen_proto);
    507 
    508   int position = 0;
    509   for (int i = 0; i < properties()->length(); i++) {
    510     ObjectLiteral::Property* property = properties()->at(i);
    511     if (property->IsPrototype()) continue;
    512 
    513     if (static_cast<uint32_t>(position) == boilerplate_properties_) {
    514       DCHECK(property->is_computed_name());
    515       break;
    516     }
    517     DCHECK(!property->is_computed_name());
    518 
    519     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
    520     if (m_literal != nullptr) {
    521       m_literal->BuildConstants(isolate);
    522     }
    523 
    524     // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
    525     // value for COMPUTED properties, the real value is filled in at
    526     // runtime. The enumeration order is maintained.
    527     Literal* key_literal = property->key()->AsLiteral();
    528     uint32_t element_index = 0;
    529     Handle<Object> key =
    530         key_literal->AsArrayIndex(&element_index)
    531             ? isolate->factory()->NewNumberFromUint(element_index)
    532             : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
    533 
    534     Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
    535 
    536     // Add name, value pair to the fixed array.
    537     boilerplate_description->set_key_value(position++, *key, *value);
    538   }
    539 
    540   boilerplate_description->set_flags(EncodeLiteralType());
    541 
    542   boilerplate_description_ = boilerplate_description;
    543 }
    544 
    545 bool ObjectLiteral::IsFastCloningSupported() const {
    546   // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
    547   // literals don't support copy-on-write (COW) elements for now.
    548   // TODO(mvstanton): make object literals support COW elements.
    549   return fast_elements() && is_shallow() &&
    550          properties_count() <=
    551              ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
    552 }
    553 
    554 bool ArrayLiteral::is_empty() const {
    555   DCHECK(is_initialized());
    556   return values()->is_empty() && (boilerplate_description().is_null() ||
    557                                   boilerplate_description()->is_empty());
    558 }
    559 
    560 int ArrayLiteral::InitDepthAndFlags() {
    561   if (is_initialized()) return depth();
    562 
    563   int constants_length =
    564       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
    565 
    566   // Fill in the literals.
    567   bool is_simple = first_spread_index_ < 0;
    568   int depth_acc = 1;
    569   int array_index = 0;
    570   for (; array_index < constants_length; array_index++) {
    571     Expression* element = values()->at(array_index);
    572     MaterializedLiteral* literal = element->AsMaterializedLiteral();
    573     if (literal != nullptr) {
    574       int subliteral_depth = literal->InitDepthAndFlags() + 1;
    575       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
    576     }
    577 
    578     if (!element->IsCompileTimeValue()) {
    579       is_simple = false;
    580     }
    581   }
    582 
    583   set_depth(depth_acc);
    584   set_is_simple(is_simple);
    585   // Array literals always need an initial allocation site to properly track
    586   // elements transitions.
    587   set_needs_initial_allocation_site(true);
    588   return depth_acc;
    589 }
    590 
    591 void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
    592   if (!boilerplate_description_.is_null()) return;
    593 
    594   int constants_length =
    595       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
    596   ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
    597   Handle<FixedArray> fixed_array =
    598       isolate->factory()->NewFixedArrayWithHoles(constants_length);
    599 
    600   // Fill in the literals.
    601   bool is_holey = false;
    602   int array_index = 0;
    603   for (; array_index < constants_length; array_index++) {
    604     Expression* element = values()->at(array_index);
    605     DCHECK(!element->IsSpread());
    606     MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
    607     if (m_literal != nullptr) {
    608       m_literal->BuildConstants(isolate);
    609     }
    610 
    611     // New handle scope here, needs to be after BuildContants().
    612     HandleScope scope(isolate);
    613     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
    614     if (boilerplate_value->IsTheHole(isolate)) {
    615       is_holey = true;
    616       continue;
    617     }
    618 
    619     if (boilerplate_value->IsUninitialized(isolate)) {
    620       boilerplate_value = handle(Smi::kZero, isolate);
    621     }
    622 
    623     kind = GetMoreGeneralElementsKind(kind,
    624                                       boilerplate_value->OptimalElementsKind());
    625     fixed_array->set(array_index, *boilerplate_value);
    626   }
    627 
    628   if (is_holey) kind = GetHoleyElementsKind(kind);
    629 
    630   // Simple and shallow arrays can be lazily copied, we transform the
    631   // elements array to a copy-on-write array.
    632   if (is_simple() && depth() == 1 && array_index > 0 &&
    633       IsSmiOrObjectElementsKind(kind)) {
    634     fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
    635   }
    636 
    637   Handle<FixedArrayBase> elements = fixed_array;
    638   if (IsDoubleElementsKind(kind)) {
    639     ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
    640     elements = isolate->factory()->NewFixedDoubleArray(constants_length);
    641     // We are copying from non-fast-double to fast-double.
    642     ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
    643     accessor->CopyElements(isolate, fixed_array, from_kind, elements,
    644                            constants_length);
    645   }
    646 
    647   boilerplate_description_ =
    648       isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
    649 }
    650 
    651 bool ArrayLiteral::IsFastCloningSupported() const {
    652   return depth() <= 1 &&
    653          values()->length() <=
    654              ConstructorBuiltins::kMaximumClonedShallowArrayElements;
    655 }
    656 
    657 bool MaterializedLiteral::IsSimple() const {
    658   if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
    659   if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
    660   DCHECK(IsRegExpLiteral());
    661   return false;
    662 }
    663 
    664 Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
    665                                                         Isolate* isolate) {
    666   if (expression->IsLiteral()) {
    667     return expression->AsLiteral()->BuildValue(isolate);
    668   }
    669   if (expression->IsCompileTimeValue()) {
    670     if (expression->IsObjectLiteral()) {
    671       ObjectLiteral* object_literal = expression->AsObjectLiteral();
    672       DCHECK(object_literal->is_simple());
    673       return object_literal->boilerplate_description();
    674     } else {
    675       DCHECK(expression->IsArrayLiteral());
    676       ArrayLiteral* array_literal = expression->AsArrayLiteral();
    677       DCHECK(array_literal->is_simple());
    678       return array_literal->boilerplate_description();
    679     }
    680   }
    681   return isolate->factory()->uninitialized_value();
    682 }
    683 
    684 int MaterializedLiteral::InitDepthAndFlags() {
    685   if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
    686   if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
    687   DCHECK(IsRegExpLiteral());
    688   return 1;
    689 }
    690 
    691 bool MaterializedLiteral::NeedsInitialAllocationSite() {
    692   if (IsArrayLiteral()) {
    693     return AsArrayLiteral()->needs_initial_allocation_site();
    694   }
    695   if (IsObjectLiteral()) {
    696     return AsObjectLiteral()->needs_initial_allocation_site();
    697   }
    698   DCHECK(IsRegExpLiteral());
    699   return false;
    700 }
    701 
    702 void MaterializedLiteral::BuildConstants(Isolate* isolate) {
    703   if (IsArrayLiteral()) {
    704     AsArrayLiteral()->BuildBoilerplateDescription(isolate);
    705     return;
    706   }
    707   if (IsObjectLiteral()) {
    708     AsObjectLiteral()->BuildBoilerplateDescription(isolate);
    709     return;
    710   }
    711   DCHECK(IsRegExpLiteral());
    712 }
    713 
    714 Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
    715     Isolate* isolate) {
    716   Handle<FixedArray> raw_strings =
    717       isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
    718   bool raw_and_cooked_match = true;
    719   for (int i = 0; i < raw_strings->length(); ++i) {
    720     if (this->cooked_strings()->at(i) == nullptr ||
    721         *this->raw_strings()->at(i)->string() !=
    722             *this->cooked_strings()->at(i)->string()) {
    723       raw_and_cooked_match = false;
    724     }
    725     raw_strings->set(i, *this->raw_strings()->at(i)->string());
    726   }
    727   Handle<FixedArray> cooked_strings = raw_strings;
    728   if (!raw_and_cooked_match) {
    729     cooked_strings = isolate->factory()->NewFixedArray(
    730         this->cooked_strings()->length(), TENURED);
    731     for (int i = 0; i < cooked_strings->length(); ++i) {
    732       if (this->cooked_strings()->at(i) != nullptr) {
    733         cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
    734       } else {
    735         cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
    736       }
    737     }
    738   }
    739   return isolate->factory()->NewTemplateObjectDescription(raw_strings,
    740                                                           cooked_strings);
    741 }
    742 
    743 static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
    744   // Add is not commutative due to potential for string addition.
    745   return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
    746          op == Token::BIT_XOR;
    747 }
    748 
    749 // Check for the pattern: x + 1.
    750 static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
    751                                      Expression** expr, Smi** literal) {
    752   if (right->IsSmiLiteral()) {
    753     *expr = left;
    754     *literal = right->AsLiteral()->AsSmiLiteral();
    755     return true;
    756   }
    757   return false;
    758 }
    759 
    760 bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
    761                                             Smi** literal) {
    762   return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
    763          (IsCommutativeOperationWithSmiLiteral(op()) &&
    764           MatchSmiLiteralOperation(right_, left_, subexpr, literal));
    765 }
    766 
    767 static bool IsTypeof(Expression* expr) {
    768   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
    769   return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
    770 }
    771 
    772 // Check for the pattern: typeof <expression> equals <string literal>.
    773 static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
    774                                       Expression* right, Expression** expr,
    775                                       Literal** literal) {
    776   if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
    777     *expr = left->AsUnaryOperation()->expression();
    778     *literal = right->AsLiteral();
    779     return true;
    780   }
    781   return false;
    782 }
    783 
    784 bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
    785                                               Literal** literal) {
    786   return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
    787          MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
    788 }
    789 
    790 
    791 static bool IsVoidOfLiteral(Expression* expr) {
    792   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
    793   return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
    794          maybe_unary->expression()->IsLiteral();
    795 }
    796 
    797 
    798 // Check for the pattern: void <literal> equals <expression> or
    799 // undefined equals <expression>
    800 static bool MatchLiteralCompareUndefined(Expression* left,
    801                                          Token::Value op,
    802                                          Expression* right,
    803                                          Expression** expr) {
    804   if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
    805     *expr = right;
    806     return true;
    807   }
    808   if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
    809     *expr = right;
    810     return true;
    811   }
    812   return false;
    813 }
    814 
    815 bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
    816   return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
    817          MatchLiteralCompareUndefined(right_, op(), left_, expr);
    818 }
    819 
    820 // Check for the pattern: null equals <expression>
    821 static bool MatchLiteralCompareNull(Expression* left,
    822                                     Token::Value op,
    823                                     Expression* right,
    824                                     Expression** expr) {
    825   if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
    826     *expr = right;
    827     return true;
    828   }
    829   return false;
    830 }
    831 
    832 bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
    833   return MatchLiteralCompareNull(left_, op(), right_, expr) ||
    834          MatchLiteralCompareNull(right_, op(), left_, expr);
    835 }
    836 
    837 Call::CallType Call::GetCallType() const {
    838   VariableProxy* proxy = expression()->AsVariableProxy();
    839   if (proxy != nullptr) {
    840     if (proxy->var()->IsUnallocated()) {
    841       return GLOBAL_CALL;
    842     } else if (proxy->var()->IsLookupSlot()) {
    843       // Calls going through 'with' always use VariableMode::kDynamic rather
    844       // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
    845       return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
    846                                                             : OTHER_CALL;
    847     }
    848   }
    849 
    850   if (expression()->IsSuperCallReference()) return SUPER_CALL;
    851 
    852   Property* property = expression()->AsProperty();
    853   if (property != nullptr) {
    854     bool is_super = property->IsSuperAccess();
    855     if (property->key()->IsPropertyName()) {
    856       return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
    857     } else {
    858       return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
    859     }
    860   }
    861 
    862   if (expression()->IsResolvedProperty()) {
    863     return RESOLVED_PROPERTY_CALL;
    864   }
    865 
    866   return OTHER_CALL;
    867 }
    868 
    869 CaseClause::CaseClause(Expression* label, ZonePtrList<Statement>* statements)
    870     : label_(label), statements_(statements) {}
    871 
    872 bool Literal::IsPropertyName() const {
    873   if (type() != kString) return false;
    874   uint32_t index;
    875   return !string_->AsArrayIndex(&index);
    876 }
    877 
    878 bool Literal::ToUint32(uint32_t* value) const {
    879   switch (type()) {
    880     case kString:
    881       return string_->AsArrayIndex(value);
    882     case kSmi:
    883       if (smi_ < 0) return false;
    884       *value = static_cast<uint32_t>(smi_);
    885       return true;
    886     case kHeapNumber:
    887       return DoubleToUint32IfEqualToSelf(AsNumber(), value);
    888     default:
    889       return false;
    890   }
    891 }
    892 
    893 bool Literal::AsArrayIndex(uint32_t* value) const {
    894   return ToUint32(value) && *value != kMaxUInt32;
    895 }
    896 
    897 Handle<Object> Literal::BuildValue(Isolate* isolate) const {
    898   switch (type()) {
    899     case kSmi:
    900       return handle(Smi::FromInt(smi_), isolate);
    901     case kHeapNumber:
    902       return isolate->factory()->NewNumber(number_, TENURED);
    903     case kString:
    904       return string_->string();
    905     case kSymbol:
    906       return isolate->factory()->home_object_symbol();
    907     case kBoolean:
    908       return isolate->factory()->ToBoolean(boolean_);
    909     case kNull:
    910       return isolate->factory()->null_value();
    911     case kUndefined:
    912       return isolate->factory()->undefined_value();
    913     case kTheHole:
    914       return isolate->factory()->the_hole_value();
    915     case kBigInt:
    916       // This should never fail: the parser will never create a BigInt
    917       // literal that cannot be allocated.
    918       return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
    919   }
    920   UNREACHABLE();
    921 }
    922 
    923 bool Literal::ToBooleanIsTrue() const {
    924   switch (type()) {
    925     case kSmi:
    926       return smi_ != 0;
    927     case kHeapNumber:
    928       return DoubleToBoolean(number_);
    929     case kString:
    930       return !string_->IsEmpty();
    931     case kNull:
    932     case kUndefined:
    933       return false;
    934     case kBoolean:
    935       return boolean_;
    936     case kBigInt: {
    937       const char* bigint_str = bigint_.c_str();
    938       size_t length = strlen(bigint_str);
    939       DCHECK_GT(length, 0);
    940       if (length == 1 && bigint_str[0] == '0') return false;
    941       // Skip over any radix prefix; BigInts with length > 1 only
    942       // begin with zero if they include a radix.
    943       for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
    944         if (bigint_str[i] != '0') return true;
    945       }
    946       return false;
    947     }
    948     case kSymbol:
    949       return true;
    950     case kTheHole:
    951       UNREACHABLE();
    952   }
    953   UNREACHABLE();
    954 }
    955 
    956 uint32_t Literal::Hash() {
    957   return IsString() ? AsRawString()->Hash()
    958                     : ComputeLongHash(double_to_uint64(AsNumber()));
    959 }
    960 
    961 
    962 // static
    963 bool Literal::Match(void* a, void* b) {
    964   Literal* x = static_cast<Literal*>(a);
    965   Literal* y = static_cast<Literal*>(b);
    966   return (x->IsString() && y->IsString() &&
    967           x->AsRawString() == y->AsRawString()) ||
    968          (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
    969 }
    970 
    971 Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
    972   int int_value;
    973   if (DoubleToSmiInteger(number, &int_value)) {
    974     return NewSmiLiteral(int_value, pos);
    975   }
    976   return new (zone_) Literal(number, pos);
    977 }
    978 
    979 const char* CallRuntime::debug_name() {
    980 #ifdef DEBUG
    981   return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
    982                         : function_->name;
    983 #else
    984   return is_jsruntime() ? "(context function)" : function_->name;
    985 #endif  // DEBUG
    986 }
    987 
    988 #define RETURN_LABELS(NodeType) \
    989   case k##NodeType:             \
    990     return static_cast<const NodeType*>(this)->labels();
    991 
    992 ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
    993   switch (node_type()) {
    994     BREAKABLE_NODE_LIST(RETURN_LABELS)
    995     ITERATION_NODE_LIST(RETURN_LABELS)
    996     default:
    997       UNREACHABLE();
    998   }
    999 }
   1000 
   1001 #undef RETURN_LABELS
   1002 
   1003 }  // namespace internal
   1004 }  // namespace v8
   1005