LCOV - code coverage report
Current view: top level - src/ast - ast.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 382 399 95.7 %
Date: 2019-02-19 Functions: 71 76 93.4 %

          Line data    Source code
       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/contexts.h"
      16             : #include "src/conversions-inl.h"
      17             : #include "src/double.h"
      18             : #include "src/elements.h"
      19             : #include "src/objects-inl.h"
      20             : #include "src/objects/literal-objects-inl.h"
      21             : #include "src/objects/literal-objects.h"
      22             : #include "src/objects/map.h"
      23             : #include "src/property-details.h"
      24             : #include "src/property.h"
      25             : #include "src/string-stream.h"
      26             : #include "src/zone/zone-list-inl.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       33520 : IterationStatement* AstNode::AsIterationStatement() {
      67       33520 :   switch (node_type()) {
      68         345 :     ITERATION_NODE_LIST(RETURN_NODE);
      69             :     default:
      70             :       return nullptr;
      71             :   }
      72             : }
      73             : 
      74    21199180 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
      75    22460804 :   switch (node_type()) {
      76       63973 :     LITERAL_NODE_LIST(RETURN_NODE);
      77             :     default:
      78             :       return nullptr;
      79             :   }
      80             : }
      81             : 
      82             : #undef RETURN_NODE
      83             : 
      84      838183 : bool Expression::IsSmiLiteral() const {
      85     1586002 :   return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
      86             : }
      87             : 
      88     2780866 : bool Expression::IsNumberLiteral() const {
      89     4589231 :   return IsLiteral() && AsLiteral()->IsNumber();
      90             : }
      91             : 
      92      394213 : bool Expression::IsStringLiteral() const {
      93     1080922 :   return IsLiteral() && AsLiteral()->type() == Literal::kString;
      94             : }
      95             : 
      96     9177869 : bool Expression::IsPropertyName() const {
      97    16486206 :   return IsLiteral() && AsLiteral()->IsPropertyName();
      98             : }
      99             : 
     100     1446632 : bool Expression::IsNullLiteral() const {
     101     2233785 :   return IsLiteral() && AsLiteral()->type() == Literal::kNull;
     102             : }
     103             : 
     104        5109 : bool Expression::IsTheHoleLiteral() const {
     105        6675 :   return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
     106             : }
     107             : 
     108    16923760 : bool Expression::IsCompileTimeValue() {
     109    16923827 :   if (IsLiteral()) return true;
     110             :   MaterializedLiteral* literal = AsMaterializedLiteral();
     111     1261624 :   if (literal == nullptr) return false;
     112      222744 :   return literal->IsSimple();
     113             : }
     114             : 
     115     1557792 : bool Expression::IsUndefinedLiteral() const {
     116     2354124 :   if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
     117             : 
     118     2229412 :   const VariableProxy* var_proxy = AsVariableProxy();
     119     1548256 :   if (var_proxy == nullptr) return false;
     120             :   Variable* var = var_proxy->var();
     121             :   // The global identifier "undefined" is immutable. Everything
     122             :   // else could be reassigned.
     123     1568203 :   return var != nullptr && var->IsUnallocated() &&
     124      887060 :          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
     125             : }
     126             : 
     127      948335 : bool Expression::ToBooleanIsTrue() const {
     128      972326 :   return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
     129             : }
     130             : 
     131      933561 : bool Expression::ToBooleanIsFalse() const {
     132      966936 :   return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
     133             : }
     134             : 
     135           0 : bool Expression::IsValidReferenceExpression() const {
     136           0 :   return IsProperty() ||
     137           0 :          (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
     138             : }
     139             : 
     140    11811279 : bool Expression::IsAnonymousFunctionDefinition() const {
     141     1607670 :   return (IsFunctionLiteral() &&
     142    23276356 :           AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
     143        3687 :          (IsClassLiteral() &&
     144    11815013 :           AsClassLiteral()->IsAnonymousFunctionDefinition());
     145             : }
     146             : 
     147    11462682 : bool Expression::IsConciseMethodDefinition() const {
     148    12723993 :   return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
     149             : }
     150             : 
     151    11105432 : bool Expression::IsAccessorFunctionDefinition() const {
     152    12009387 :   return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
     153             : }
     154             : 
     155     5795596 : VariableProxy::VariableProxy(Variable* var, int start_position)
     156             :     : Expression(start_position, kVariableProxy),
     157             :       raw_name_(var->raw_name()),
     158     2897798 :       next_unresolved_(nullptr) {
     159             :   DCHECK(!var->is_this());
     160             :   bit_field_ |= IsAssignedField::encode(false) |
     161             :                 IsResolvedField::encode(false) |
     162     2897798 :                 HoleCheckModeField::encode(HoleCheckMode::kElided);
     163             :   BindTo(var);
     164     2897798 : }
     165             : 
     166     6503508 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
     167             :     : Expression(copy_from->position(), kVariableProxy),
     168    13007016 :       next_unresolved_(nullptr) {
     169     6503508 :   bit_field_ = copy_from->bit_field_;
     170             :   DCHECK(!copy_from->is_resolved());
     171     6503508 :   raw_name_ = copy_from->raw_name_;
     172     6503508 : }
     173             : 
     174    81416788 : void VariableProxy::BindTo(Variable* var) {
     175             :   DCHECK_EQ(raw_name(), var->raw_name());
     176             :   set_var(var);
     177             :   set_is_resolved();
     178             :   var->set_is_used();
     179    42157293 :   if (is_assigned()) var->set_maybe_assigned();
     180    39259495 : }
     181             : 
     182    14168333 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
     183             :                        Expression* value, int pos)
     184    14168333 :     : Expression(pos, node_type), target_(target), value_(value) {
     185    14168333 :   bit_field_ |= TokenField::encode(op);
     186    14168333 : }
     187             : 
     188     1402480 : void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
     189             :   DCHECK(!inferred_name.is_null());
     190      701240 :   inferred_name_ = inferred_name;
     191             :   DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
     192      701240 :   raw_inferred_name_ = nullptr;
     193             :   scope()->set_has_inferred_function_name(true);
     194      701240 : }
     195             : 
     196      461906 : void FunctionLiteral::set_raw_inferred_name(
     197      461906 :     const AstConsString* raw_inferred_name) {
     198             :   DCHECK_NOT_NULL(raw_inferred_name);
     199      461906 :   raw_inferred_name_ = raw_inferred_name;
     200             :   DCHECK(inferred_name_.is_null());
     201      461906 :   inferred_name_ = Handle<String>();
     202             :   scope()->set_has_inferred_function_name(true);
     203      461906 : }
     204             : 
     205     6471715 : bool FunctionLiteral::ShouldEagerCompile() const {
     206     6471715 :   return scope()->ShouldEagerCompile();
     207             : }
     208             : 
     209      716694 : void FunctionLiteral::SetShouldEagerCompile() {
     210      716694 :   scope()->set_should_eager_compile();
     211      716717 : }
     212             : 
     213     3576899 : bool FunctionLiteral::AllowsLazyCompilation() {
     214     3576899 :   return scope()->AllowsLazyCompilation();
     215             : }
     216             : 
     217           0 : Handle<String> FunctionLiteral::name(Isolate* isolate) const {
     218           0 :   return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
     219             : }
     220             : 
     221    10794317 : int FunctionLiteral::start_position() const {
     222    10794317 :   return scope()->start_position();
     223             : }
     224             : 
     225             : 
     226     5117354 : int FunctionLiteral::end_position() const {
     227     5117354 :   return scope()->end_position();
     228             : }
     229             : 
     230             : 
     231     4912447 : LanguageMode FunctionLiteral::language_mode() const {
     232     4912447 :   return scope()->language_mode();
     233             : }
     234             : 
     235    12172869 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
     236             : 
     237      293320 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
     238      586643 :   if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
     239             :   DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
     240      306843 :   return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
     241             : }
     242             : 
     243          23 : std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
     244             :   const AstConsString* cons_string;
     245          23 :   if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
     246             :     cons_string = raw_name_;
     247           6 :   } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
     248             :     cons_string = raw_inferred_name_;
     249           6 :   } else if (!inferred_name_.is_null()) {
     250             :     AllowHandleDereference allow_deref;
     251           6 :     return inferred_name_->ToCString();
     252             :   } else {
     253           0 :     char* empty_str = new char[1];
     254           0 :     empty_str[0] = 0;
     255             :     return std::unique_ptr<char[]>(empty_str);
     256             :   }
     257             : 
     258             :   // TODO(rmcilroy): Deal with two-character strings.
     259             :   std::vector<char> result_vec;
     260          17 :   std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
     261          51 :   for (const AstRawString* string : strings) {
     262          17 :     if (!string->is_one_byte()) break;
     263         335 :     for (int i = 0; i < string->length(); i++) {
     264         318 :       result_vec.push_back(string->raw_data()[i]);
     265             :     }
     266             :   }
     267          34 :   std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
     268          17 :   memcpy(result.get(), result_vec.data(), result_vec.size());
     269          34 :   result[result_vec.size()] = '\0';
     270             :   return result;
     271             : }
     272             : 
     273      136954 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
     274             :                                              Kind kind, bool is_computed_name)
     275             :     : LiteralProperty(key, value, is_computed_name),
     276             :       kind_(kind),
     277      136954 :       emit_store_(true) {}
     278             : 
     279     4337756 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
     280             :                                              Expression* key, Expression* value,
     281             :                                              bool is_computed_name)
     282     2899167 :     : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
     283     7223160 :   if (!is_computed_name && key->AsLiteral()->IsString() &&
     284     1438589 :       key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
     285        6587 :     kind_ = PROTOTYPE;
     286     2892638 :   } else if (value_->AsMaterializedLiteral() != nullptr) {
     287       59556 :     kind_ = MATERIALIZED_LITERAL;
     288     2833056 :   } else if (value_->IsLiteral()) {
     289     1851541 :     kind_ = CONSTANT;
     290             :   } else {
     291      981515 :     kind_ = COMPUTED;
     292             :   }
     293     2899199 : }
     294             : 
     295     3390410 : bool LiteralProperty::NeedsSetFunctionName() const {
     296     3419745 :   return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
     297       51771 :                                 value_->IsConciseMethodDefinition() ||
     298     3412849 :                                 value_->IsAccessorFunctionDefinition());
     299             : }
     300             : 
     301      436427 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
     302             :                                            Kind kind, bool is_static,
     303             :                                            bool is_computed_name,
     304             :                                            bool is_private)
     305             :     : LiteralProperty(key, value, is_computed_name),
     306             :       kind_(kind),
     307             :       is_static_(is_static),
     308             :       is_private_(is_private),
     309      436427 :       private_or_computed_name_var_(nullptr) {}
     310             : 
     311     2007299 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
     312     2007299 :   return kind_ == CONSTANT ||
     313       43992 :          (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
     314             : }
     315             : 
     316             : 
     317           0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
     318        3363 :   emit_store_ = emit_store;
     319           0 : }
     320             : 
     321      247388 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
     322             : 
     323      586981 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
     324             :   const auto GETTER = ObjectLiteral::Property::GETTER;
     325             :   const auto SETTER = ObjectLiteral::Property::SETTER;
     326             : 
     327             :   ZoneAllocationPolicy allocator(zone);
     328             : 
     329             :   CustomMatcherZoneHashMap table(
     330             :       Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
     331     3594868 :   for (int i = properties()->length() - 1; i >= 0; i--) {
     332     3011884 :     ObjectLiteral::Property* property = properties()->at(i);
     333     3007804 :     if (property->is_computed_name()) continue;
     334     2986913 :     if (property->IsPrototype()) continue;
     335     2980279 :     Literal* literal = property->key()->AsLiteral();
     336             :     DCHECK(!literal->IsNullLiteral());
     337             : 
     338     2980282 :     uint32_t hash = literal->Hash();
     339     5960519 :     ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
     340     2984376 :     if (entry->value == nullptr) {
     341     2976216 :       entry->value = property;
     342             :     } else {
     343             :       // We already have a later definition of this property, so we don't need
     344             :       // to emit a store for the current one.
     345             :       //
     346             :       // There are two subtleties here.
     347             :       //
     348             :       // (1) Emitting a store might actually be incorrect. For example, in {get
     349             :       // foo() {}, foo: 42}, the getter store would override the data property
     350             :       // (which, being a non-computed compile-time valued property, is already
     351             :       // part of the initial literal object.
     352             :       //
     353             :       // (2) If the later definition is an accessor (say, a getter), and the
     354             :       // current definition is a complementary accessor (here, a setter), then
     355             :       // we still must emit a store for the current definition.
     356             : 
     357             :       auto later_kind =
     358             :           static_cast<ObjectLiteral::Property*>(entry->value)->kind();
     359             :       bool complementary_accessors =
     360        4080 :           (property->kind() == GETTER && later_kind == SETTER) ||
     361         204 :           (property->kind() == SETTER && later_kind == GETTER);
     362        4080 :       if (!complementary_accessors) {
     363             :         property->set_emit_store(false);
     364        3363 :         if (later_kind == GETTER || later_kind == SETTER) {
     365        1066 :           entry->value = property;
     366             :         }
     367             :       }
     368             :     }
     369             :   }
     370      587064 : }
     371             : 
     372        2091 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
     373             :   // We still check for __proto__:null after computed property names.
     374        5145 :   for (; i < properties()->length(); i++) {
     375        6118 :     if (properties()->at(i)->IsNullPrototype()) {
     376             :       set_has_null_protoype(true);
     377             :       break;
     378             :     }
     379             :   }
     380        2091 : }
     381             : 
     382      262509 : int ObjectLiteral::InitDepthAndFlags() {
     383      280260 :   if (is_initialized()) return depth();
     384             :   bool is_simple = true;
     385             :   bool has_seen_prototype = false;
     386             :   bool needs_initial_allocation_site = false;
     387             :   int depth_acc = 1;
     388             :   uint32_t nof_properties = 0;
     389             :   uint32_t elements = 0;
     390             :   uint32_t max_element_index = 0;
     391     2038763 :   for (int i = 0; i < properties()->length(); i++) {
     392     2040861 :     ObjectLiteral::Property* property = properties()->at(i);
     393     2040861 :     if (property->IsPrototype()) {
     394             :       has_seen_prototype = true;
     395             :       // __proto__:null has no side-effects and is set directly on the
     396             :       // boilerplate.
     397        4091 :       if (property->IsNullPrototype()) {
     398             :         set_has_null_protoype(true);
     399        4091 :         continue;
     400             :       }
     401             :       DCHECK(!has_null_prototype());
     402             :       is_simple = false;
     403             :       continue;
     404             :     }
     405     2036787 :     if (nof_properties == boilerplate_properties_) {
     406             :       DCHECK(property->is_computed_name());
     407             :       is_simple = false;
     408        2124 :       if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
     409        2124 :       break;
     410             :     }
     411             :     DCHECK(!property->is_computed_name());
     412             : 
     413     4069306 :     MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
     414     2034663 :     if (literal != nullptr) {
     415       45458 :       int subliteral_depth = literal->InitDepthAndFlags() + 1;
     416       45458 :       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
     417       45458 :       needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
     418             :     }
     419             : 
     420     2034662 :     Literal* key = property->key()->AsLiteral();
     421             :     Expression* value = property->value();
     422             : 
     423     2034643 :     bool is_compile_time_value = value->IsCompileTimeValue();
     424     2034695 :     is_simple = is_simple && is_compile_time_value;
     425             : 
     426             :     // Keep track of the number of elements in the object literal and
     427             :     // the largest element index.  If the largest element index is
     428             :     // much larger than the number of elements, creating an object
     429             :     // literal with fast elements will be a waste of space.
     430     2034695 :     uint32_t element_index = 0;
     431     2034672 :     if (key->AsArrayIndex(&element_index)) {
     432      784534 :       max_element_index = Max(element_index, max_element_index);
     433      784534 :       elements++;
     434             :     } else {
     435             :       DCHECK(key->IsPropertyName());
     436             :     }
     437             : 
     438     2034672 :     nof_properties++;
     439             :   }
     440             : 
     441             :   set_depth(depth_acc);
     442             :   set_is_simple(is_simple);
     443             :   set_needs_initial_allocation_site(needs_initial_allocation_site);
     444      244784 :   set_has_elements(elements > 0);
     445      245321 :   set_fast_elements((max_element_index <= 32) ||
     446         537 :                     ((2 * elements) >= max_element_index));
     447      244784 :   return depth_acc;
     448             : }
     449             : 
     450      204176 : void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
     451      408357 :   if (!boilerplate_description_.is_null()) return;
     452             : 
     453             :   int index_keys = 0;
     454             :   bool has_seen_proto = false;
     455     1957366 :   for (int i = 0; i < properties()->length(); i++) {
     456     1957364 :     ObjectLiteral::Property* property = properties()->at(i);
     457     1957364 :     if (property->IsPrototype()) {
     458             :       has_seen_proto = true;
     459             :       continue;
     460             :     }
     461     1954080 :     if (property->is_computed_name()) continue;
     462             : 
     463     1953534 :     Literal* key = property->key()->AsLiteral();
     464     1953538 :     if (!key->IsPropertyName()) index_keys++;
     465             :   }
     466             : 
     467             :   Handle<ObjectBoilerplateDescription> boilerplate_description =
     468             :       isolate->factory()->NewObjectBoilerplateDescription(
     469             :           boilerplate_properties_, properties()->length(), index_keys,
     470      202070 :           has_seen_proto);
     471             : 
     472             :   int position = 0;
     473     2158596 :   for (int i = 0; i < properties()->length(); i++) {
     474     1956947 :     ObjectLiteral::Property* property = properties()->at(i);
     475     1960227 :     if (property->IsPrototype()) continue;
     476             : 
     477     1953667 :     if (static_cast<uint32_t>(position) == boilerplate_properties_) {
     478             :       DCHECK(property->is_computed_name());
     479         424 :       break;
     480             :     }
     481             :     DCHECK(!property->is_computed_name());
     482             : 
     483     3906488 :     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
     484     1953243 :     if (m_literal != nullptr) {
     485       44163 :       m_literal->BuildConstants(isolate);
     486             :     }
     487             : 
     488             :     // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
     489             :     // value for COMPUTED properties, the real value is filled in at
     490             :     // runtime. The enumeration order is maintained.
     491     3123684 :     Literal* key_literal = property->key()->AsLiteral();
     492     1953244 :     uint32_t element_index = 0;
     493             :     Handle<Object> key =
     494             :         key_literal->AsArrayIndex(&element_index)
     495      782804 :             ? isolate->factory()->NewNumberFromUint(element_index)
     496     3906490 :             : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
     497             : 
     498     1953245 :     Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
     499             : 
     500             :     // Add name, value pair to the fixed array.
     501     3906490 :     boilerplate_description->set_key_value(position++, *key, *value);
     502             :   }
     503             : 
     504             :   boilerplate_description->set_flags(EncodeLiteralType());
     505             : 
     506      202073 :   boilerplate_description_ = boilerplate_description;
     507             : }
     508             : 
     509      380765 : bool ObjectLiteral::IsFastCloningSupported() const {
     510             :   // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
     511             :   // literals don't support copy-on-write (COW) elements for now.
     512             :   // TODO(mvstanton): make object literals support COW elements.
     513      579931 :   return fast_elements() && is_shallow() &&
     514             :          properties_count() <=
     515      199553 :              ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
     516             : }
     517             : 
     518      387239 : int ArrayLiteral::InitDepthAndFlags() {
     519      392004 :   if (is_initialized()) return depth();
     520             : 
     521             :   int constants_length =
     522      382474 :       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
     523             : 
     524             :   // Fill in the literals.
     525      382474 :   bool is_simple = first_spread_index_ < 0;
     526             :   int depth_acc = 1;
     527             :   int array_index = 0;
     528     7594750 :   for (; array_index < constants_length; array_index++) {
     529     7212253 :     Expression* element = values()->at(array_index);
     530             :     MaterializedLiteral* literal = element->AsMaterializedLiteral();
     531     7212253 :     if (literal != nullptr) {
     532       31474 :       int subliteral_depth = literal->InitDepthAndFlags() + 1;
     533       31473 :       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
     534             :     }
     535             : 
     536     7212252 :     if (!element->IsCompileTimeValue()) {
     537             :       is_simple = false;
     538             :     }
     539             :   }
     540             : 
     541             :   set_depth(depth_acc);
     542             :   set_is_simple(is_simple);
     543             :   // Array literals always need an initial allocation site to properly track
     544             :   // elements transitions.
     545             :   set_needs_initial_allocation_site(true);
     546      382497 :   return depth_acc;
     547             : }
     548             : 
     549      165022 : void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
     550      165022 :   if (!boilerplate_description_.is_null()) return;
     551             : 
     552             :   int constants_length =
     553      165022 :       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
     554             :   ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
     555             :   Handle<FixedArray> fixed_array =
     556      165022 :       isolate->factory()->NewFixedArrayWithHoles(constants_length);
     557             : 
     558             :   // Fill in the literals.
     559             :   bool is_holey = false;
     560             :   int array_index = 0;
     561     7271405 :   for (; array_index < constants_length; array_index++) {
     562     7106383 :     Expression* element = values()->at(array_index);
     563             :     DCHECK(!element->IsSpread());
     564             :     MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
     565     7106383 :     if (m_literal != nullptr) {
     566       28699 :       m_literal->BuildConstants(isolate);
     567             :     }
     568             : 
     569             :     // New handle scope here, needs to be after BuildContants().
     570             :     HandleScope scope(isolate);
     571     7106383 :     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
     572    14212763 :     if (boilerplate_value->IsTheHole(isolate)) {
     573             :       is_holey = true;
     574             :       continue;
     575             :     }
     576             : 
     577    12073679 :     if (boilerplate_value->IsUninitialized(isolate)) {
     578             :       boilerplate_value = handle(Smi::kZero, isolate);
     579             :     }
     580             : 
     581             :     kind = GetMoreGeneralElementsKind(kind,
     582    12073682 :                                       boilerplate_value->OptimalElementsKind());
     583     6036842 :     fixed_array->set(array_index, *boilerplate_value);
     584             :   }
     585             : 
     586      165022 :   if (is_holey) kind = GetHoleyElementsKind(kind);
     587             : 
     588             :   // Simple and shallow arrays can be lazily copied, we transform the
     589             :   // elements array to a copy-on-write array.
     590      404713 :   if (is_simple() && depth() == 1 && array_index > 0 &&
     591             :       IsSmiOrObjectElementsKind(kind)) {
     592       54753 :     fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
     593             :   }
     594             : 
     595             :   Handle<FixedArrayBase> elements = fixed_array;
     596      165021 :   if (IsDoubleElementsKind(kind)) {
     597             :     ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
     598        3306 :     elements = isolate->factory()->NewFixedDoubleArray(constants_length);
     599             :     // We are copying from non-fast-double to fast-double.
     600             :     ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
     601             :     accessor->CopyElements(isolate, fixed_array, from_kind, elements,
     602        6612 :                            constants_length);
     603             :   }
     604             : 
     605             :   boilerplate_description_ =
     606      165021 :       isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
     607             : }
     608             : 
     609      354318 : bool ArrayLiteral::IsFastCloningSupported() const {
     610      701755 :   return depth() <= 1 &&
     611      347437 :          values_.length() <=
     612      354318 :              ConstructorBuiltins::kMaximumClonedShallowArrayElements;
     613             : }
     614             : 
     615      222740 : bool MaterializedLiteral::IsSimple() const {
     616      397796 :   if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
     617      341566 :   if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
     618             :   DCHECK(IsRegExpLiteral());
     619             :   return false;
     620             : }
     621             : 
     622     9059628 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
     623             :                                                         Isolate* isolate) {
     624     9059628 :   if (expression->IsLiteral()) {
     625    17188426 :     return expression->AsLiteral()->BuildValue(isolate);
     626             :   }
     627      465415 :   if (expression->IsCompileTimeValue()) {
     628       40880 :     if (expression->IsObjectLiteral()) {
     629       16648 :       ObjectLiteral* object_literal = expression->AsObjectLiteral();
     630             :       DCHECK(object_literal->is_simple());
     631       16648 :       return object_literal->boilerplate_description();
     632             :     } else {
     633             :       DCHECK(expression->IsArrayLiteral());
     634       24232 :       ArrayLiteral* array_literal = expression->AsArrayLiteral();
     635             :       DCHECK(array_literal->is_simple());
     636       24232 :       return array_literal->boilerplate_description();
     637             :     }
     638             :   }
     639      424535 :   return isolate->factory()->uninitialized_value();
     640             : }
     641             : 
     642       76928 : int MaterializedLiteral::InitDepthAndFlags() {
     643      107824 :   if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
     644       81387 :   if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
     645             :   DCHECK(IsRegExpLiteral());
     646             :   return 1;
     647             : }
     648             : 
     649       45458 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
     650       45458 :   if (IsArrayLiteral()) {
     651       52563 :     return AsArrayLiteral()->needs_initial_allocation_site();
     652             :   }
     653       27937 :   if (IsObjectLiteral()) {
     654       52626 :     return AsObjectLiteral()->needs_initial_allocation_site();
     655             :   }
     656             :   DCHECK(IsRegExpLiteral());
     657             :   return false;
     658             : }
     659             : 
     660       72861 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
     661       72862 :   if (IsArrayLiteral()) {
     662       57052 :     AsArrayLiteral()->BuildBoilerplateDescription(isolate);
     663       28526 :     return;
     664             :   }
     665       44336 :   if (IsObjectLiteral()) {
     666       67346 :     AsObjectLiteral()->BuildBoilerplateDescription(isolate);
     667       33675 :     return;
     668             :   }
     669             :   DCHECK(IsRegExpLiteral());
     670             : }
     671             : 
     672        1718 : Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
     673       12430 :     Isolate* isolate) {
     674             :   Handle<FixedArray> raw_strings =
     675        1718 :       isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
     676             :   bool raw_and_cooked_match = true;
     677        9132 :   for (int i = 0; i < raw_strings->length(); ++i) {
     678        4660 :     if (this->cooked_strings()->at(i) == nullptr ||
     679        1812 :         *this->raw_strings()->at(i)->string() !=
     680        1812 :             *this->cooked_strings()->at(i)->string()) {
     681             :       raw_and_cooked_match = false;
     682             :     }
     683        8544 :     raw_strings->set(i, *this->raw_strings()->at(i)->string());
     684             :   }
     685             :   Handle<FixedArray> cooked_strings = raw_strings;
     686        1718 :   if (!raw_and_cooked_match) {
     687             :     cooked_strings = isolate->factory()->NewFixedArray(
     688        1176 :         this->cooked_strings()->length(), TENURED);
     689        6408 :     for (int i = 0; i < cooked_strings->length(); ++i) {
     690        2028 :       if (this->cooked_strings()->at(i) != nullptr) {
     691        2976 :         cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
     692             :       } else {
     693        2072 :         cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
     694             :       }
     695             :     }
     696             :   }
     697             :   return isolate->factory()->NewTemplateObjectDescription(raw_strings,
     698        1718 :                                                           cooked_strings);
     699             : }
     700             : 
     701             : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
     702             :   // Add is not commutative due to potential for string addition.
     703      262836 :   return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
     704             :          op == Token::BIT_XOR;
     705             : }
     706             : 
     707             : // Check for the pattern: x + 1.
     708      421255 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
     709             :                                      Expression** expr, Smi* literal) {
     710      421255 :   if (right->IsSmiLiteral()) {
     711      119978 :     *expr = left;
     712      359928 :     *literal = right->AsLiteral()->AsSmiLiteral();
     713      119975 :     return true;
     714             :   }
     715             :   return false;
     716             : }
     717             : 
     718      356821 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
     719      262836 :                                             Smi* literal) {
     720      619657 :   return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
     721       64444 :          (IsCommutativeOperationWithSmiLiteral(op()) &&
     722      421270 :           MatchSmiLiteralOperation(right_, left_, subexpr, literal));
     723             : }
     724             : 
     725     1654521 : static bool IsTypeof(Expression* expr) {
     726     1801346 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     727     1801362 :   return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
     728             : }
     729             : 
     730             : // Check for the pattern: typeof <expression> equals <string literal>.
     731     1654520 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
     732             :                                       Expression* right, Expression** expr,
     733             :                                       Literal** literal) {
     734     1753910 :   if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
     735      198780 :     *expr = left->AsUnaryOperation()->expression();
     736      198779 :     *literal = right->AsLiteral();
     737       99389 :     return true;
     738             :   }
     739             :   return false;
     740             : }
     741             : 
     742      876936 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
     743     1654552 :                                               Literal** literal) {
     744     2531505 :   return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
     745     2432187 :          MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
     746             : }
     747             : 
     748             : 
     749     1554150 : static bool IsVoidOfLiteral(Expression* expr) {
     750     1603324 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     751     1603325 :   return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
     752     1554151 :          maybe_unary->expression()->IsLiteral();
     753             : }
     754             : 
     755             : 
     756             : // Check for the pattern: void <literal> equals <expression> or
     757             : // undefined equals <expression>
     758     1554145 : static bool MatchLiteralCompareUndefined(Expression* left,
     759             :                                          Token::Value op,
     760             :                                          Expression* right,
     761             :                                          Expression** expr) {
     762     1556072 :   if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
     763        1129 :     *expr = right;
     764        1129 :     return true;
     765             :   }
     766     1612349 :   if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
     767       59262 :     *expr = right;
     768       59262 :     return true;
     769             :   }
     770             :   return false;
     771             : }
     772             : 
     773     2331700 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
     774     2331700 :   return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
     775     2330769 :          MatchLiteralCompareUndefined(right_, op(), left_, expr);
     776             : }
     777             : 
     778             : // Check for the pattern: null equals <expression>
     779             : static bool MatchLiteralCompareNull(Expression* left,
     780             :                                     Token::Value op,
     781             :                                     Expression* right,
     782             :                                     Expression** expr) {
     783     1439528 :   if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
     784        5069 :     *expr = right;
     785             :     return true;
     786             :   }
     787             :   return false;
     788             : }
     789             : 
     790     2150789 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
     791     2867953 :   return MatchLiteralCompareNull(left_, op(), right_, expr) ||
     792     2150114 :          MatchLiteralCompareNull(right_, op(), left_, expr);
     793             : }
     794             : 
     795     5109594 : Call::CallType Call::GetCallType() const {
     796     9318622 :   VariableProxy* proxy = expression()->AsVariableProxy();
     797     5109656 :   if (proxy != nullptr) {
     798     4209028 :     if (proxy->var()->IsUnallocated()) {
     799             :       return GLOBAL_CALL;
     800      419419 :     } else if (proxy->var()->IsLookupSlot()) {
     801             :       // Calls going through 'with' always use VariableMode::kDynamic rather
     802             :       // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
     803             :       return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
     804      177479 :                                                             : OTHER_CALL;
     805             :     }
     806             :   }
     807             : 
     808     1142568 :   if (expression()->IsSuperCallReference()) return SUPER_CALL;
     809             : 
     810      790084 :   Property* property = expression()->AsProperty();
     811     1137322 :   if (property != nullptr) {
     812             :     bool is_super = property->IsSuperAccess();
     813      790084 :     if (property->key()->IsPropertyName()) {
     814      785475 :       return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
     815             :     } else {
     816        4592 :       return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
     817             :     }
     818             :   }
     819             : 
     820      347246 :   if (expression()->IsResolvedProperty()) {
     821             :     return RESOLVED_PROPERTY_CALL;
     822             :   }
     823             : 
     824      347246 :   return OTHER_CALL;
     825             : }
     826             : 
     827       88853 : CaseClause::CaseClause(Zone* zone, Expression* label,
     828             :                        const ScopedPtrList<Statement>& statements)
     829       88853 :     : label_(label), statements_(0, nullptr) {
     830       88853 :   statements.CopyTo(&statements_, zone);
     831       88853 : }
     832             : 
     833     9528949 : bool Literal::IsPropertyName() const {
     834     9528949 :   if (type() != kString) return false;
     835             :   uint32_t index;
     836     8539640 :   return !string_->AsArrayIndex(&index);
     837             : }
     838             : 
     839     4254580 : bool Literal::ToUint32(uint32_t* value) const {
     840     4254580 :   switch (type()) {
     841             :     case kString:
     842     2687900 :       return string_->AsArrayIndex(value);
     843             :     case kSmi:
     844     1566633 :       if (smi_ < 0) return false;
     845     1566633 :       *value = static_cast<uint32_t>(smi_);
     846     1566633 :       return true;
     847             :     case kHeapNumber:
     848         130 :       return DoubleToUint32IfEqualToSelf(AsNumber(), value);
     849             :     default:
     850             :       return false;
     851             :   }
     852             : }
     853             : 
     854      266669 : bool Literal::AsArrayIndex(uint32_t* value) const {
     855     4254608 :   return ToUint32(value) && *value != kMaxUInt32;
     856             : }
     857             : 
     858     8671275 : Handle<Object> Literal::BuildValue(Isolate* isolate) const {
     859     8671275 :   switch (type()) {
     860             :     case kSmi:
     861    13257068 :       return handle(Smi::FromInt(smi_), isolate);
     862             :     case kHeapNumber:
     863      408016 :       return isolate->factory()->NewNumber(number_, TENURED);
     864             :     case kString:
     865      520278 :       return string_->string();
     866             :     case kSymbol:
     867           0 :       return isolate->factory()->home_object_symbol();
     868             :     case kBoolean:
     869       39796 :       return isolate->factory()->ToBoolean(boolean_);
     870             :     case kNull:
     871        2351 :       return isolate->factory()->null_value();
     872             :     case kUndefined:
     873         261 :       return isolate->factory()->undefined_value();
     874             :     case kTheHole:
     875     1069551 :       return isolate->factory()->the_hole_value();
     876             :     case kBigInt:
     877             :       // This should never fail: the parser will never create a BigInt
     878             :       // literal that cannot be allocated.
     879        4976 :       return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
     880             :   }
     881           0 :   UNREACHABLE();
     882             : }
     883             : 
     884      379695 : bool Literal::ToBooleanIsTrue() const {
     885      379695 :   switch (type()) {
     886             :     case kSmi:
     887       48489 :       return smi_ != 0;
     888             :     case kHeapNumber:
     889         172 :       return DoubleToBoolean(number_);
     890             :     case kString:
     891         876 :       return !string_->IsEmpty();
     892             :     case kNull:
     893             :     case kUndefined:
     894             :       return false;
     895             :     case kBoolean:
     896      330532 :       return boolean_;
     897             :     case kBigInt: {
     898             :       const char* bigint_str = bigint_.c_str();
     899          14 :       size_t length = strlen(bigint_str);
     900             :       DCHECK_GT(length, 0);
     901          14 :       if (length == 1 && bigint_str[0] == '0') return false;
     902             :       // Skip over any radix prefix; BigInts with length > 1 only
     903             :       // begin with zero if they include a radix.
     904          47 :       for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
     905          41 :         if (bigint_str[i] != '0') return true;
     906             :       }
     907             :       return false;
     908             :     }
     909             :     case kSymbol:
     910           0 :       return true;
     911             :     case kTheHole:
     912           0 :       UNREACHABLE();
     913             :   }
     914           0 :   UNREACHABLE();
     915             : }
     916             : 
     917     4524411 : uint32_t Literal::Hash() {
     918     1538482 :   return IsString() ? AsRawString()->Hash()
     919     7419306 :                     : ComputeLongHash(double_to_uint64(AsNumber()));
     920             : }
     921             : 
     922             : 
     923             : // static
     924       76461 : bool Literal::Match(void* a, void* b) {
     925       75214 :   Literal* x = static_cast<Literal*>(a);
     926       75214 :   Literal* y = static_cast<Literal*>(b);
     927      150424 :   return (x->IsString() && y->IsString() &&
     928       77743 :           x->AsRawString() == y->AsRawString()) ||
     929        1282 :          (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
     930             : }
     931             : 
     932     6563571 : Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
     933             :   int int_value;
     934     3677317 :   if (DoubleToSmiInteger(number, &int_value)) {
     935     2886210 :     return NewSmiLiteral(int_value, pos);
     936             :   }
     937     1582120 :   return new (zone_) Literal(number, pos);
     938             : }
     939             : 
     940           0 : const char* CallRuntime::debug_name() {
     941             : #ifdef DEBUG
     942             :   return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
     943             :                         : function_->name;
     944             : #else
     945           0 :   return is_jsruntime() ? "(context function)" : function_->name;
     946             : #endif  // DEBUG
     947             : }
     948             : 
     949             : #define RETURN_LABELS(NodeType) \
     950             :   case k##NodeType:             \
     951             :     return static_cast<const NodeType*>(this)->labels();
     952             : 
     953       24591 : ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
     954       48716 :   switch (node_type()) {
     955       21057 :     BREAKABLE_NODE_LIST(RETURN_LABELS)
     956         255 :     ITERATION_NODE_LIST(RETURN_LABELS)
     957             :     default:
     958           0 :       UNREACHABLE();
     959             :   }
     960             : }
     961             : 
     962             : #undef RETURN_LABELS
     963             : 
     964             : }  // namespace internal
     965      178779 : }  // namespace v8

Generated by: LCOV version 1.10