LCOV - code coverage report
Current view: top level - src/ast - ast.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 450 470 95.7 %
Date: 2017-04-26 Functions: 81 87 93.1 %

          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/property-details.h"
      23             : #include "src/property.h"
      24             : #include "src/string-stream.h"
      25             : #include "src/type-info.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      294281 : IterationStatement* AstNode::AsIterationStatement() {
      66      294281 :   switch (node_type()) {
      67         447 :     ITERATION_NODE_LIST(RETURN_NODE);
      68             :     default:
      69             :       return nullptr;
      70             :   }
      71             : }
      72             : 
      73       83904 : BreakableStatement* AstNode::AsBreakableStatement() {
      74       83904 :   switch (node_type()) {
      75       59948 :     BREAKABLE_NODE_LIST(RETURN_NODE);
      76       15840 :     ITERATION_NODE_LIST(RETURN_NODE);
      77             :     default:
      78             :       return nullptr;
      79             :   }
      80             : }
      81             : 
      82    36326821 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
      83    36326821 :   switch (node_type()) {
      84       40110 :     LITERAL_NODE_LIST(RETURN_NODE);
      85             :     default:
      86             :       return nullptr;
      87             :   }
      88             : }
      89             : 
      90             : #undef RETURN_NODE
      91             : 
      92     1107176 : bool Expression::IsSmiLiteral() const {
      93     3292362 :   return IsLiteral() && AsLiteral()->raw_value()->IsSmi();
      94             : }
      95             : 
      96     2523645 : bool Expression::IsNumberLiteral() const {
      97     8523985 :   return IsLiteral() && AsLiteral()->raw_value()->IsNumber();
      98             : }
      99             : 
     100     1820993 : bool Expression::IsStringLiteral() const {
     101     5365567 :   return IsLiteral() && AsLiteral()->raw_value()->IsString();
     102             : }
     103             : 
     104    28750032 : bool Expression::IsPropertyName() const {
     105   102566629 :   return IsLiteral() && AsLiteral()->IsPropertyName();
     106             : }
     107             : 
     108     3695693 : bool Expression::IsNullLiteral() const {
     109     7391386 :   if (!IsLiteral()) return false;
     110     2313446 :   return AsLiteral()->raw_value()->IsNull();
     111             : }
     112             : 
     113     4429841 : bool Expression::IsUndefinedLiteral() const {
     114     5891558 :   if (IsLiteral() && AsLiteral()->raw_value()->IsUndefined()) return true;
     115             : 
     116     6018358 :   const VariableProxy* var_proxy = AsVariableProxy();
     117     4395251 :   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     3343400 :   return var != NULL && var->IsUnallocated() &&
     122     1720292 :          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
     123             : }
     124             : 
     125     2502865 : bool Expression::ToBooleanIsTrue() const {
     126     5033739 :   return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
     127             : }
     128             : 
     129     2504348 : bool Expression::ToBooleanIsFalse() const {
     130     5044355 :   return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
     131             : }
     132             : 
     133    11747171 : 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    11747171 :   if (IsRewritableExpression()) return false;
     138    16861541 :   return IsProperty() ||
     139    10218820 :          (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
     140             : }
     141             : 
     142           0 : bool Expression::IsValidReferenceExpressionOrThis() const {
     143           0 :   return IsValidReferenceExpression() ||
     144           0 :          (IsVariableProxy() && AsVariableProxy()->is_this());
     145             : }
     146             : 
     147    19136508 : bool Expression::IsAnonymousFunctionDefinition() const {
     148     1534518 :   return (IsFunctionLiteral() &&
     149    37454591 :           AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
     150        3765 :          (IsDoExpression() &&
     151    19140272 :           AsDoExpression()->IsAnonymousFunctionDefinition());
     152             : }
     153             : 
     154       11030 : void Expression::MarkTail() {
     155       11030 :   if (IsConditional()) {
     156         280 :     AsConditional()->MarkTail();
     157       10890 :   } else if (IsCall()) {
     158        3667 :     AsCall()->MarkTail();
     159        7223 :   } else if (IsBinaryOperation()) {
     160        2484 :     AsBinaryOperation()->MarkTail();
     161             :   }
     162       11030 : }
     163             : 
     164           0 : bool DoExpression::IsAnonymousFunctionDefinition() const {
     165             :   // This is specifically to allow DoExpressions to represent ClassLiterals.
     166        7055 :   return represented_function_ != nullptr &&
     167        3290 :          represented_function_->raw_name()->IsEmpty();
     168             : }
     169             : 
     170    53418581 : bool Statement::IsJump() const {
     171    68999956 :   switch (node_type()) {
     172             : #define JUMP_NODE_LIST(V) \
     173             :   V(Block)                \
     174             :   V(ExpressionStatement)  \
     175             :   V(ContinueStatement)    \
     176             :   V(BreakStatement)       \
     177             :   V(ReturnStatement)      \
     178             :   V(IfStatement)
     179             : #define GENERATE_CASE(Node) \
     180             :   case k##Node:             \
     181             :     return static_cast<const Node*>(this)->IsJump();
     182    26433281 :     JUMP_NODE_LIST(GENERATE_CASE)
     183             : #undef GENERATE_CASE
     184             : #undef JUMP_NODE_LIST
     185             :     default:
     186      937730 :       return false;
     187             :   }
     188             : }
     189             : 
     190    27512578 : VariableProxy::VariableProxy(Variable* var, int start_position)
     191             :     : Expression(start_position, kVariableProxy),
     192             :       raw_name_(var->raw_name()),
     193    13756289 :       next_unresolved_(nullptr) {
     194             :   bit_field_ |= IsThisField::encode(var->is_this()) |
     195             :                 IsAssignedField::encode(false) |
     196             :                 IsResolvedField::encode(false) |
     197    13756289 :                 HoleCheckModeField::encode(HoleCheckMode::kElided);
     198             :   BindTo(var);
     199    13756289 : }
     200             : 
     201   124212310 : VariableProxy::VariableProxy(const AstRawString* name,
     202             :                              VariableKind variable_kind, int start_position)
     203             :     : Expression(start_position, kVariableProxy),
     204             :       raw_name_(name),
     205   124212310 :       next_unresolved_(nullptr) {
     206   124212310 :   bit_field_ |= IsThisField::encode(variable_kind == THIS_VARIABLE) |
     207             :                 IsAssignedField::encode(false) |
     208             :                 IsResolvedField::encode(false) |
     209   124212310 :                 HoleCheckModeField::encode(HoleCheckMode::kElided);
     210   124212310 : }
     211             : 
     212     2534705 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
     213             :     : Expression(copy_from->position(), kVariableProxy),
     214     5069410 :       next_unresolved_(nullptr) {
     215     2534705 :   bit_field_ = copy_from->bit_field_;
     216             :   DCHECK(!copy_from->is_resolved());
     217     2534705 :   raw_name_ = copy_from->raw_name_;
     218     2534705 : }
     219             : 
     220    93254615 : void VariableProxy::BindTo(Variable* var) {
     221             :   DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
     222             :   set_var(var);
     223             :   set_is_resolved();
     224             :   var->set_is_used();
     225   107010904 :   if (is_assigned()) var->set_maybe_assigned();
     226    93254615 : }
     227             : 
     228    28627431 : void VariableProxy::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     229             :                                         TypeofMode typeof_mode,
     230     3032345 :                                         FeedbackSlotCache* cache) {
     231    28627431 :   if (UsesVariableFeedbackSlot()) {
     232             :     // VariableProxies that point to the same Variable within a function can
     233             :     // make their loads from the same IC slot.
     234     5978997 :     if (var()->IsUnallocated() || var()->mode() == DYNAMIC_GLOBAL) {
     235     4772404 :       FeedbackSlot slot = cache->Get(typeof_mode, var());
     236     4772402 :       if (!slot.IsInvalid()) {
     237     1740057 :         variable_feedback_slot_ = slot;
     238    30367487 :         return;
     239             :       }
     240     3032345 :       variable_feedback_slot_ = spec->AddLoadGlobalICSlot(typeof_mode);
     241             :       cache->Put(typeof_mode, var(), variable_feedback_slot_);
     242             :     } else {
     243      324414 :       variable_feedback_slot_ = spec->AddLoadICSlot();
     244             :     }
     245             :   }
     246             : }
     247             : 
     248    10911912 : static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec,
     249             :                               LanguageMode language_mode,
     250             :                               FeedbackSlot* out_slot) {
     251    10911912 :   Property* property = expr->AsProperty();
     252    10911922 :   LhsKind assign_type = Property::GetAssignType(property);
     253             :   // TODO(ishell): consider using ICSlotCache for variables here.
     254    19060790 :   if (assign_type == VARIABLE &&
     255     8148865 :       expr->AsVariableProxy()->var()->IsUnallocated()) {
     256      998372 :     *out_slot = spec->AddStoreGlobalICSlot(language_mode);
     257             : 
     258     9913560 :   } else if (assign_type == NAMED_PROPERTY) {
     259     2551741 :     *out_slot = spec->AddStoreICSlot(language_mode);
     260             : 
     261     7361819 :   } else if (assign_type == KEYED_PROPERTY) {
     262      210490 :     *out_slot = spec->AddKeyedStoreICSlot(language_mode);
     263             :   }
     264    10911932 : }
     265             : 
     266       11513 : void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     267             :                                          LanguageMode language_mode,
     268       11513 :                                          FeedbackSlotCache* cache) {
     269       23026 :   AssignVectorSlots(each(), spec, language_mode, &each_slot_);
     270       11513 :   for_in_feedback_slot_ = spec->AddGeneralSlot();
     271       11513 : }
     272             : 
     273    28097097 : Assignment::Assignment(Token::Value op, Expression* target, Expression* value,
     274             :                        int pos)
     275             :     : Expression(pos, kAssignment),
     276             :       target_(target),
     277             :       value_(value),
     278    28097097 :       binary_operation_(NULL) {
     279             :   bit_field_ |= IsUninitializedField::encode(false) |
     280             :                 KeyTypeField::encode(ELEMENT) |
     281    28097097 :                 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
     282    28097097 : }
     283             : 
     284    10624862 : void Assignment::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     285             :                                      LanguageMode language_mode,
     286    10624862 :                                      FeedbackSlotCache* cache) {
     287    21249724 :   AssignVectorSlots(target(), spec, language_mode, &slot_);
     288    10624871 : }
     289             : 
     290      275545 : void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     291             :                                          LanguageMode language_mode,
     292      275545 :                                          FeedbackSlotCache* cache) {
     293      551090 :   AssignVectorSlots(expression(), spec, language_mode, &slot_);
     294             :   // Assign a slot to collect feedback about binary operations. Used only in
     295             :   // ignition. Fullcodegen uses AstId to record type feedback.
     296      275545 :   binary_operation_slot_ = spec->AddInterpreterBinaryOpICSlot();
     297      275545 : }
     298             : 
     299             : 
     300      710940 : Token::Value Assignment::binary_op() const {
     301      710940 :   switch (op()) {
     302             :     case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
     303        8472 :     case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
     304        7568 :     case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
     305        6535 :     case Token::ASSIGN_SHL: return Token::SHL;
     306        7854 :     case Token::ASSIGN_SAR: return Token::SAR;
     307        7117 :     case Token::ASSIGN_SHR: return Token::SHR;
     308      631286 :     case Token::ASSIGN_ADD: return Token::ADD;
     309       11451 :     case Token::ASSIGN_SUB: return Token::SUB;
     310        7954 :     case Token::ASSIGN_MUL: return Token::MUL;
     311        7080 :     case Token::ASSIGN_DIV: return Token::DIV;
     312        8082 :     case Token::ASSIGN_MOD: return Token::MOD;
     313           0 :     default: UNREACHABLE();
     314             :   }
     315             :   return Token::ILLEGAL;
     316             : }
     317             : 
     318     5458779 : bool FunctionLiteral::ShouldEagerCompile() const {
     319     5458779 :   return scope()->ShouldEagerCompile();
     320             : }
     321             : 
     322     1096879 : void FunctionLiteral::SetShouldEagerCompile() {
     323     1096879 :   scope()->set_should_eager_compile();
     324     1096884 : }
     325             : 
     326     6235391 : bool FunctionLiteral::AllowsLazyCompilation() {
     327     6235391 :   return scope()->AllowsLazyCompilation();
     328             : }
     329             : 
     330             : 
     331    12922248 : int FunctionLiteral::start_position() const {
     332    12922248 :   return scope()->start_position();
     333             : }
     334             : 
     335             : 
     336     9749704 : int FunctionLiteral::end_position() const {
     337     9749704 :   return scope()->end_position();
     338             : }
     339             : 
     340             : 
     341    11610958 : LanguageMode FunctionLiteral::language_mode() const {
     342    11610958 :   return scope()->language_mode();
     343             : }
     344             : 
     345    28041180 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
     346             : 
     347     2452017 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
     348     4904034 :   if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
     349             :   DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
     350     3716580 :   return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
     351             : }
     352             : 
     353      220800 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
     354             :                                              Kind kind, bool is_computed_name)
     355             :     : LiteralProperty(key, value, is_computed_name),
     356             :       kind_(kind),
     357      441600 :       emit_store_(true) {}
     358             : 
     359     9378466 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
     360             :                                              Expression* key, Expression* value,
     361             :                                              bool is_computed_name)
     362     4697000 :     : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
     363     9378468 :   if (!is_computed_name &&
     364             :       key->AsLiteral()->raw_value()->EqualsString(
     365     9362934 :           ast_value_factory->proto_string())) {
     366       92665 :     kind_ = PROTOTYPE;
     367     9208674 :   } else if (value_->AsMaterializedLiteral() != NULL) {
     368      297937 :     kind_ = MATERIALIZED_LITERAL;
     369     4306400 :   } else if (value_->IsLiteral()) {
     370     2050908 :     kind_ = CONSTANT;
     371             :   } else {
     372     2255492 :     kind_ = COMPUTED;
     373             :   }
     374     4697002 : }
     375             : 
     376      293714 : FeedbackSlot LiteralProperty::GetStoreDataPropertySlot() const {
     377      293714 :   int offset = FunctionLiteral::NeedsHomeObject(value_) ? 1 : 0;
     378      293714 :   return GetSlot(offset);
     379             : }
     380             : 
     381           0 : void LiteralProperty::SetStoreDataPropertySlot(FeedbackSlot slot) {
     382      307523 :   int offset = FunctionLiteral::NeedsHomeObject(value_) ? 1 : 0;
     383           0 :   return SetSlot(slot, offset);
     384             : }
     385             : 
     386      293714 : bool LiteralProperty::NeedsSetFunctionName() const {
     387      299192 :   return is_computed_name_ &&
     388       10666 :          (value_->IsAnonymousFunctionDefinition() ||
     389        9458 :           (value_->IsFunctionLiteral() &&
     390      297984 :            IsConciseMethod(value_->AsFunctionLiteral()->kind())));
     391             : }
     392             : 
     393      350663 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
     394             :                                            Kind kind, bool is_static,
     395             :                                            bool is_computed_name)
     396             :     : LiteralProperty(key, value, is_computed_name),
     397             :       kind_(kind),
     398      350663 :       is_static_(is_static) {}
     399             : 
     400       43578 : void ClassLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     401             :                                        LanguageMode language_mode,
     402      390618 :                                        FeedbackSlotCache* cache) {
     403             :   // This logic that computes the number of slots needed for vector store
     404             :   // ICs must mirror BytecodeGenerator::VisitClassLiteral.
     405       43578 :   if (FunctionLiteral::NeedsHomeObject(constructor())) {
     406        1204 :     home_object_slot_ = spec->AddStoreICSlot(language_mode);
     407             :   }
     408             : 
     409       43578 :   if (NeedsProxySlot()) {
     410           0 :     proxy_slot_ = spec->AddStoreICSlot(language_mode);
     411             :   }
     412             : 
     413      650502 :   for (int i = 0; i < properties()->length(); i++) {
     414      303462 :     ClassLiteral::Property* property = properties()->at(i);
     415      303462 :     Expression* value = property->value();
     416      303462 :     if (FunctionLiteral::NeedsHomeObject(value)) {
     417             :       property->SetSlot(spec->AddStoreICSlot(language_mode));
     418             :     }
     419             :     property->SetStoreDataPropertySlot(
     420             :         spec->AddStoreDataPropertyInLiteralICSlot());
     421             :   }
     422       43578 : }
     423             : 
     424     4354764 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
     425     4354764 :   return kind_ == CONSTANT ||
     426      363519 :       (kind_ == MATERIALIZED_LITERAL &&
     427     4718283 :        CompileTimeValue::IsCompileTimeValue(value_));
     428             : }
     429             : 
     430             : 
     431           0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
     432         818 :   emit_store_ = emit_store;
     433           0 : }
     434             : 
     435     1177670 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
     436             : 
     437      752293 : void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     438             :                                         LanguageMode language_mode,
     439     4078660 :                                         FeedbackSlotCache* cache) {
     440             :   MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, cache);
     441             : 
     442             :   // This logic that computes the number of slots needed for vector store
     443             :   // ics must mirror FullCodeGenerator::VisitObjectLiteral.
     444             :   int property_index = 0;
     445     6644612 :   for (; property_index < properties()->length(); property_index++) {
     446     3193885 :     ObjectLiteral::Property* property = properties()->at(property_index);
     447     3815873 :     if (property->is_computed_name()) break;
     448     2570013 :     if (property->IsCompileTimeValue()) continue;
     449             : 
     450      621988 :     Literal* key = property->key()->AsLiteral();
     451             :     Expression* value = property->value();
     452      621988 :     switch (property->kind()) {
     453             :       case ObjectLiteral::Property::SPREAD:
     454             :       case ObjectLiteral::Property::CONSTANT:
     455           0 :         UNREACHABLE();
     456             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
     457             :       // Fall through.
     458             :       case ObjectLiteral::Property::COMPUTED:
     459             :         // It is safe to use [[Put]] here because the boilerplate already
     460             :         // contains computed properties with an uninitialized value.
     461      575795 :         if (key->IsStringLiteral()) {
     462      575017 :           if (property->emit_store()) {
     463             :             property->SetSlot(spec->AddStoreOwnICSlot());
     464      574804 :             if (FunctionLiteral::NeedsHomeObject(value)) {
     465             :               property->SetSlot(spec->AddStoreICSlot(language_mode), 1);
     466             :             }
     467             :           }
     468             :           break;
     469             :         }
     470         778 :         if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
     471             :           property->SetSlot(spec->AddStoreICSlot(language_mode));
     472             :         }
     473             :         break;
     474             :       case ObjectLiteral::Property::PROTOTYPE:
     475             :         break;
     476             :       case ObjectLiteral::Property::GETTER:
     477        3660 :         if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
     478             :           property->SetSlot(spec->AddStoreICSlot(language_mode));
     479             :         }
     480             :         break;
     481             :       case ObjectLiteral::Property::SETTER:
     482        2532 :         if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
     483             :           property->SetSlot(spec->AddStoreICSlot(language_mode));
     484             :         }
     485             :         break;
     486             :     }
     487             :   }
     488             : 
     489      760415 :   for (; property_index < properties()->length(); property_index++) {
     490        8122 :     ObjectLiteral::Property* property = properties()->at(property_index);
     491             : 
     492        4061 :     Expression* value = property->value();
     493        4061 :     if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
     494        4011 :       if (FunctionLiteral::NeedsHomeObject(value)) {
     495             :         property->SetSlot(spec->AddStoreICSlot(language_mode));
     496             :       }
     497             :     }
     498             :     property->SetStoreDataPropertySlot(
     499             :         spec->AddStoreDataPropertyInLiteralICSlot());
     500             :   }
     501      752293 : }
     502             : 
     503             : 
     504     4078660 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
     505             :   const auto GETTER = ObjectLiteral::Property::GETTER;
     506             :   const auto SETTER = ObjectLiteral::Property::SETTER;
     507             : 
     508             :   ZoneAllocationPolicy allocator(zone);
     509             : 
     510             :   CustomMatcherZoneHashMap table(
     511             :       Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
     512     3326367 :   for (int i = properties()->length() - 1; i >= 0; i--) {
     513     5147528 :     ObjectLiteral::Property* property = properties()->at(i);
     514     5105866 :     if (property->is_computed_name()) continue;
     515     2571843 :     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
     516     2531792 :     Literal* literal = property->key()->AsLiteral();
     517             :     DCHECK(!literal->IsNullLiteral());
     518             : 
     519             :     // If there is an existing entry do not emit a store unless the previous
     520             :     // entry was also an accessor.
     521     2531792 :     uint32_t hash = literal->Hash();
     522     5063584 :     ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
     523     2531792 :     if (entry->value != NULL) {
     524             :       auto previous_kind =
     525             :           static_cast<ObjectLiteral::Property*>(entry->value)->kind();
     526        2459 :       if (!((property->kind() == GETTER && previous_kind == SETTER) ||
     527        2487 :             (property->kind() == SETTER && previous_kind == GETTER))) {
     528             :         property->set_emit_store(false);
     529             :       }
     530             :     }
     531     2531792 :     entry->value = property;
     532             :   }
     533      752293 : }
     534             : 
     535             : 
     536    17359715 : bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
     537    24883830 :   return property != NULL &&
     538     4917800 :          property->kind() != ObjectLiteral::Property::PROTOTYPE;
     539             : }
     540             : 
     541     4339082 : void ObjectLiteral::InitDepthAndFlags() {
     542     2051272 :   if (depth_ > 0) return;
     543             : 
     544             :   int position = 0;
     545             :   // Accumulate the value in local variables and store it at the end.
     546             :   bool is_simple = true;
     547             :   int depth_acc = 1;
     548             :   uint32_t max_element_index = 0;
     549             :   uint32_t elements = 0;
     550     5878632 :   for (int i = 0; i < properties()->length(); i++) {
     551     2567070 :     ObjectLiteral::Property* property = properties()->at(i);
     552     2567070 :     if (!IsBoilerplateProperty(property)) {
     553             :       is_simple = false;
     554       40001 :       continue;
     555             :     }
     556             : 
     557     2527069 :     if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
     558             :       DCHECK(property->is_computed_name());
     559             :       is_simple = false;
     560        1884 :       break;
     561             :     }
     562             :     DCHECK(!property->is_computed_name());
     563             : 
     564     7575555 :     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
     565     2525185 :     if (m_literal != NULL) {
     566      254980 :       m_literal->InitDepthAndFlags();
     567      254980 :       if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1;
     568             :     }
     569             : 
     570     7575554 :     const AstValue* key = property->key()->AsLiteral()->raw_value();
     571             :     Expression* value = property->value();
     572             : 
     573     2525185 :     bool is_compile_time_value = CompileTimeValue::IsCompileTimeValue(value);
     574             : 
     575             :     // Ensure objects that may, at any point in time, contain fields with double
     576             :     // representation are always treated as nested objects. This is true for
     577             :     // computed fields, and smi and double literals.
     578             :     // TODO(verwaest): Remove once we can store them inline.
     579     7574012 :     if (FLAG_track_double_fields &&
     580     4042500 :         (value->IsNumberLiteral() || !is_compile_time_value)) {
     581     3171544 :       bit_field_ = MayStoreDoublesField::update(bit_field_, true);
     582             :     }
     583             : 
     584     2525184 :     is_simple = is_simple && is_compile_time_value;
     585             : 
     586             :     // Keep track of the number of elements in the object literal and
     587             :     // the largest element index.  If the largest element index is
     588             :     // much larger than the number of elements, creating an object
     589             :     // literal with fast elements will be a waste of space.
     590     2525184 :     uint32_t element_index = 0;
     591     5034375 :     if (key->IsString() && key->AsString()->AsArrayIndex(&element_index)) {
     592         452 :       max_element_index = Max(element_index, max_element_index);
     593         452 :       elements++;
     594     2524732 :     } else if (key->ToUint32(&element_index) && element_index != kMaxUInt32) {
     595       15993 :       max_element_index = Max(element_index, max_element_index);
     596       15993 :       elements++;
     597             :     }
     598             : 
     599             :     // Increment the position for the key and the value.
     600     2525185 :     position += 2;
     601             :   }
     602             : 
     603             :   bit_field_ = FastElementsField::update(
     604             :       bit_field_,
     605     1496520 :       (max_element_index <= 32) || ((2 * elements) >= max_element_index));
     606     1496520 :   bit_field_ = HasElementsField::update(bit_field_, elements > 0);
     607             : 
     608             :   set_is_simple(is_simple);
     609             :   set_depth(depth_acc);
     610             : }
     611             : 
     612     6965733 : void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
     613     1340450 :   if (!constant_properties_.is_null()) return;
     614             : 
     615             :   int index_keys = 0;
     616             :   bool has_seen_proto = false;
     617     5628251 :   for (int i = 0; i < properties()->length(); i++) {
     618     2479358 :     ObjectLiteral::Property* property = properties()->at(i);
     619     2479358 :     if (!IsBoilerplateProperty(property)) {
     620             :       has_seen_proto = true;
     621       30818 :       continue;
     622             :     }
     623     2449285 :     if (property->is_computed_name()) {
     624             :       continue;
     625             :     }
     626             : 
     627     4897080 :     Handle<Object> key = property->key()->AsLiteral()->value();
     628             : 
     629     2448540 :     uint32_t element_index = 0;
     630     7329728 :     if (key->ToArrayIndex(&element_index) ||
     631     2432648 :         (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index))) {
     632       16338 :       index_keys++;
     633             :     }
     634             :   }
     635             : 
     636             :   Handle<BoilerplateDescription> constant_properties =
     637             :       isolate->factory()->NewBoilerplateDescription(boilerplate_properties_,
     638             :                                                     properties()->length(),
     639      669535 :                                                     index_keys, has_seen_proto);
     640             : 
     641             :   int position = 0;
     642     6293230 :   for (int i = 0; i < properties()->length(); i++) {
     643     2477687 :     ObjectLiteral::Property* property = properties()->at(i);
     644     2477687 :     if (!IsBoilerplateProperty(property)) {
     645       30067 :       continue;
     646             :     }
     647             : 
     648     2447620 :     if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
     649             :       DCHECK(property->is_computed_name());
     650         607 :       break;
     651             :     }
     652             :     DCHECK(!property->is_computed_name());
     653             : 
     654     7341038 :     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
     655     2447013 :     if (m_literal != NULL) {
     656      251761 :       m_literal->BuildConstants(isolate);
     657             :     }
     658             : 
     659             :     // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
     660             :     // value for COMPUTED properties, the real value is filled in at
     661             :     // runtime. The enumeration order is maintained.
     662     4894025 :     Handle<Object> key = property->key()->AsLiteral()->value();
     663     2447012 :     Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
     664             : 
     665     2447012 :     uint32_t element_index = 0;
     666     4878270 :     if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) {
     667         416 :       key = isolate->factory()->NewNumberFromUint(element_index);
     668     2462350 :     } else if (key->IsNumber() && !key->ToArrayIndex(&element_index)) {
     669           0 :       key = isolate->factory()->NumberToString(key);
     670             :     }
     671             : 
     672             :     // Add name, value pair to the fixed array.
     673     4894024 :     constant_properties->set(position++, *key);
     674     4894024 :     constant_properties->set(position++, *value);
     675             :   }
     676             : 
     677      669535 :   constant_properties_ = constant_properties;
     678             : }
     679             : 
     680      634180 : bool ObjectLiteral::IsFastCloningSupported() const {
     681             :   // The FastCloneShallowObject builtin doesn't copy elements, and object
     682             :   // literals don't support copy-on-write (COW) elements for now.
     683             :   // TODO(mvstanton): make object literals support COW elements.
     684     1124850 :   return fast_elements() && has_shallow_properties() &&
     685             :          properties_count() <=
     686      491143 :              ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
     687             : }
     688             : 
     689           0 : ElementsKind ArrayLiteral::constant_elements_kind() const {
     690           0 :   return static_cast<ElementsKind>(constant_elements()->elements_kind());
     691             : }
     692             : 
     693    12364156 : void ArrayLiteral::InitDepthAndFlags() {
     694             :   DCHECK_LT(first_spread_index_, 0);
     695             : 
     696      764494 :   if (depth_ > 0) return;
     697             : 
     698      309166 :   int constants_length = values()->length();
     699             : 
     700             :   // Fill in the literals.
     701             :   bool is_simple = true;
     702             :   int depth_acc = 1;
     703             :   int array_index = 0;
     704    11981909 :   for (; array_index < constants_length; array_index++) {
     705    11672743 :     Expression* element = values()->at(array_index);
     706             :     DCHECK(!element->IsSpread());
     707             :     MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
     708    11672743 :     if (m_literal != NULL) {
     709       97157 :       m_literal->InitDepthAndFlags();
     710       97157 :       if (m_literal->depth() + 1 > depth_acc) {
     711       46306 :         depth_acc = m_literal->depth() + 1;
     712             :       }
     713             :     }
     714             : 
     715    11672743 :     if (!CompileTimeValue::IsCompileTimeValue(element)) {
     716             :       is_simple = false;
     717             :     }
     718             :   }
     719             : 
     720             :   set_is_simple(is_simple);
     721             :   set_depth(depth_acc);
     722             : }
     723             : 
     724    12188749 : void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
     725             :   DCHECK_LT(first_spread_index_, 0);
     726             : 
     727      293194 :   if (!constant_elements_.is_null()) return;
     728             : 
     729      293194 :   int constants_length = values()->length();
     730             :   ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
     731             :   Handle<FixedArray> fixed_array =
     732      293194 :       isolate->factory()->NewFixedArrayWithHoles(constants_length);
     733             : 
     734             :   // Fill in the literals.
     735             :   bool is_holey = false;
     736             :   int array_index = 0;
     737    11895555 :   for (; array_index < constants_length; array_index++) {
     738    11602361 :     Expression* element = values()->at(array_index);
     739             :     DCHECK(!element->IsSpread());
     740             :     MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
     741    11602361 :     if (m_literal != NULL) {
     742       95919 :       m_literal->BuildConstants(isolate);
     743             :     }
     744             : 
     745             :     // New handle scope here, needs to be after BuildContants().
     746             :     HandleScope scope(isolate);
     747    11895555 :     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
     748    11602361 :     if (boilerplate_value->IsTheHole(isolate)) {
     749             :       is_holey = true;
     750             :       continue;
     751             :     }
     752             : 
     753    10178271 :     if (boilerplate_value->IsUninitialized(isolate)) {
     754             :       boilerplate_value = handle(Smi::kZero, isolate);
     755             :     }
     756             : 
     757             :     kind = GetMoreGeneralElementsKind(kind,
     758    10178271 :                                       boilerplate_value->OptimalElementsKind());
     759    10178271 :     fixed_array->set(array_index, *boilerplate_value);
     760             :   }
     761             : 
     762      293194 :   if (is_holey) kind = GetHoleyElementsKind(kind);
     763             : 
     764             :   // Simple and shallow arrays can be lazily copied, we transform the
     765             :   // elements array to a copy-on-write array.
     766      510648 :   if (is_simple() && depth() == 1 && array_index > 0 &&
     767             :       IsFastSmiOrObjectElementsKind(kind)) {
     768      128260 :     fixed_array->set_map(isolate->heap()->fixed_cow_array_map());
     769             :   }
     770             : 
     771             :   Handle<FixedArrayBase> elements = fixed_array;
     772      293194 :   if (IsFastDoubleElementsKind(kind)) {
     773             :     ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
     774        3063 :     elements = isolate->factory()->NewFixedDoubleArray(constants_length);
     775             :     // We are copying from non-fast-double to fast-double.
     776             :     ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
     777        6126 :     accessor->CopyElements(fixed_array, from_kind, elements, constants_length);
     778             :   }
     779             : 
     780             :   // Remember both the literal's constant values as well as the ElementsKind.
     781             :   Handle<ConstantElementsPair> literals =
     782      293194 :       isolate->factory()->NewConstantElementsPair(kind, elements);
     783             : 
     784      293194 :   constant_elements_ = literals;
     785             : }
     786             : 
     787      445571 : bool ArrayLiteral::IsFastCloningSupported() const {
     788      445571 :   return depth() <= 1 &&
     789      219984 :          values()->length() <=
     790      225587 :              ConstructorBuiltins::kMaximumClonedShallowArrayElements;
     791             : }
     792             : 
     793        3324 : void ArrayLiteral::RewindSpreads() {
     794        3324 :   values_->Rewind(first_spread_index_);
     795        3324 :   first_spread_index_ = -1;
     796        3324 : }
     797             : 
     798      309216 : void ArrayLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     799             :                                        LanguageMode language_mode,
     800    11315557 :                                        FeedbackSlotCache* cache) {
     801             :   MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, cache);
     802             : 
     803             :   // This logic that computes the number of slots needed for vector store
     804             :   // ics must mirror FullCodeGenerator::VisitArrayLiteral.
     805    22631114 :   for (int array_index = 0; array_index < values()->length(); array_index++) {
     806    11088536 :     Expression* subexpr = values()->at(array_index);
     807             :     DCHECK(!subexpr->IsSpread());
     808    11088536 :     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
     809             : 
     810             :     // We'll reuse the same literal slot for all of the non-constant
     811             :     // subexpressions that use a keyed store IC.
     812       82195 :     literal_slot_ = spec->AddKeyedStoreICSlot(language_mode);
     813      391411 :     return;
     814             :   }
     815             : }
     816             : 
     817             : 
     818    14049373 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
     819             :                                                         Isolate* isolate) {
     820    14049374 :   if (expression->IsLiteral()) {
     821    25669680 :     return expression->AsLiteral()->value();
     822             :   }
     823     1214534 :   if (CompileTimeValue::IsCompileTimeValue(expression)) {
     824      294850 :     return CompileTimeValue::GetValue(isolate, expression);
     825             :   }
     826      919684 :   return isolate->factory()->uninitialized_value();
     827             : }
     828             : 
     829      352137 : void MaterializedLiteral::InitDepthAndFlags() {
     830      352137 :   if (IsArrayLiteral()) {
     831      146062 :     return AsArrayLiteral()->InitDepthAndFlags();
     832             :   }
     833      279106 :   if (IsObjectLiteral()) {
     834      546686 :     return AsObjectLiteral()->InitDepthAndFlags();
     835             :   }
     836             :   DCHECK(IsRegExpLiteral());
     837             :   DCHECK_LE(1, depth());  // Depth should be initialized.
     838             : }
     839             : 
     840      347680 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
     841      347680 :   if (IsArrayLiteral()) {
     842      143432 :     return AsArrayLiteral()->BuildConstantElements(isolate);
     843             :   }
     844      275964 :   if (IsObjectLiteral()) {
     845      540448 :     return AsObjectLiteral()->BuildConstantProperties(isolate);
     846             :   }
     847             :   DCHECK(IsRegExpLiteral());
     848             : }
     849             : 
     850             : 
     851      186448 : void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
     852             :   // TODO(olivf) If this Operation is used in a test context, then the
     853             :   // expression has a ToBoolean stub and we want to collect the type
     854             :   // information. However the GraphBuilder expects it to be on the instruction
     855             :   // corresponding to the TestContext, therefore we have to store it here and
     856             :   // not on the operand.
     857      186448 :   set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
     858      186448 : }
     859             : 
     860             : 
     861      149557 : void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
     862             :   // TODO(olivf) If this Operation is used in a test context, then the right
     863             :   // hand side has a ToBoolean stub and we want to collect the type information.
     864             :   // However the GraphBuilder expects it to be on the instruction corresponding
     865             :   // to the TestContext, therefore we have to store it here and not on the
     866             :   // right hand operand.
     867      149557 :   set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
     868      149557 : }
     869             : 
     870     3750940 : void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     871             :                                           LanguageMode language_mode,
     872     3750940 :                                           FeedbackSlotCache* cache) {
     873             :   // Feedback vector slot is only used by interpreter for binary operations.
     874             :   // Full-codegen uses AstId to record type feedback.
     875     3750940 :   switch (op()) {
     876             :     // Comma, logical_or and logical_and do not collect type feedback.
     877             :     case Token::COMMA:
     878             :     case Token::AND:
     879             :     case Token::OR:
     880             :       return;
     881             :     default:
     882     2774743 :       feedback_slot_ = spec->AddInterpreterBinaryOpICSlot();
     883     2774743 :       return;
     884             :   }
     885             : }
     886             : 
     887             : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
     888             :   // Add is not commutative due to potential for string addition.
     889      639108 :   return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
     890             :          op == Token::BIT_XOR;
     891             : }
     892             : 
     893             : // Check for the pattern: x + 1.
     894     1014905 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
     895             :                                      Expression** expr, Smi** literal) {
     896     1014905 :   if (right->IsSmiLiteral()) {
     897      307542 :     *expr = left;
     898      615084 :     *literal = right->AsLiteral()->AsSmiLiteral();
     899      307542 :     return true;
     900             :   }
     901             :   return false;
     902             : }
     903             : 
     904      931383 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
     905      639108 :                                             Smi** literal) {
     906     1570491 :   return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
     907       83522 :          (IsCommutativeOperationWithSmiLiteral(op()) &&
     908     1014904 :           MatchSmiLiteralOperation(right_, left_, subexpr, literal));
     909             : }
     910             : 
     911     4294358 : static bool IsTypeof(Expression* expr) {
     912     4782472 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     913     4782473 :   return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
     914             : }
     915             : 
     916     2302959 : void CompareOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
     917             :                                            LanguageMode language_mode,
     918     2302959 :                                            FeedbackSlotCache* cache_) {
     919             :   // Feedback vector slot is only used by interpreter for binary operations.
     920             :   // Full-codegen uses AstId to record type feedback.
     921     2302959 :   switch (op()) {
     922             :     // instanceof and in do not collect type feedback.
     923             :     case Token::INSTANCEOF:
     924             :     case Token::IN:
     925     2302959 :       return;
     926             :     default:
     927     2261572 :       feedback_slot_ = spec->AddInterpreterCompareICSlot();
     928             :   }
     929             : }
     930             : 
     931             : // Check for the pattern: typeof <expression> equals <string literal>.
     932     4294359 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
     933             :                                       Expression* right, Expression** expr,
     934             :                                       Literal** literal) {
     935     4580349 :   if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
     936      571980 :     *expr = left->AsUnaryOperation()->expression();
     937      571980 :     *literal = right->AsLiteral();
     938      285990 :     return true;
     939             :   }
     940             :   return false;
     941             : }
     942             : 
     943     2290124 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
     944     4294361 :                                               Literal** literal) {
     945     6584485 :   return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
     946     6298597 :          MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
     947             : }
     948             : 
     949             : 
     950     4006424 : static bool IsVoidOfLiteral(Expression* expr) {
     951     4320709 :   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
     952      201469 :   return maybe_unary != NULL &&
     953     4119240 :       maybe_unary->op() == Token::VOID &&
     954     4006424 :       maybe_unary->expression()->IsLiteral();
     955             : }
     956             : 
     957             : 
     958             : // Check for the pattern: void <literal> equals <expression> or
     959             : // undefined equals <expression>
     960     4006424 : static bool MatchLiteralCompareUndefined(Expression* left,
     961             :                                          Token::Value op,
     962             :                                          Expression* right,
     963             :                                          Expression** expr) {
     964     4119232 :   if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
     965      111420 :     *expr = right;
     966      111420 :     return true;
     967             :   }
     968     3942267 :   if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
     969       47191 :     *expr = right;
     970       47191 :     return true;
     971             :   }
     972             :   return false;
     973             : }
     974             : 
     975     6010558 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
     976     6010557 :   return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
     977     6008716 :          MatchLiteralCompareUndefined(right_, op(), left_, expr);
     978             : }
     979             : 
     980             : 
     981             : // Check for the pattern: null equals <expression>
     982     3689852 : static bool MatchLiteralCompareNull(Expression* left,
     983             :                                     Token::Value op,
     984             :                                     Expression* right,
     985             :                                     Expression** expr) {
     986     3794824 :   if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
     987      103523 :     *expr = right;
     988      103523 :     return true;
     989             :   }
     990             :   return false;
     991             : }
     992             : 
     993             : 
     994     5535373 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
     995     5535374 :   return MatchLiteralCompareNull(left_, op(), right_, expr) ||
     996     5534184 :          MatchLiteralCompareNull(right_, op(), left_, expr);
     997             : }
     998             : 
     999             : 
    1000             : // ----------------------------------------------------------------------------
    1001             : // Recording of type feedback
    1002             : 
    1003             : // TODO(rossberg): all RecordTypeFeedback functions should disappear
    1004             : // once we use the common type field in the AST consistently.
    1005             : 
    1006     1357149 : void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
    1007     1357149 :   if (IsUnaryOperation()) {
    1008      372896 :     AsUnaryOperation()->RecordToBooleanTypeFeedback(oracle);
    1009     1170701 :   } else if (IsBinaryOperation()) {
    1010      299114 :     AsBinaryOperation()->RecordToBooleanTypeFeedback(oracle);
    1011             :   } else {
    1012     1021144 :     set_to_boolean_types(oracle->ToBooleanTypes(test_id()));
    1013             :   }
    1014     1357149 : }
    1015             : 
    1016      805234 : SmallMapList* Expression::GetReceiverTypes() {
    1017     1610468 :   switch (node_type()) {
    1018             : #define NODE_LIST(V)    \
    1019             :   PROPERTY_NODE_LIST(V) \
    1020             :   V(Call)
    1021             : #define GENERATE_CASE(Node) \
    1022             :   case k##Node:             \
    1023             :     return static_cast<Node*>(this)->GetReceiverTypes();
    1024       72372 :     NODE_LIST(GENERATE_CASE)
    1025             : #undef NODE_LIST
    1026             : #undef GENERATE_CASE
    1027             :     default:
    1028           0 :       UNREACHABLE();
    1029             :       return nullptr;
    1030             :   }
    1031             : }
    1032             : 
    1033       24584 : KeyedAccessStoreMode Expression::GetStoreMode() const {
    1034       49168 :   switch (node_type()) {
    1035             : #define GENERATE_CASE(Node) \
    1036             :   case k##Node:             \
    1037             :     return static_cast<const Node*>(this)->GetStoreMode();
    1038        5235 :     PROPERTY_NODE_LIST(GENERATE_CASE)
    1039             : #undef GENERATE_CASE
    1040             :     default:
    1041           0 :       UNREACHABLE();
    1042             :       return STANDARD_STORE;
    1043             :   }
    1044             : }
    1045             : 
    1046      107304 : IcCheckType Expression::GetKeyType() const {
    1047      214608 :   switch (node_type()) {
    1048             : #define GENERATE_CASE(Node) \
    1049             :   case k##Node:             \
    1050             :     return static_cast<const Node*>(this)->GetKeyType();
    1051      107304 :     PROPERTY_NODE_LIST(GENERATE_CASE)
    1052             : #undef GENERATE_CASE
    1053             :     default:
    1054           0 :       UNREACHABLE();
    1055             :       return PROPERTY;
    1056             :   }
    1057             : }
    1058             : 
    1059      805234 : bool Expression::IsMonomorphic() const {
    1060     1610468 :   switch (node_type()) {
    1061             : #define GENERATE_CASE(Node) \
    1062             :   case k##Node:             \
    1063             :     return static_cast<const Node*>(this)->IsMonomorphic();
    1064      596745 :     PROPERTY_NODE_LIST(GENERATE_CASE)
    1065      208489 :     CALL_NODE_LIST(GENERATE_CASE)
    1066             : #undef GENERATE_CASE
    1067             :     default:
    1068           0 :       UNREACHABLE();
    1069             :       return false;
    1070             :   }
    1071             : }
    1072             : 
    1073     4171566 : void Call::AssignFeedbackSlots(FeedbackVectorSpec* spec,
    1074             :                                LanguageMode language_mode,
    1075             :                                FeedbackSlotCache* cache) {
    1076     4171578 :   ic_slot_ = spec->AddCallICSlot();
    1077     4171578 : }
    1078             : 
    1079     8293366 : Call::CallType Call::GetCallType() const {
    1080     5550055 :   VariableProxy* proxy = expression()->AsVariableProxy();
    1081     3575407 :   if (proxy != NULL) {
    1082     1974658 :     if (proxy->var()->IsUnallocated()) {
    1083             :       return GLOBAL_CALL;
    1084      995659 :     } else if (proxy->var()->IsLookupSlot()) {
    1085             :       // Calls going through 'with' always use DYNAMIC rather than DYNAMIC_LOCAL
    1086             :       // or DYNAMIC_GLOBAL.
    1087      235371 :       return proxy->var()->mode() == DYNAMIC ? WITH_CALL : OTHER_CALL;
    1088             :     }
    1089             :   }
    1090             : 
    1091     4722070 :   if (expression()->IsSuperCallReference()) return SUPER_CALL;
    1092             : 
    1093     3824035 :   Property* property = expression()->AsProperty();
    1094     2356938 :   if (property != nullptr) {
    1095     1467102 :     bool is_super = property->IsSuperAccess();
    1096     1467103 :     if (property->key()->IsPropertyName()) {
    1097     1457934 :       return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
    1098             :     } else {
    1099        9169 :       return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
    1100             :     }
    1101             :   }
    1102             : 
    1103             :   return OTHER_CALL;
    1104             : }
    1105             : 
    1106      535223 : CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
    1107             :                        int pos)
    1108             :     : Expression(pos, kCaseClause),
    1109             :       label_(label),
    1110             :       statements_(statements),
    1111     1605669 :       compare_type_(AstType::None()) {}
    1112             : 
    1113      243390 : void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec,
    1114             :                                      LanguageMode language_mode,
    1115             :                                      FeedbackSlotCache* cache) {
    1116      243390 :   feedback_slot_ = spec->AddInterpreterCompareICSlot();
    1117      243390 : }
    1118             : 
    1119     2537594 : uint32_t Literal::Hash() {
    1120     2537594 :   return raw_value()->IsString()
    1121     2521441 :              ? raw_value()->AsString()->hash()
    1122     5091341 :              : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
    1123             : }
    1124             : 
    1125             : 
    1126             : // static
    1127       99854 : bool Literal::Match(void* literal1, void* literal2) {
    1128       99854 :   const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
    1129       99126 :   const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
    1130      298834 :   return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) ||
    1131         728 :          (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
    1132             : }
    1133             : 
    1134           0 : const char* CallRuntime::debug_name() {
    1135             : #ifdef DEBUG
    1136             :   return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
    1137             :                         : function_->name;
    1138             : #else
    1139           0 :   return is_jsruntime() ? "(context function)" : function_->name;
    1140             : #endif  // DEBUG
    1141             : }
    1142             : 
    1143             : }  // namespace internal
    1144             : }  // namespace v8

Generated by: LCOV version 1.10