LCOV - code coverage report
Current view: top level - src/ast - ast.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 331 342 96.8 %
Date: 2017-10-20 Functions: 65 68 95.6 %

          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             : 
       9             : #include "src/ast/compile-time-value.h"
      10             : #include "src/ast/prettyprinter.h"
      11             : #include "src/ast/scopes.h"
      12             : #include "src/base/hashmap.h"
      13             : #include "src/builtins/builtins-constructor.h"
      14             : #include "src/builtins/builtins.h"
      15             : #include "src/code-stubs.h"
      16             : #include "src/contexts.h"
      17             : #include "src/conversions.h"
      18             : #include "src/double.h"
      19             : #include "src/elements.h"
      20             : #include "src/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      129654 : IterationStatement* AstNode::AsIterationStatement() {
      66      129654 :   switch (node_type()) {
      67         304 :     ITERATION_NODE_LIST(RETURN_NODE);
      68             :     default:
      69             :       return nullptr;
      70             :   }
      71             : }
      72             : 
      73           0 : BreakableStatement* AstNode::AsBreakableStatement() {
      74           0 :   switch (node_type()) {
      75           0 :     BREAKABLE_NODE_LIST(RETURN_NODE);
      76           0 :     ITERATION_NODE_LIST(RETURN_NODE);
      77             :     default:
      78             :       return nullptr;
      79             :   }
      80             : }
      81             : 
      82    26334653 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
      83    26334653 :   switch (node_type()) {
      84       26808 :     LITERAL_NODE_LIST(RETURN_NODE);
      85             :     default:
      86             :       return nullptr;
      87             :   }
      88             : }
      89             : 
      90             : #undef RETURN_NODE
      91             : 
      92      944797 : bool Expression::IsSmiLiteral() const {
      93     2308869 :   return IsLiteral() && AsLiteral()->raw_value()->IsSmi();
      94             : }
      95             : 
      96          75 : bool Expression::IsNumberLiteral() const {
      97         300 :   return IsLiteral() && AsLiteral()->raw_value()->IsNumber();
      98             : }
      99             : 
     100      913513 : bool Expression::IsStringLiteral() const {
     101     2694990 :   return IsLiteral() && AsLiteral()->raw_value()->IsString();
     102             : }
     103             : 
     104    11821275 : bool Expression::IsPropertyName() const {
     105    41586892 :   return IsLiteral() && AsLiteral()->IsPropertyName();
     106             : }
     107             : 
     108     1930910 : bool Expression::IsNullLiteral() const {
     109     3861820 :   if (!IsLiteral()) return false;
     110     1344180 :   return AsLiteral()->raw_value()->IsNull();
     111             : }
     112             : 
     113     1997598 : bool Expression::IsUndefinedLiteral() const {
     114     2639796 :   if (IsLiteral() && AsLiteral()->raw_value()->IsUndefined()) return true;
     115             : 
     116     2847022 :   const VariableProxy* var_proxy = AsVariableProxy();
     117     1979140 :   if (var_proxy == nullptr) return false;
     118             :   Variable* var = var_proxy->var();
     119             :   // The global identifier "undefined" is immutable. Everything
     120             :   // else could be reassigned.
     121     1857479 :   return var != nullptr && var->IsUnallocated() &&
     122      989597 :          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
     123             : }
     124             : 
     125     1483185 : bool Expression::ToBooleanIsTrue() const {
     126     2991588 :   return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
     127             : }
     128             : 
     129     1488327 : bool Expression::ToBooleanIsFalse() const {
     130     3011364 :   return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
     131             : }
     132             : 
     133     6535873 : bool Expression::IsValidReferenceExpression() const {
     134             :   // We don't want expressions wrapped inside RewritableExpression to be
     135             :   // considered as valid reference expressions, as they will be rewritten
     136             :   // to something (most probably involving a do expression).
     137     6535873 :   if (IsRewritableExpression()) return false;
     138     9148339 :   return IsProperty() ||
     139     5214118 :          (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
     140             : }
     141             : 
     142    12919092 : bool Expression::IsAnonymousFunctionDefinition() const {
     143     1550765 :   return (IsFunctionLiteral() &&
     144    25391003 :           AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
     145        3588 :          (IsClassLiteral() &&
     146    12922680 :           AsClassLiteral()->IsAnonymousFunctionDefinition());
     147             : }
     148             : 
     149    12469454 : bool Expression::IsConciseMethodDefinition() const {
     150    26042491 :   return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
     151             : }
     152             : 
     153    12027329 : bool Expression::IsAccessorFunctionDefinition() const {
     154    24716118 :   return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
     155             : }
     156             : 
     157    64693443 : bool Statement::IsJump() const {
     158    82013704 :   switch (node_type()) {
     159             : #define JUMP_NODE_LIST(V) \
     160             :   V(Block)                \
     161             :   V(ExpressionStatement)  \
     162             :   V(ContinueStatement)    \
     163             :   V(BreakStatement)       \
     164             :   V(ReturnStatement)      \
     165             :   V(IfStatement)
     166             : #define GENERATE_CASE(Node) \
     167             :   case k##Node:             \
     168             :     return static_cast<const Node*>(this)->IsJump();
     169    32944267 :     JUMP_NODE_LIST(GENERATE_CASE)
     170             : #undef GENERATE_CASE
     171             : #undef JUMP_NODE_LIST
     172             :     default:
     173     1161693 :       return false;
     174             :   }
     175             : }
     176             : 
     177    18036628 : VariableProxy::VariableProxy(Variable* var, int start_position)
     178             :     : Expression(start_position, kVariableProxy),
     179             :       raw_name_(var->raw_name()),
     180     9018314 :       next_unresolved_(nullptr) {
     181             :   bit_field_ |= IsThisField::encode(var->is_this()) |
     182             :                 IsAssignedField::encode(false) |
     183             :                 IsResolvedField::encode(false) |
     184     9018314 :                 HoleCheckModeField::encode(HoleCheckMode::kElided);
     185             :   BindTo(var);
     186     9018314 : }
     187             : 
     188     5058783 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
     189             :     : Expression(copy_from->position(), kVariableProxy),
     190    10117566 :       next_unresolved_(nullptr) {
     191     5058783 :   bit_field_ = copy_from->bit_field_;
     192             :   DCHECK(!copy_from->is_resolved());
     193     5058783 :   raw_name_ = copy_from->raw_name_;
     194     5058783 : }
     195             : 
     196   106153890 : void VariableProxy::BindTo(Variable* var) {
     197             :   DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
     198             :   set_var(var);
     199             :   set_is_resolved();
     200             :   var->set_is_used();
     201    57586102 :   if (is_assigned()) var->set_maybe_assigned();
     202    48567788 : }
     203             : 
     204    17152758 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
     205             :                        Expression* value, int pos)
     206    17152758 :     : Expression(pos, node_type), target_(target), value_(value) {
     207    17152758 :   bit_field_ |= TokenField::encode(op);
     208    17152758 : }
     209             : 
     210     4231477 : bool FunctionLiteral::ShouldEagerCompile() const {
     211     4231477 :   return scope()->ShouldEagerCompile();
     212             : }
     213             : 
     214      741926 : void FunctionLiteral::SetShouldEagerCompile() {
     215      741926 :   scope()->set_should_eager_compile();
     216      741927 : }
     217             : 
     218     5166990 : bool FunctionLiteral::AllowsLazyCompilation() {
     219     5166990 :   return scope()->AllowsLazyCompilation();
     220             : }
     221             : 
     222        3534 : Handle<String> FunctionLiteral::name(Isolate* isolate) const {
     223        7068 :   return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
     224             : }
     225             : 
     226    10717660 : int FunctionLiteral::start_position() const {
     227    10717660 :   return scope()->start_position();
     228             : }
     229             : 
     230             : 
     231     8240291 : int FunctionLiteral::end_position() const {
     232     8240291 :   return scope()->end_position();
     233             : }
     234             : 
     235             : 
     236     6529366 : LanguageMode FunctionLiteral::language_mode() const {
     237     6529366 :   return scope()->language_mode();
     238             : }
     239             : 
     240    14318803 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
     241             : 
     242      793535 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
     243     1587071 :   if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
     244             :   DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
     245     1306956 :   return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
     246             : }
     247             : 
     248      106057 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
     249             :                                              Kind kind, bool is_computed_name)
     250             :     : LiteralProperty(key, value, is_computed_name),
     251             :       kind_(kind),
     252      106057 :       emit_store_(true) {}
     253             : 
     254     7289530 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
     255             :                                              Expression* key, Expression* value,
     256             :                                              bool is_computed_name)
     257     3651362 :     : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
     258     7289531 :   if (!is_computed_name &&
     259             :       key->AsLiteral()->raw_value()->EqualsString(
     260     7276337 :           ast_value_factory->proto_string())) {
     261       33634 :     kind_ = PROTOTYPE;
     262     7235458 :   } else if (value_->AsMaterializedLiteral() != nullptr) {
     263       69617 :     kind_ = MATERIALIZED_LITERAL;
     264     3548112 :   } else if (value_->IsLiteral()) {
     265     2287970 :     kind_ = CONSTANT;
     266             :   } else {
     267     1260142 :     kind_ = COMPUTED;
     268             :   }
     269     3651363 : }
     270             : 
     271     4579633 : bool LiteralProperty::NeedsSetFunctionName() const {
     272     4605382 :   return is_computed_name_ && (value_->IsAnonymousFunctionDefinition() ||
     273       43246 :                                value_->IsConciseMethodDefinition() ||
     274     4597130 :                                value_->IsAccessorFunctionDefinition());
     275             : }
     276             : 
     277      472919 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
     278             :                                            Kind kind, bool is_static,
     279             :                                            bool is_computed_name)
     280             :     : LiteralProperty(key, value, is_computed_name),
     281             :       kind_(kind),
     282      472919 :       is_static_(is_static) {}
     283             : 
     284     2520935 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
     285     2520935 :   return kind_ == CONSTANT ||
     286       47054 :       (kind_ == MATERIALIZED_LITERAL &&
     287     2567989 :        CompileTimeValue::IsCompileTimeValue(value_));
     288             : }
     289             : 
     290             : 
     291           0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
     292         569 :   emit_store_ = emit_store;
     293           0 : }
     294             : 
     295      333431 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
     296             : 
     297     3258717 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
     298             :   const auto GETTER = ObjectLiteral::Property::GETTER;
     299             :   const auto SETTER = ObjectLiteral::Property::SETTER;
     300             : 
     301             :   ZoneAllocationPolicy allocator(zone);
     302             : 
     303             :   CustomMatcherZoneHashMap table(
     304             :       Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
     305     2921008 :   for (int i = properties()->length() - 1; i >= 0; i--) {
     306     2584466 :     ObjectLiteral::Property* property = properties()->at(i);
     307     5135737 :     if (property->is_computed_name()) continue;
     308     2581047 :     if (property->IsPrototype()) continue;
     309     2552438 :     Literal* literal = property->key()->AsLiteral();
     310             :     DCHECK(!literal->IsNullLiteral());
     311             : 
     312             :     // If there is an existing entry do not emit a store unless the previous
     313             :     // entry was also an accessor.
     314     2552438 :     uint32_t hash = literal->Hash();
     315     5104876 :     ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
     316     2552438 :     if (entry->value != nullptr) {
     317             :       auto previous_kind =
     318             :           static_cast<ObjectLiteral::Property*>(entry->value)->kind();
     319        1803 :       if (!((property->kind() == GETTER && previous_kind == SETTER) ||
     320        1776 :             (property->kind() == SETTER && previous_kind == GETTER))) {
     321             :         property->set_emit_store(false);
     322             :       }
     323             :     }
     324     2552438 :     entry->value = property;
     325             :   }
     326      337709 : }
     327             : 
     328        7711 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
     329             :   // We still check for __proto__:null after computed property names.
     330       11560 :   for (; i < properties()->length(); i++) {
     331        7710 :     if (properties()->at(i)->IsNullPrototype()) {
     332             :       set_has_null_protoype(true);
     333             :       break;
     334             :     }
     335             :   }
     336        1931 : }
     337             : 
     338     3295670 : int ObjectLiteral::InitDepthAndFlags() {
     339      438535 :   if (is_initialized()) return depth();
     340             :   bool is_simple = true;
     341             :   bool has_seen_prototype = false;
     342             :   bool needs_initial_allocation_site = false;
     343             :   int depth_acc = 1;
     344             :   uint32_t nof_properties = 0;
     345             :   uint32_t elements = 0;
     346             :   uint32_t max_element_index = 0;
     347     5484131 :   for (int i = 0; i < properties()->length(); i++) {
     348     2576859 :     ObjectLiteral::Property* property = properties()->at(i);
     349     2576859 :     if (property->IsPrototype()) {
     350             :       has_seen_prototype = true;
     351             :       // __proto__:null has no side-effects and is set directly on the
     352             :       // boilerplate.
     353       28563 :       if (property->IsNullPrototype()) {
     354             :         set_has_null_protoype(true);
     355       28563 :         continue;
     356             :       }
     357             :       DCHECK(!has_null_prototype());
     358             :       is_simple = false;
     359             :       continue;
     360             :     }
     361     2548296 :     if (nof_properties == boilerplate_properties_) {
     362             :       DCHECK(property->is_computed_name());
     363             :       is_simple = false;
     364        1962 :       if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
     365        1962 :       break;
     366             :     }
     367             :     DCHECK(!property->is_computed_name());
     368             : 
     369     7639002 :     MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
     370     2546334 :     if (literal != nullptr) {
     371       48083 :       int subliteral_depth = literal->InitDepthAndFlags() + 1;
     372       48083 :       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
     373       48083 :       needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
     374             :     }
     375             : 
     376     7639002 :     const AstValue* key = property->key()->AsLiteral()->raw_value();
     377             :     Expression* value = property->value();
     378             : 
     379     2546334 :     bool is_compile_time_value = CompileTimeValue::IsCompileTimeValue(value);
     380     2546334 :     is_simple = is_simple && is_compile_time_value;
     381             : 
     382             :     // Keep track of the number of elements in the object literal and
     383             :     // the largest element index.  If the largest element index is
     384             :     // much larger than the number of elements, creating an object
     385             :     // literal with fast elements will be a waste of space.
     386     2546334 :     uint32_t element_index = 0;
     387     4179022 :     if (key->IsString() && key->AsString()->AsArrayIndex(&element_index)) {
     388         325 :       max_element_index = Max(element_index, max_element_index);
     389         325 :       elements++;
     390     2546009 :     } else if (key->ToUint32(&element_index) && element_index != kMaxUInt32) {
     391      913646 :       max_element_index = Max(element_index, max_element_index);
     392      913646 :       elements++;
     393             :     }
     394             : 
     395     2546334 :     nof_properties++;
     396             :   }
     397             : 
     398             :   set_depth(depth_acc);
     399             :   set_is_simple(is_simple);
     400             :   set_needs_initial_allocation_site(needs_initial_allocation_site);
     401      334337 :   set_has_elements(elements > 0);
     402      334905 :   set_fast_elements((max_element_index <= 32) ||
     403         568 :                     ((2 * elements) >= max_element_index));
     404      334337 :   return depth_acc;
     405             : }
     406             : 
     407     5972096 : void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
     408      565962 :   if (!constant_properties_.is_null()) return;
     409             : 
     410             :   int index_keys = 0;
     411             :   bool has_seen_proto = false;
     412     5409013 :   for (int i = 0; i < properties()->length(); i++) {
     413     2563391 :     ObjectLiteral::Property* property = properties()->at(i);
     414     2563391 :     if (property->IsPrototype()) {
     415             :       has_seen_proto = true;
     416       23855 :       continue;
     417             :     }
     418     2540225 :     if (property->is_computed_name()) {
     419             :       continue;
     420             :     }
     421             : 
     422     5079072 :     Handle<Object> key = property->key()->AsLiteral()->value();
     423             : 
     424     2539536 :     uint32_t element_index = 0;
     425     6704847 :     if (key->ToArrayIndex(&element_index) ||
     426     1625775 :         (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index))) {
     427      914111 :       index_keys++;
     428             :     }
     429             :   }
     430             : 
     431             :   Handle<BoilerplateDescription> constant_properties =
     432             :       isolate->factory()->NewBoilerplateDescription(boilerplate_properties_,
     433             :                                                     properties()->length(),
     434      282231 :                                                     index_keys, has_seen_proto);
     435             : 
     436             :   int position = 0;
     437     5686986 :   for (int i = 0; i < properties()->length(); i++) {
     438     2561836 :     ObjectLiteral::Property* property = properties()->at(i);
     439     2584997 :     if (property->IsPrototype()) continue;
     440             : 
     441     2538675 :     if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
     442             :       DCHECK(property->is_computed_name());
     443         574 :       break;
     444             :     }
     445             :     DCHECK(!property->is_computed_name());
     446             : 
     447     7614303 :     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
     448     2538101 :     if (m_literal != nullptr) {
     449       48083 :       m_literal->BuildConstants(isolate);
     450             :     }
     451             : 
     452             :     // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
     453             :     // value for COMPUTED properties, the real value is filled in at
     454             :     // runtime. The enumeration order is maintained.
     455     5076202 :     Handle<Object> key = property->key()->AsLiteral()->value();
     456     2538101 :     Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
     457             : 
     458     2538101 :     uint32_t element_index = 0;
     459     4162556 :     if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) {
     460         325 :       key = isolate->factory()->NewNumberFromUint(element_index);
     461     3451422 :     } else if (key->IsNumber() && !key->ToArrayIndex(&element_index)) {
     462           0 :       key = isolate->factory()->NumberToString(key);
     463             :     }
     464             : 
     465             :     // Add name, value pair to the fixed array.
     466     5076202 :     constant_properties->set(position++, *key);
     467     5076202 :     constant_properties->set(position++, *value);
     468             :   }
     469             : 
     470      282231 :   constant_properties_ = constant_properties;
     471             : }
     472             : 
     473      508181 : bool ObjectLiteral::IsFastCloningSupported() const {
     474             :   // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
     475             :   // literals don't support copy-on-write (COW) elements for now.
     476             :   // TODO(mvstanton): make object literals support COW elements.
     477      771337 :   return fast_elements() && is_shallow() &&
     478             :          properties_count() <=
     479      263561 :              ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
     480             : }
     481             : 
     482      248665 : bool ArrayLiteral::is_empty() const {
     483             :   DCHECK(is_initialized());
     484      248665 :   return values()->is_empty() &&
     485           0 :          (constant_elements().is_null() || constant_elements()->is_empty());
     486             : }
     487             : 
     488     8532334 : int ArrayLiteral::InitDepthAndFlags() {
     489             :   DCHECK_LT(first_spread_index_, 0);
     490      307262 :   if (is_initialized()) return depth();
     491             : 
     492      267510 :   int constants_length = values()->length();
     493             : 
     494             :   // Fill in the literals.
     495             :   bool is_simple = true;
     496             :   int depth_acc = 1;
     497             :   int array_index = 0;
     498     8244948 :   for (; array_index < constants_length; array_index++) {
     499     7977438 :     Expression* element = values()->at(array_index);
     500             :     DCHECK(!element->IsSpread());
     501             :     MaterializedLiteral* literal = element->AsMaterializedLiteral();
     502     7977438 :     if (literal != nullptr) {
     503       24950 :       int subliteral_depth = literal->InitDepthAndFlags() + 1;
     504       24950 :       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
     505             :     }
     506             : 
     507     7977438 :     if (!CompileTimeValue::IsCompileTimeValue(element)) {
     508             :       is_simple = false;
     509             :     }
     510             :   }
     511             : 
     512             :   set_depth(depth_acc);
     513             :   set_is_simple(is_simple);
     514             :   // Array literals always need an initial allocation site to properly track
     515             :   // elements transitions.
     516             :   set_needs_initial_allocation_site(true);
     517      267510 :   return depth_acc;
     518             : }
     519             : 
     520     8223700 : void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
     521             :   DCHECK_LT(first_spread_index_, 0);
     522             : 
     523      127279 :   if (!constant_elements_.is_null()) return;
     524             : 
     525      127279 :   int constants_length = values()->length();
     526             :   ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
     527             :   Handle<FixedArray> fixed_array =
     528      127279 :       isolate->factory()->NewFixedArrayWithHoles(constants_length);
     529             : 
     530             :   // Fill in the literals.
     531             :   bool is_holey = false;
     532             :   int array_index = 0;
     533     8096421 :   for (; array_index < constants_length; array_index++) {
     534     7969142 :     Expression* element = values()->at(array_index);
     535             :     DCHECK(!element->IsSpread());
     536             :     MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
     537     7969142 :     if (m_literal != nullptr) {
     538       24950 :       m_literal->BuildConstants(isolate);
     539             :     }
     540             : 
     541             :     // New handle scope here, needs to be after BuildContants().
     542             :     HandleScope scope(isolate);
     543     7969142 :     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
     544     7969142 :     if (boilerplate_value->IsTheHole(isolate)) {
     545             :       is_holey = true;
     546             :       continue;
     547             :     }
     548             : 
     549     6808014 :     if (boilerplate_value->IsUninitialized(isolate)) {
     550             :       boilerplate_value = handle(Smi::kZero, isolate);
     551             :     }
     552             : 
     553             :     kind = GetMoreGeneralElementsKind(kind,
     554     6808014 :                                       boilerplate_value->OptimalElementsKind());
     555     6808014 :     fixed_array->set(array_index, *boilerplate_value);
     556             :   }
     557             : 
     558      127279 :   if (is_holey) kind = GetHoleyElementsKind(kind);
     559             : 
     560             :   // Simple and shallow arrays can be lazily copied, we transform the
     561             :   // elements array to a copy-on-write array.
     562      317435 :   if (is_simple() && depth() == 1 && array_index > 0 &&
     563             :       IsSmiOrObjectElementsKind(kind)) {
     564      102350 :     fixed_array->set_map(isolate->heap()->fixed_cow_array_map());
     565             :   }
     566             : 
     567             :   Handle<FixedArrayBase> elements = fixed_array;
     568      127279 :   if (IsDoubleElementsKind(kind)) {
     569             :     ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
     570        2489 :     elements = isolate->factory()->NewFixedDoubleArray(constants_length);
     571             :     // We are copying from non-fast-double to fast-double.
     572             :     ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
     573        4978 :     accessor->CopyElements(fixed_array, from_kind, elements, constants_length);
     574             :   }
     575             : 
     576             :   // Remember both the literal's constant values as well as the ElementsKind.
     577             :   Handle<ConstantElementsPair> literals =
     578      127279 :       isolate->factory()->NewConstantElementsPair(kind, elements);
     579             : 
     580      127279 :   constant_elements_ = literals;
     581             : }
     582             : 
     583      218280 : bool ArrayLiteral::IsFastCloningSupported() const {
     584      218280 :   return depth() <= 1 &&
     585      106821 :          values()->length() <=
     586      111459 :              ConstructorBuiltins::kMaximumClonedShallowArrayElements;
     587             : }
     588             : 
     589        2112 : void ArrayLiteral::RewindSpreads() {
     590        2112 :   values_->Rewind(first_spread_index_);
     591        2112 :   first_spread_index_ = -1;
     592        2112 : }
     593             : 
     594      216549 : bool MaterializedLiteral::IsSimple() const {
     595      331499 :   if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
     596      450468 :   if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
     597             :   DCHECK(IsRegExpLiteral());
     598             :   return false;
     599             : }
     600             : 
     601    10507243 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
     602             :                                                         Isolate* isolate) {
     603    10507243 :   if (expression->IsLiteral()) {
     604    19694352 :     return expression->AsLiteral()->value();
     605             :   }
     606      660067 :   if (CompileTimeValue::IsCompileTimeValue(expression)) {
     607       41259 :     return CompileTimeValue::GetValue(isolate, expression);
     608             :   }
     609      618808 :   return isolate->factory()->uninitialized_value();
     610             : }
     611             : 
     612       73033 : int MaterializedLiteral::InitDepthAndFlags() {
     613       92880 :   if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
     614      101913 :   if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
     615             :   DCHECK(IsRegExpLiteral());
     616             :   return 1;
     617             : }
     618             : 
     619       48083 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
     620       48083 :   if (IsArrayLiteral()) {
     621       29271 :     return AsArrayLiteral()->needs_initial_allocation_site();
     622             :   }
     623       38326 :   if (IsObjectLiteral()) {
     624      102399 :     return AsObjectLiteral()->needs_initial_allocation_site();
     625             :   }
     626             :   DCHECK(IsRegExpLiteral());
     627             :   return false;
     628             : }
     629             : 
     630       73033 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
     631       73033 :   if (IsArrayLiteral()) {
     632       39694 :     return AsArrayLiteral()->BuildConstantElements(isolate);
     633             :   }
     634       53186 :   if (IsObjectLiteral()) {
     635       97454 :     return AsObjectLiteral()->BuildConstantProperties(isolate);
     636             :   }
     637             :   DCHECK(IsRegExpLiteral());
     638             : }
     639             : 
     640        1439 : Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
     641       10843 :     Isolate* isolate) {
     642             :   Handle<FixedArray> raw_strings =
     643        1439 :       isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
     644             :   bool raw_and_cooked_match = true;
     645        7868 :   for (int i = 0; i < raw_strings->length(); ++i) {
     646        4990 :     if (*this->raw_strings()->at(i)->value() !=
     647        2495 :         *this->cooked_strings()->at(i)->value()) {
     648             :       raw_and_cooked_match = false;
     649             :     }
     650        2495 :     raw_strings->set(i, *this->raw_strings()->at(i)->value());
     651             :   }
     652             :   Handle<FixedArray> cooked_strings = raw_strings;
     653        1439 :   if (!raw_and_cooked_match) {
     654             :     cooked_strings = isolate->factory()->NewFixedArray(
     655        1062 :         this->cooked_strings()->length(), TENURED);
     656        5950 :     for (int i = 0; i < cooked_strings->length(); ++i) {
     657        3826 :       cooked_strings->set(i, *this->cooked_strings()->at(i)->value());
     658             :     }
     659             :   }
     660             :   return isolate->factory()->NewTemplateObjectDescription(
     661        1439 :       this->hash(), raw_strings, cooked_strings);
     662             : }
     663             : 
     664             : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
     665             :   // Add is not commutative due to potential for string addition.
     666      603336 :   return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
     667             :          op == Token::BIT_XOR;
     668             : }
     669             : 
     670             : // Check for the pattern: x + 1.
     671      844100 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
     672             :                                      Expression** expr, Smi** literal) {
     673      844100 :   if (right->IsSmiLiteral()) {
     674      181417 :     *expr = left;
     675      362834 :     *literal = right->AsLiteral()->AsSmiLiteral();
     676      181417 :     return true;
     677             :   }
     678             :   return false;
     679             : }
     680             : 
     681      766484 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
     682      603336 :                                             Smi** literal) {
     683     1369820 :   return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
     684       77616 :          (IsCommutativeOperationWithSmiLiteral(op()) &&
     685      844100 :           MatchSmiLiteralOperation(right_, left_, subexpr, literal));
     686             : }
     687             : 
     688     2179202 : static bool IsTypeof(Expression* expr) {
     689     2407972 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     690     2407972 :   return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
     691             : }
     692             : 
     693             : // Check for the pattern: typeof <expression> equals <string literal>.
     694     2179202 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
     695             :                                       Expression* right, Expression** expr,
     696             :                                       Literal** literal) {
     697     2324804 :   if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
     698      291204 :     *expr = left->AsUnaryOperation()->expression();
     699      291204 :     *literal = right->AsLiteral();
     700      145602 :     return true;
     701             :   }
     702             :   return false;
     703             : }
     704             : 
     705     1162365 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
     706     2179202 :                                               Literal** literal) {
     707     3341567 :   return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
     708     3196039 :          MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
     709             : }
     710             : 
     711             : 
     712     2032436 : static bool IsVoidOfLiteral(Expression* expr) {
     713     2157086 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     714     2157086 :   return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
     715     2032436 :          maybe_unary->expression()->IsLiteral();
     716             : }
     717             : 
     718             : 
     719             : // Check for the pattern: void <literal> equals <expression> or
     720             : // undefined equals <expression>
     721     2032436 : static bool MatchLiteralCompareUndefined(Expression* left,
     722             :                                          Token::Value op,
     723             :                                          Expression* right,
     724             :                                          Expression** expr) {
     725     2074310 :   if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
     726       40938 :     *expr = right;
     727       40938 :     return true;
     728             :   }
     729     2030303 :   if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
     730       38757 :     *expr = right;
     731       38757 :     return true;
     732             :   }
     733             :   return false;
     734             : }
     735             : 
     736     3049199 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
     737     3049199 :   return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
     738     3048109 :          MatchLiteralCompareUndefined(right_, op(), left_, expr);
     739             : }
     740             : 
     741             : // Check for the pattern: null equals <expression>
     742     1873374 : static bool MatchLiteralCompareNull(Expression* left,
     743             :                                     Token::Value op,
     744             :                                     Expression* right,
     745             :                                     Expression** expr) {
     746     1929072 :   if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
     747       54734 :     *expr = right;
     748       54734 :     return true;
     749             :   }
     750             :   return false;
     751             : }
     752             : 
     753     2810442 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
     754     2810442 :   return MatchLiteralCompareNull(left_, op(), right_, expr) ||
     755     2809680 :          MatchLiteralCompareNull(right_, op(), left_, expr);
     756             : }
     757             : 
     758     5446772 : Call::CallType Call::GetCallType() const {
     759     4400737 :   VariableProxy* proxy = expression()->AsVariableProxy();
     760     2665848 :   if (proxy != nullptr) {
     761     1734890 :     if (proxy->var()->IsUnallocated()) {
     762             :       return GLOBAL_CALL;
     763      647800 :     } else if (proxy->var()->IsLookupSlot()) {
     764             :       // Calls going through 'with' always use DYNAMIC rather than DYNAMIC_LOCAL
     765             :       // or DYNAMIC_GLOBAL.
     766      186414 :       return proxy->var()->mode() == DYNAMIC ? WITH_CALL : OTHER_CALL;
     767             :     }
     768             :   }
     769             : 
     770     2784687 :   if (expression()->IsSuperCallReference()) return SUPER_CALL;
     771             : 
     772     2224454 :   Property* property = expression()->AsProperty();
     773     1388581 :   if (property != nullptr) {
     774      835873 :     bool is_super = property->IsSuperAccess();
     775      835873 :     if (property->key()->IsPropertyName()) {
     776      831566 :       return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
     777             :     } else {
     778        4307 :       return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
     779             :     }
     780             :   }
     781             : 
     782             :   return OTHER_CALL;
     783             : }
     784             : 
     785      109361 : CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements)
     786      109361 :     : label_(label), statements_(statements) {}
     787             : 
     788     2557030 : uint32_t Literal::Hash() {
     789     2557030 :   return raw_value()->IsString()
     790     1643254 :              ? raw_value()->AsString()->Hash()
     791     6027836 :              : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
     792             : }
     793             : 
     794             : 
     795             : // static
     796       64323 : bool Literal::Match(void* literal1, void* literal2) {
     797       64323 :   const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
     798       63451 :   const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
     799      192673 :   return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) ||
     800         872 :          (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
     801             : }
     802             : 
     803           0 : const char* CallRuntime::debug_name() {
     804             : #ifdef DEBUG
     805             :   return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
     806             :                         : function_->name;
     807             : #else
     808           0 :   return is_jsruntime() ? "(context function)" : function_->name;
     809             : #endif  // DEBUG
     810             : }
     811             : 
     812             : #define RETURN_LABELS(NodeType) \
     813             :   case k##NodeType:             \
     814             :     return static_cast<const NodeType*>(this)->labels();
     815             : 
     816       45167 : ZoneList<const AstRawString*>* BreakableStatement::labels() const {
     817       89796 :   switch (node_type()) {
     818       32748 :     BREAKABLE_NODE_LIST(RETURN_LABELS)
     819        3151 :     ITERATION_NODE_LIST(RETURN_LABELS)
     820             :     default:
     821           0 :       UNREACHABLE();
     822             :   }
     823             : }
     824             : 
     825             : #undef RETURN_LABELS
     826             : 
     827             : }  // namespace internal
     828             : }  // namespace v8

Generated by: LCOV version 1.10