LCOV - code coverage report
Current view: top level - src/ast - ast.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 387 404 95.8 %
Date: 2019-01-20 Functions: 72 77 93.5 %

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

Generated by: LCOV version 1.10