LCOV - code coverage report
Current view: top level - src/ast - ast.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 369 387 95.3 %
Date: 2019-04-17 Functions: 68 73 93.2 %

          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       34478 : IterationStatement* AstNode::AsIterationStatement() {
      67       34478 :   switch (node_type()) {
      68         345 :     ITERATION_NODE_LIST(RETURN_NODE);
      69             :     default:
      70             :       return nullptr;
      71             :   }
      72             : }
      73             : 
      74           0 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
      75    20935343 :   switch (node_type()) {
      76       63973 :     LITERAL_NODE_LIST(RETURN_NODE);
      77             :     default:
      78             :       return nullptr;
      79             :   }
      80             : }
      81             : 
      82             : #undef RETURN_NODE
      83             : 
      84      426545 : bool Expression::IsSmiLiteral() const {
      85     1252652 :   return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
      86             : }
      87             : 
      88     2829122 : bool Expression::IsNumberLiteral() const {
      89     4662171 :   return IsLiteral() && AsLiteral()->IsNumber();
      90             : }
      91             : 
      92      255142 : bool Expression::IsStringLiteral() const {
      93      746925 :   return IsLiteral() && AsLiteral()->type() == Literal::kString;
      94             : }
      95             : 
      96     9397728 : bool Expression::IsPropertyName() const {
      97    16920779 :   return IsLiteral() && AsLiteral()->IsPropertyName();
      98             : }
      99             : 
     100        8947 : bool Expression::IsNullLiteral() const {
     101     1877950 :   return IsLiteral() && AsLiteral()->type() == Literal::kNull;
     102             : }
     103             : 
     104        5170 : bool Expression::IsTheHoleLiteral() const {
     105        5963 :   return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
     106             : }
     107             : 
     108    15292826 : bool Expression::IsCompileTimeValue() {
     109    15292826 :   if (IsLiteral()) return true;
     110             :   MaterializedLiteral* literal = AsMaterializedLiteral();
     111     1380352 :   if (literal == nullptr) return false;
     112      224934 :   return literal->IsSimple();
     113             : }
     114             : 
     115     1589933 : bool Expression::IsUndefinedLiteral() const {
     116     1995032 :   if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
     117             : 
     118     1580671 :   const VariableProxy* var_proxy = AsVariableProxy();
     119     1580671 :   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     1600173 :   return var != nullptr && var->IsUnallocated() &&
     124      207534 :          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
     125             : }
     126             : 
     127      966556 : bool Expression::ToBooleanIsTrue() const {
     128      989390 :   return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
     129             : }
     130             : 
     131      951296 : bool Expression::ToBooleanIsFalse() const {
     132      983504 :   return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
     133             : }
     134             : 
     135           0 : bool Expression::IsValidReferenceExpression() const {
     136           0 :   return IsProperty() ||
     137           0 :          (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
     138             : }
     139             : 
     140    11983321 : bool Expression::IsAnonymousFunctionDefinition() const {
     141     1651266 :   return (IsFunctionLiteral() &&
     142    23616666 :           AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
     143        3867 :          (IsClassLiteral() &&
     144    11987188 :           AsClassLiteral()->IsAnonymousFunctionDefinition());
     145             : }
     146             : 
     147    11601267 : bool Expression::IsConciseMethodDefinition() const {
     148    12932012 :   return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
     149             : }
     150             : 
     151    11231189 : bool Expression::IsAccessorFunctionDefinition() const {
     152    12177846 :   return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
     153             : }
     154             : 
     155     2930625 : VariableProxy::VariableProxy(Variable* var, int start_position)
     156             :     : Expression(start_position, kVariableProxy),
     157             :       raw_name_(var->raw_name()),
     158     2930625 :       next_unresolved_(nullptr) {
     159             :   DCHECK(!var->is_this());
     160             :   bit_field_ |= IsAssignedField::encode(false) |
     161             :                 IsResolvedField::encode(false) |
     162     2930625 :                 HoleCheckModeField::encode(HoleCheckMode::kElided);
     163             :   BindTo(var);
     164     2930625 : }
     165             : 
     166     6655837 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
     167             :     : Expression(copy_from->position(), kVariableProxy),
     168     6655837 :       next_unresolved_(nullptr) {
     169     6655837 :   bit_field_ = copy_from->bit_field_;
     170             :   DCHECK(!copy_from->is_resolved());
     171     6655837 :   raw_name_ = copy_from->raw_name_;
     172     6655837 : }
     173             : 
     174    39781550 : 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    42712175 :   if (is_assigned()) var->set_maybe_assigned();
     180    39781550 : }
     181             : 
     182    14333264 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
     183             :                        Expression* value, int pos)
     184    14333264 :     : Expression(pos, node_type), target_(target), value_(value) {
     185    14333264 :   bit_field_ |= TokenField::encode(op);
     186    14333264 : }
     187             : 
     188      714954 : void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
     189             :   DCHECK(!inferred_name.is_null());
     190      714954 :   inferred_name_ = inferred_name;
     191             :   DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
     192      714954 :   raw_inferred_name_ = nullptr;
     193             :   scope()->set_has_inferred_function_name(true);
     194      714954 : }
     195             : 
     196      467956 : void FunctionLiteral::set_raw_inferred_name(
     197             :     const AstConsString* raw_inferred_name) {
     198             :   DCHECK_NOT_NULL(raw_inferred_name);
     199      467956 :   raw_inferred_name_ = raw_inferred_name;
     200             :   DCHECK(inferred_name_.is_null());
     201      467956 :   inferred_name_ = Handle<String>();
     202             :   scope()->set_has_inferred_function_name(true);
     203      467956 : }
     204             : 
     205     6591363 : bool FunctionLiteral::ShouldEagerCompile() const {
     206     6591363 :   return scope()->ShouldEagerCompile();
     207             : }
     208             : 
     209      726111 : void FunctionLiteral::SetShouldEagerCompile() {
     210      726111 :   scope()->set_should_eager_compile();
     211      726112 : }
     212             : 
     213     3636820 : bool FunctionLiteral::AllowsLazyCompilation() {
     214     3636820 :   return scope()->AllowsLazyCompilation();
     215             : }
     216             : 
     217     3618641 : bool FunctionLiteral::SafeToSkipArgumentsAdaptor() const {
     218             :   // TODO(bmeurer,verwaest): The --fast_calls_with_arguments_mismatches
     219             :   // is mostly here for checking the real-world impact of the calling
     220             :   // convention. There's not really a point in turning off this flag
     221             :   // otherwise, so we should remove it at some point, when we're done
     222             :   // with the experiments (https://crbug.com/v8/8895).
     223     3618650 :   return FLAG_fast_calls_with_arguments_mismatches &&
     224      683602 :          language_mode() == LanguageMode::kStrict &&
     225     4235591 :          scope()->arguments() == nullptr &&
     226     3618641 :          scope()->rest_parameter() == nullptr;
     227             : }
     228             : 
     229           0 : Handle<String> FunctionLiteral::name(Isolate* isolate) const {
     230           0 :   return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
     231             : }
     232             : 
     233    10941116 : int FunctionLiteral::start_position() const {
     234    10941116 :   return scope()->start_position();
     235             : }
     236             : 
     237             : 
     238     5175057 : int FunctionLiteral::end_position() const {
     239     5175057 :   return scope()->end_position();
     240             : }
     241             : 
     242             : 
     243     4981764 : LanguageMode FunctionLiteral::language_mode() const {
     244     4981764 :   return scope()->language_mode();
     245             : }
     246             : 
     247    10153419 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
     248             : 
     249      298208 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
     250      596416 :   if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
     251             :   DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
     252      310392 :   return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
     253             : }
     254             : 
     255          23 : std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
     256             :   const AstConsString* cons_string;
     257          23 :   if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
     258             :     cons_string = raw_name_;
     259           6 :   } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
     260             :     cons_string = raw_inferred_name_;
     261           6 :   } else if (!inferred_name_.is_null()) {
     262             :     AllowHandleDereference allow_deref;
     263           6 :     return inferred_name_->ToCString();
     264             :   } else {
     265           0 :     char* empty_str = new char[1];
     266           0 :     empty_str[0] = 0;
     267             :     return std::unique_ptr<char[]>(empty_str);
     268             :   }
     269             : 
     270             :   // TODO(rmcilroy): Deal with two-character strings.
     271             :   std::vector<char> result_vec;
     272          17 :   std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
     273          34 :   for (const AstRawString* string : strings) {
     274          17 :     if (!string->is_one_byte()) break;
     275         335 :     for (int i = 0; i < string->length(); i++) {
     276         318 :       result_vec.push_back(string->raw_data()[i]);
     277             :     }
     278             :   }
     279          17 :   std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
     280             :   memcpy(result.get(), result_vec.data(), result_vec.size());
     281          17 :   result[result_vec.size()] = '\0';
     282             :   return result;
     283             : }
     284             : 
     285      137835 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
     286             :                                              Kind kind, bool is_computed_name)
     287             :     : LiteralProperty(key, value, is_computed_name),
     288             :       kind_(kind),
     289      137835 :       emit_store_(true) {}
     290             : 
     291     2914917 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
     292             :                                              Expression* key, Expression* value,
     293             :                                              bool is_computed_name)
     294     2914917 :     : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
     295     7270254 :   if (!is_computed_name && key->AsLiteral()->IsString() &&
     296             :       key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
     297        6609 :     kind_ = PROTOTYPE;
     298     2908308 :   } else if (value_->AsMaterializedLiteral() != nullptr) {
     299       59957 :     kind_ = MATERIALIZED_LITERAL;
     300     2848351 :   } else if (value_->IsLiteral()) {
     301     1862621 :     kind_ = CONSTANT;
     302             :   } else {
     303      985730 :     kind_ = COMPUTED;
     304             :   }
     305     2914917 : }
     306             : 
     307     3429575 : bool LiteralProperty::NeedsSetFunctionName() const {
     308     3459052 :   return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
     309       22480 :                                 value_->IsConciseMethodDefinition() ||
     310     3429574 :                                 value_->IsAccessorFunctionDefinition());
     311             : }
     312             : 
     313      459706 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
     314             :                                            Kind kind, bool is_static,
     315             :                                            bool is_computed_name,
     316             :                                            bool is_private)
     317             :     : LiteralProperty(key, value, is_computed_name),
     318             :       kind_(kind),
     319             :       is_static_(is_static),
     320             :       is_private_(is_private),
     321      459706 :       private_or_computed_name_var_(nullptr) {}
     322             : 
     323     2021158 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
     324     2021158 :   return kind_ == CONSTANT ||
     325       44244 :          (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
     326             : }
     327             : 
     328             : 
     329           0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
     330        3370 :   emit_store_ = emit_store;
     331           0 : }
     332             : 
     333      250785 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
     334             : 
     335      593651 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
     336             :   const auto GETTER = ObjectLiteral::Property::GETTER;
     337             :   const auto SETTER = ObjectLiteral::Property::SETTER;
     338             : 
     339             :   ZoneAllocationPolicy allocator(zone);
     340             : 
     341             :   CustomMatcherZoneHashMap table(
     342             :       Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
     343     3618027 :   for (int i = properties()->length() - 1; i >= 0; i--) {
     344     3024361 :     ObjectLiteral::Property* property = properties()->at(i);
     345     3024361 :     if (property->is_computed_name()) continue;
     346     3003335 :     if (property->IsPrototype()) continue;
     347     2996729 :     Literal* literal = property->key()->AsLiteral();
     348             :     DCHECK(!literal->IsNullLiteral());
     349             : 
     350     2996729 :     uint32_t hash = literal->Hash();
     351     5993466 :     ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
     352     2996736 :     if (entry->value == nullptr) {
     353     2992638 :       entry->value = property;
     354             :     } else {
     355             :       // We already have a later definition of this property, so we don't need
     356             :       // to emit a store for the current one.
     357             :       //
     358             :       // There are two subtleties here.
     359             :       //
     360             :       // (1) Emitting a store might actually be incorrect. For example, in {get
     361             :       // foo() {}, foo: 42}, the getter store would override the data property
     362             :       // (which, being a non-computed compile-time valued property, is already
     363             :       // part of the initial literal object.
     364             :       //
     365             :       // (2) If the later definition is an accessor (say, a getter), and the
     366             :       // current definition is a complementary accessor (here, a setter), then
     367             :       // we still must emit a store for the current definition.
     368             : 
     369             :       auto later_kind =
     370             :           static_cast<ObjectLiteral::Property*>(entry->value)->kind();
     371             :       bool complementary_accessors =
     372        4098 :           (property->kind() == GETTER && later_kind == SETTER) ||
     373         215 :           (property->kind() == SETTER && later_kind == GETTER);
     374        4098 :       if (!complementary_accessors) {
     375             :         property->set_emit_store(false);
     376        3370 :         if (later_kind == GETTER || later_kind == SETTER) {
     377        1067 :           entry->value = property;
     378             :         }
     379             :       }
     380             :     }
     381             :   }
     382      593666 : }
     383             : 
     384        2160 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
     385             :   // We still check for __proto__:null after computed property names.
     386        8568 :   for (; i < properties()->length(); i++) {
     387        6418 :     if (properties()->at(i)->IsNullPrototype()) {
     388             :       set_has_null_protoype(true);
     389             :       break;
     390             :     }
     391             :   }
     392        2160 : }
     393             : 
     394      267441 : int ObjectLiteral::InitDepthAndFlags() {
     395      285349 :   if (is_initialized()) return depth();
     396             :   bool is_simple = true;
     397             :   bool has_seen_prototype = false;
     398             :   bool needs_initial_allocation_site = false;
     399             :   int depth_acc = 1;
     400             :   uint32_t nof_properties = 0;
     401             :   uint32_t elements = 0;
     402             :   uint32_t max_element_index = 0;
     403     4355541 :   for (int i = 0; i < properties()->length(); i++) {
     404     2055172 :     ObjectLiteral::Property* property = properties()->at(i);
     405     2055172 :     if (property->IsPrototype()) {
     406             :       has_seen_prototype = true;
     407             :       // __proto__:null has no side-effects and is set directly on the
     408             :       // boilerplate.
     409        4113 :       if (property->IsNullPrototype()) {
     410             :         set_has_null_protoype(true);
     411        4113 :         continue;
     412             :       }
     413             :       DCHECK(!has_null_prototype());
     414             :       is_simple = false;
     415             :       continue;
     416             :     }
     417     2051059 :     if (nof_properties == boilerplate_properties_) {
     418             :       DCHECK(property->is_computed_name());
     419             :       is_simple = false;
     420        2193 :       if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
     421        2193 :       break;
     422             :     }
     423             :     DCHECK(!property->is_computed_name());
     424             : 
     425             :     MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
     426     2048866 :     if (literal != nullptr) {
     427       45792 :       int subliteral_depth = literal->InitDepthAndFlags() + 1;
     428       45792 :       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
     429       45792 :       needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
     430             :     }
     431             : 
     432     2048866 :     Literal* key = property->key()->AsLiteral();
     433             :     Expression* value = property->value();
     434             : 
     435     2048866 :     bool is_compile_time_value = value->IsCompileTimeValue();
     436     2048881 :     is_simple = is_simple && is_compile_time_value;
     437             : 
     438             :     // Keep track of the number of elements in the object literal and
     439             :     // the largest element index.  If the largest element index is
     440             :     // much larger than the number of elements, creating an object
     441             :     // literal with fast elements will be a waste of space.
     442     2048881 :     uint32_t element_index = 0;
     443     2048891 :     if (key->AsArrayIndex(&element_index)) {
     444      784610 :       max_element_index = Max(element_index, max_element_index);
     445      784610 :       elements++;
     446             :     } else {
     447             :       DCHECK(key->IsPropertyName());
     448             :     }
     449             : 
     450     2048891 :     nof_properties++;
     451             :   }
     452             : 
     453             :   set_depth(depth_acc);
     454             :   set_is_simple(is_simple);
     455             :   set_needs_initial_allocation_site(needs_initial_allocation_site);
     456      249558 :   set_has_elements(elements > 0);
     457      250095 :   set_fast_elements((max_element_index <= 32) ||
     458         537 :                     ((2 * elements) >= max_element_index));
     459      249558 :   return depth_acc;
     460             : }
     461             : 
     462      207874 : void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
     463      207874 :   if (!boilerplate_description_.is_null()) return;
     464             : 
     465             :   int index_keys = 0;
     466             :   bool has_seen_proto = false;
     467     4145201 :   for (int i = 0; i < properties()->length(); i++) {
     468     1969719 :     ObjectLiteral::Property* property = properties()->at(i);
     469     1969719 :     if (property->IsPrototype()) {
     470             :       has_seen_proto = true;
     471             :       continue;
     472             :     }
     473     1966425 :     if (property->is_computed_name()) continue;
     474             : 
     475     1965871 :     Literal* key = property->key()->AsLiteral();
     476     1965871 :     if (!key->IsPropertyName()) index_keys++;
     477             :   }
     478             : 
     479             :   Handle<ObjectBoilerplateDescription> boilerplate_description =
     480             :       isolate->factory()->NewObjectBoilerplateDescription(
     481      205763 :           boilerplate_properties_, properties()->length(), index_keys,
     482      411526 :           has_seen_proto);
     483             : 
     484             :   int position = 0;
     485     4143481 :   for (int i = 0; i < properties()->length(); i++) {
     486     1969286 :     ObjectLiteral::Property* property = properties()->at(i);
     487     1972576 :     if (property->IsPrototype()) continue;
     488             : 
     489     1965996 :     if (static_cast<uint32_t>(position) == boilerplate_properties_) {
     490             :       DCHECK(property->is_computed_name());
     491         429 :       break;
     492             :     }
     493             :     DCHECK(!property->is_computed_name());
     494             : 
     495             :     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
     496     1965567 :     if (m_literal != nullptr) {
     497       44460 :       m_literal->BuildConstants(isolate);
     498             :     }
     499             : 
     500             :     // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
     501             :     // value for COMPUTED properties, the real value is filled in at
     502             :     // runtime. The enumeration order is maintained.
     503     1965567 :     Literal* key_literal = property->key()->AsLiteral();
     504     1965567 :     uint32_t element_index = 0;
     505             :     Handle<Object> key =
     506             :         key_literal->AsArrayIndex(&element_index)
     507      782870 :             ? isolate->factory()->NewNumberFromUint(element_index)
     508     2748437 :             : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
     509             : 
     510     1965567 :     Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
     511             : 
     512             :     // Add name, value pair to the fixed array.
     513     3931134 :     boilerplate_description->set_key_value(position++, *key, *value);
     514             :   }
     515             : 
     516             :   boilerplate_description->set_flags(EncodeLiteralType());
     517             : 
     518      205766 :   boilerplate_description_ = boilerplate_description;
     519             : }
     520             : 
     521      203292 : bool ObjectLiteral::IsFastCloningSupported() const {
     522             :   // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
     523             :   // literals don't support copy-on-write (COW) elements for now.
     524             :   // TODO(mvstanton): make object literals support COW elements.
     525      590882 :   return fast_elements() && is_shallow() &&
     526             :          properties_count() <=
     527      203292 :              ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
     528             : }
     529             : 
     530      415285 : int ArrayLiteral::InitDepthAndFlags() {
     531      420153 :   if (is_initialized()) return depth();
     532             : 
     533             :   int constants_length =
     534      410417 :       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
     535             : 
     536             :   // Fill in the literals.
     537      410417 :   bool is_simple = first_spread_index_ < 0;
     538             :   int depth_acc = 1;
     539             :   int array_index = 0;
     540    13155451 :   for (; array_index < constants_length; array_index++) {
     541     6372515 :     Expression* element = values()->at(array_index);
     542             :     MaterializedLiteral* literal = element->AsMaterializedLiteral();
     543     6372515 :     if (literal != nullptr) {
     544       31937 :       int subliteral_depth = literal->InitDepthAndFlags() + 1;
     545       31935 :       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
     546             :     }
     547             : 
     548     6372513 :     if (!element->IsCompileTimeValue()) {
     549             :       is_simple = false;
     550             :     }
     551             :   }
     552             : 
     553             :   set_depth(depth_acc);
     554             :   set_is_simple(is_simple);
     555             :   // Array literals always need an initial allocation site to properly track
     556             :   // elements transitions.
     557             :   set_needs_initial_allocation_site(true);
     558      410419 :   return depth_acc;
     559             : }
     560             : 
     561      180150 : void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
     562      180150 :   if (!boilerplate_description_.is_null()) return;
     563             : 
     564             :   int constants_length =
     565      180150 :       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
     566             :   ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
     567             :   Handle<FixedArray> fixed_array =
     568      180150 :       isolate->factory()->NewFixedArrayWithHoles(constants_length);
     569             : 
     570             :   // Fill in the literals.
     571             :   bool is_holey = false;
     572             :   int array_index = 0;
     573    12699634 :   for (; array_index < constants_length; array_index++) {
     574     6259735 :     Expression* element = values()->at(array_index);
     575             :     DCHECK(!element->IsSpread());
     576             :     MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
     577     6259735 :     if (m_literal != nullptr) {
     578       29123 :       m_literal->BuildConstants(isolate);
     579             :     }
     580             : 
     581             :     // New handle scope here, needs to be after BuildContants().
     582             :     HandleScope scope(isolate);
     583     6259735 :     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
     584     6259736 :     if (boilerplate_value->IsTheHole(isolate)) {
     585             :       is_holey = true;
     586             :       continue;
     587             :     }
     588             : 
     589     5190167 :     if (boilerplate_value->IsUninitialized(isolate)) {
     590             :       boilerplate_value = handle(Smi::kZero, isolate);
     591             :     }
     592             : 
     593             :     kind = GetMoreGeneralElementsKind(kind,
     594    10380335 :                                       boilerplate_value->OptimalElementsKind());
     595     5190167 :     fixed_array->set(array_index, *boilerplate_value);
     596             :   }
     597             : 
     598      180152 :   if (is_holey) kind = GetHoleyElementsKind(kind);
     599             : 
     600             :   // Simple and shallow arrays can be lazily copied, we transform the
     601             :   // elements array to a copy-on-write array.
     602      254320 :   if (is_simple() && depth() == 1 && array_index > 0 &&
     603             :       IsSmiOrObjectElementsKind(kind)) {
     604       53952 :     fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
     605             :   }
     606             : 
     607             :   Handle<FixedArrayBase> elements = fixed_array;
     608      180153 :   if (IsDoubleElementsKind(kind)) {
     609             :     ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
     610        3348 :     elements = isolate->factory()->NewFixedDoubleArray(constants_length);
     611             :     // We are copying from non-fast-double to fast-double.
     612             :     ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
     613        3348 :     accessor->CopyElements(isolate, fixed_array, from_kind, elements,
     614        6696 :                            constants_length);
     615             :   }
     616             : 
     617             :   boilerplate_description_ =
     618      180153 :       isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
     619             : }
     620             : 
     621      382100 : bool ArrayLiteral::IsFastCloningSupported() const {
     622      757065 :   return depth() <= 1 &&
     623             :          values_.length() <=
     624      382100 :              ConstructorBuiltins::kMaximumClonedShallowArrayElements;
     625             : }
     626             : 
     627      224934 : bool MaterializedLiteral::IsSimple() const {
     628      313045 :   if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
     629      241599 :   if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
     630             :   DCHECK(IsRegExpLiteral());
     631             :   return false;
     632             : }
     633             : 
     634     8225305 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
     635             :                                                         Isolate* isolate) {
     636     8225305 :   if (expression->IsLiteral()) {
     637    15446250 :     return expression->AsLiteral()->BuildValue(isolate);
     638             :   }
     639      502180 :   if (expression->IsCompileTimeValue()) {
     640       41390 :     if (expression->IsObjectLiteral()) {
     641       17048 :       ObjectLiteral* object_literal = expression->AsObjectLiteral();
     642             :       DCHECK(object_literal->is_simple());
     643       17048 :       return object_literal->boilerplate_description();
     644             :     } else {
     645             :       DCHECK(expression->IsArrayLiteral());
     646       24342 :       ArrayLiteral* array_literal = expression->AsArrayLiteral();
     647             :       DCHECK(array_literal->is_simple());
     648       24342 :       return array_literal->boilerplate_description();
     649             :     }
     650             :   }
     651      460791 :   return isolate->factory()->uninitialized_value();
     652             : }
     653             : 
     654       77727 : int MaterializedLiteral::InitDepthAndFlags() {
     655      108843 :   if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
     656       82529 :   if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
     657             :   DCHECK(IsRegExpLiteral());
     658             :   return 1;
     659             : }
     660             : 
     661       45792 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
     662       45792 :   if (IsArrayLiteral()) {
     663       35118 :     return AsArrayLiteral()->needs_initial_allocation_site();
     664             :   }
     665       28233 :   if (IsObjectLiteral()) {
     666       35676 :     return AsObjectLiteral()->needs_initial_allocation_site();
     667             :   }
     668             :   DCHECK(IsRegExpLiteral());
     669             :   return false;
     670             : }
     671             : 
     672       73583 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
     673       73583 :   if (IsArrayLiteral()) {
     674       57442 :     AsArrayLiteral()->BuildBoilerplateDescription(isolate);
     675       28721 :     return;
     676             :   }
     677       44862 :   if (IsObjectLiteral()) {
     678       68402 :     AsObjectLiteral()->BuildBoilerplateDescription(isolate);
     679       34202 :     return;
     680             :   }
     681             :   DCHECK(IsRegExpLiteral());
     682             : }
     683             : 
     684        1731 : Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
     685             :     Isolate* isolate) {
     686             :   Handle<FixedArray> raw_strings = isolate->factory()->NewFixedArray(
     687        1731 :       this->raw_strings()->length(), AllocationType::kOld);
     688             :   bool raw_and_cooked_match = true;
     689        7479 :   for (int i = 0; i < raw_strings->length(); ++i) {
     690        4712 :     if (this->cooked_strings()->at(i) == nullptr ||
     691        1838 :         *this->raw_strings()->at(i)->string() !=
     692             :             *this->cooked_strings()->at(i)->string()) {
     693             :       raw_and_cooked_match = false;
     694             :     }
     695        5748 :     raw_strings->set(i, *this->raw_strings()->at(i)->string());
     696             :   }
     697             :   Handle<FixedArray> cooked_strings = raw_strings;
     698        1731 :   if (!raw_and_cooked_match) {
     699             :     cooked_strings = isolate->factory()->NewFixedArray(
     700        1176 :         this->cooked_strings()->length(), AllocationType::kOld);
     701        5232 :     for (int i = 0; i < cooked_strings->length(); ++i) {
     702        2028 :       if (this->cooked_strings()->at(i) != nullptr) {
     703         992 :         cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
     704             :       } else {
     705        1036 :         cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
     706             :       }
     707             :     }
     708             :   }
     709             :   return isolate->factory()->NewTemplateObjectDescription(raw_strings,
     710        1731 :                                                           cooked_strings);
     711             : }
     712             : 
     713             : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
     714             :   // Add is not commutative due to potential for string addition.
     715      274875 :   return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
     716             :          op == Token::BIT_XOR;
     717             : }
     718             : 
     719             : // Check for the pattern: x + 1.
     720             : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
     721             :                                      Expression** expr, Smi* literal) {
     722      441254 :   if (right->IsSmiLiteral()) {
     723      127549 :     *expr = left;
     724      255098 :     *literal = right->AsLiteral()->AsSmiLiteral();
     725             :     return true;
     726             :   }
     727             :   return false;
     728             : }
     729             : 
     730      374772 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
     731             :                                             Smi* literal) {
     732     1024419 :   return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
     733       66482 :          (IsCommutativeOperationWithSmiLiteral(op()) &&
     734      441254 :           MatchSmiLiteralOperation(right_, left_, subexpr, literal));
     735             : }
     736             : 
     737             : static bool IsTypeof(Expression* expr) {
     738     1687380 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     739     1835481 :   return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
     740             : }
     741             : 
     742             : // Check for the pattern: typeof <expression> equals <string literal>.
     743     1687380 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
     744             :                                       Expression* right, Expression** expr,
     745             :                                       Literal** literal) {
     746     1931536 :   if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
     747      100065 :     *expr = left->AsUnaryOperation()->expression();
     748      200130 :     *literal = right->AsLiteral();
     749      100065 :     return true;
     750             :   }
     751             :   return false;
     752             : }
     753             : 
     754      893694 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
     755             :                                               Literal** literal) {
     756     2581090 :   return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
     757     2481100 :          MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
     758             : }
     759             : 
     760             : 
     761             : static bool IsVoidOfLiteral(Expression* expr) {
     762     1586285 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     763     1636059 :   return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
     764             :          maybe_unary->expression()->IsLiteral();
     765             : }
     766             : 
     767             : 
     768             : // Check for the pattern: void <literal> equals <expression> or
     769             : // undefined equals <expression>
     770     1586285 : static bool MatchLiteralCompareUndefined(Expression* left,
     771             :                                          Token::Value op,
     772             :                                          Expression* right,
     773             :                                          Expression** expr) {
     774     1588212 :   if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
     775        1129 :     *expr = right;
     776        1129 :     return true;
     777             :   }
     778     1645323 :   if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
     779       60120 :     *expr = right;
     780       60120 :     return true;
     781             :   }
     782             :   return false;
     783             : }
     784             : 
     785      793632 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
     786     2379919 :   return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
     787     2378944 :          MatchLiteralCompareUndefined(right_, op(), left_, expr);
     788             : }
     789             : 
     790             : // Check for the pattern: null equals <expression>
     791             : static bool MatchLiteralCompareNull(Expression* left,
     792             :                                     Token::Value op,
     793             :                                     Expression* right,
     794             :                                     Expression** expr) {
     795     1470113 :   if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
     796        5223 :     *expr = right;
     797             :     return true;
     798             :   }
     799             :   return false;
     800             : }
     801             : 
     802      732383 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
     803     2928829 :   return MatchLiteralCompareNull(left_, op(), right_, expr) ||
     804     2195743 :          MatchLiteralCompareNull(right_, op(), left_, expr);
     805             : }
     806             : 
     807     5178642 : Call::CallType Call::GetCallType() const {
     808     5178642 :   VariableProxy* proxy = expression()->AsVariableProxy();
     809     5178642 :   if (proxy != nullptr) {
     810     4239670 :     if (proxy->var()->IsUnallocated()) {
     811             :       return GLOBAL_CALL;
     812      430756 :     } else if (proxy->var()->IsLookupSlot()) {
     813             :       // Calls going through 'with' always use VariableMode::kDynamic rather
     814             :       // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
     815             :       return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
     816      178126 :                                                             : OTHER_CALL;
     817             :     }
     818             :   }
     819             : 
     820     1191602 :   if (expression()->IsSuperCallReference()) return SUPER_CALL;
     821             : 
     822             :   Property* property = expression()->AsProperty();
     823     1187478 :   if (property != nullptr) {
     824             :     bool is_super = property->IsSuperAccess();
     825      826001 :     if (property->key()->IsPropertyName()) {
     826      821355 :       return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
     827             :     } else {
     828        4645 :       return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
     829             :     }
     830             :   }
     831             : 
     832      361477 :   if (expression()->IsResolvedProperty()) {
     833             :     return RESOLVED_PROPERTY_CALL;
     834             :   }
     835             : 
     836      361476 :   return OTHER_CALL;
     837             : }
     838             : 
     839       92045 : CaseClause::CaseClause(Zone* zone, Expression* label,
     840             :                        const ScopedPtrList<Statement>& statements)
     841       92045 :     : label_(label), statements_(0, nullptr) {
     842       92045 :   statements.CopyTo(&statements_, zone);
     843       92045 : }
     844             : 
     845      282631 : bool Literal::IsPropertyName() const {
     846     9771558 :   if (type() != kString) return false;
     847             :   uint32_t index;
     848     8797079 :   return !string_->AsArrayIndex(&index);
     849             : }
     850             : 
     851     4296447 : bool Literal::ToUint32(uint32_t* value) const {
     852     4296447 :   switch (type()) {
     853             :     case kString:
     854     2729618 :       return string_->AsArrayIndex(value);
     855             :     case kSmi:
     856     1566773 :       if (smi_ < 0) return false;
     857     1566774 :       *value = static_cast<uint32_t>(smi_);
     858     1566774 :       return true;
     859             :     case kHeapNumber:
     860         130 :       return DoubleToUint32IfEqualToSelf(AsNumber(), value);
     861             :     default:
     862             :       return false;
     863             :   }
     864             : }
     865             : 
     866      282019 : bool Literal::AsArrayIndex(uint32_t* value) const {
     867     4296467 :   return ToUint32(value) && *value != kMaxUInt32;
     868             : }
     869             : 
     870     7801467 : Handle<Object> Literal::BuildValue(Isolate* isolate) const {
     871     7801467 :   switch (type()) {
     872             :     case kSmi:
     873    11508408 :       return handle(Smi::FromInt(smi_), isolate);
     874             :     case kHeapNumber:
     875      408160 :       return isolate->factory()->NewNumber(number_, AllocationType::kOld);
     876             :     case kString:
     877     1048648 :       return string_->string();
     878             :     case kSymbol:
     879           0 :       return isolate->factory()->home_object_symbol();
     880             :     case kBoolean:
     881       40065 :       return isolate->factory()->ToBoolean(boolean_);
     882             :     case kNull:
     883        2387 :       return isolate->factory()->null_value();
     884             :     case kUndefined:
     885         261 :       return isolate->factory()->undefined_value();
     886             :     case kTheHole:
     887     1069578 :       return isolate->factory()->the_hole_value();
     888             :     case kBigInt:
     889             :       // This should never fail: the parser will never create a BigInt
     890             :       // literal that cannot be allocated.
     891        4976 :       return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
     892             :   }
     893           0 :   UNREACHABLE();
     894             : }
     895             : 
     896      381678 : bool Literal::ToBooleanIsTrue() const {
     897      381678 :   switch (type()) {
     898             :     case kSmi:
     899       48519 :       return smi_ != 0;
     900             :     case kHeapNumber:
     901         172 :       return DoubleToBoolean(number_);
     902             :     case kString:
     903         878 :       return !string_->IsEmpty();
     904             :     case kNull:
     905             :     case kUndefined:
     906             :       return false;
     907             :     case kBoolean:
     908      332484 :       return boolean_;
     909             :     case kBigInt: {
     910             :       const char* bigint_str = bigint_.c_str();
     911          14 :       size_t length = strlen(bigint_str);
     912             :       DCHECK_GT(length, 0);
     913          14 :       if (length == 1 && bigint_str[0] == '0') return false;
     914             :       // Skip over any radix prefix; BigInts with length > 1 only
     915             :       // begin with zero if they include a radix.
     916          47 :       for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
     917          41 :         if (bigint_str[i] != '0') return true;
     918             :       }
     919             :       return false;
     920             :     }
     921             :     case kSymbol:
     922           0 :       return true;
     923             :     case kTheHole:
     924           0 :       UNREACHABLE();
     925             :   }
     926           0 :   UNREACHABLE();
     927             : }
     928             : 
     929     3002500 : uint32_t Literal::Hash() {
     930             :   return IsString() ? AsRawString()->Hash()
     931     7452528 :                     : ComputeLongHash(double_to_uint64(AsNumber()));
     932             : }
     933             : 
     934             : 
     935             : // static
     936       77831 : bool Literal::Match(void* a, void* b) {
     937             :   Literal* x = static_cast<Literal*>(a);
     938             :   Literal* y = static_cast<Literal*>(b);
     939       76549 :   return (x->IsString() && y->IsString() &&
     940       79113 :           x->AsRawString() == y->AsRawString()) ||
     941        1282 :          (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
     942             : }
     943             : 
     944     3745559 : Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
     945             :   int int_value;
     946     3745559 :   if (DoubleToSmiInteger(number, &int_value)) {
     947     2953701 :     return NewSmiLiteral(int_value, pos);
     948             :   }
     949     1583716 :   return new (zone_) Literal(number, pos);
     950             : }
     951             : 
     952           0 : const char* CallRuntime::debug_name() {
     953             : #ifdef DEBUG
     954             :   return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
     955             :                         : function_->name;
     956             : #else
     957           0 :   return is_jsruntime() ? "(context function)" : function_->name;
     958             : #endif  // DEBUG
     959             : }
     960             : 
     961             : #define RETURN_LABELS(NodeType) \
     962             :   case k##NodeType:             \
     963             :     return static_cast<const NodeType*>(this)->labels();
     964             : 
     965       24387 : ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
     966       24387 :   switch (node_type()) {
     967       20850 :     BREAKABLE_NODE_LIST(RETURN_LABELS)
     968         255 :     ITERATION_NODE_LIST(RETURN_LABELS)
     969             :     default:
     970           0 :       UNREACHABLE();
     971             :   }
     972             : }
     973             : 
     974             : #undef RETURN_LABELS
     975             : 
     976             : }  // namespace internal
     977      121996 : }  // namespace v8

Generated by: LCOV version 1.10