LCOV - code coverage report
Current view: top level - src - type-info.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 214 229 93.4 %
Date: 2017-04-26 Functions: 35 36 97.2 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/type-info.h"
       6             : 
       7             : #include "src/assembler-inl.h"
       8             : #include "src/ast/ast.h"
       9             : #include "src/code-stubs.h"
      10             : #include "src/ic/ic.h"
      11             : #include "src/ic/stub-cache.h"
      12             : #include "src/objects-inl.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17      371311 : TypeFeedbackOracle::TypeFeedbackOracle(Isolate* isolate, Zone* zone,
      18             :                                        Handle<Code> code,
      19             :                                        Handle<FeedbackVector> feedback_vector,
      20             :                                        Handle<Context> native_context)
      21      371311 :     : native_context_(native_context), isolate_(isolate), zone_(zone) {
      22      371311 :   BuildDictionary(code);
      23             :   DCHECK(dictionary_->IsUnseededNumberDictionary());
      24             :   // We make a copy of the feedback vector because a GC could clear
      25             :   // the type feedback info contained therein.
      26             :   // TODO(mvstanton): revisit the decision to copy when we weakly
      27             :   // traverse the feedback vector at GC time.
      28      371311 :   feedback_vector_ = FeedbackVector::Copy(isolate, feedback_vector);
      29      371311 : }
      30             : 
      31             : 
      32             : static uint32_t IdToKey(TypeFeedbackId ast_id) {
      33     3463095 :   return static_cast<uint32_t>(ast_id.ToInt());
      34             : }
      35             : 
      36             : 
      37     4900086 : Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) {
      38             :   int entry = dictionary_->FindEntry(IdToKey(ast_id));
      39     2450043 :   if (entry != UnseededNumberDictionary::kNotFound) {
      40     1086197 :     Object* value = dictionary_->ValueAt(entry);
      41     1086197 :     if (value->IsCell()) {
      42             :       Cell* cell = Cell::cast(value);
      43           0 :       return Handle<Object>(cell->value(), isolate());
      44             :     } else {
      45     1086197 :       return Handle<Object>(value, isolate());
      46             :     }
      47             :   }
      48             :   return Handle<Object>::cast(isolate()->factory()->undefined_value());
      49             : }
      50             : 
      51     2638496 : Handle<Object> TypeFeedbackOracle::GetInfo(FeedbackSlot slot) {
      52             :   DCHECK(slot.ToInt() >= 0 && slot.ToInt() < feedback_vector_->length());
      53             :   Handle<Object> undefined =
      54             :       Handle<Object>::cast(isolate()->factory()->undefined_value());
      55             :   Object* obj = feedback_vector_->Get(slot);
      56             : 
      57             :   // Slots do not embed direct pointers to maps, functions. Instead
      58             :   // a WeakCell is always used.
      59     1319263 :   if (obj->IsWeakCell()) {
      60             :     WeakCell* cell = WeakCell::cast(obj);
      61      363188 :     if (cell->cleared()) return undefined;
      62             :     obj = cell->value();
      63             :   }
      64             : 
      65     3229300 :   if (obj->IsJSFunction() || obj->IsAllocationSite() || obj->IsSymbol()) {
      66     1319233 :     return Handle<Object>(obj, isolate());
      67             :   }
      68             : 
      69           0 :   return undefined;
      70             : }
      71             : 
      72      604009 : InlineCacheState TypeFeedbackOracle::LoadInlineCacheState(FeedbackSlot slot) {
      73      604009 :   if (!slot.IsInvalid()) {
      74      531296 :     FeedbackSlotKind kind = feedback_vector_->GetKind(slot);
      75      531296 :     if (IsLoadICKind(kind)) {
      76             :       LoadICNexus nexus(feedback_vector_, slot);
      77      436517 :       return nexus.StateFromFeedback();
      78       94779 :     } else if (IsKeyedLoadICKind(kind)) {
      79             :       KeyedLoadICNexus nexus(feedback_vector_, slot);
      80       94779 :       return nexus.StateFromFeedback();
      81             :     }
      82             :   }
      83             : 
      84             :   // If we can't find an IC, assume we've seen *something*, but we don't know
      85             :   // what. PREMONOMORPHIC roughly encodes this meaning.
      86             :   return PREMONOMORPHIC;
      87             : }
      88             : 
      89       73045 : bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackSlot slot) {
      90       73045 :   if (!slot.IsInvalid()) {
      91       73045 :     FeedbackSlotKind kind = feedback_vector_->GetKind(slot);
      92       88910 :     if (IsStoreICKind(kind) || IsStoreGlobalICKind(kind)) {
      93             :       StoreICNexus nexus(feedback_vector_, slot);
      94       57180 :       return nexus.StateFromFeedback() == UNINITIALIZED;
      95       15865 :     } else if (IsKeyedStoreICKind(kind)) {
      96             :       KeyedStoreICNexus nexus(feedback_vector_, slot);
      97       15865 :       return nexus.StateFromFeedback() == UNINITIALIZED;
      98             :     }
      99             :   }
     100             :   return true;
     101             : }
     102             : 
     103     1968321 : bool TypeFeedbackOracle::CallIsUninitialized(FeedbackSlot slot) {
     104      656112 :   Handle<Object> value = GetInfo(slot);
     105     1312209 :   return value->IsUndefined(isolate()) ||
     106             :          value.is_identical_to(
     107      656112 :              FeedbackVector::UninitializedSentinel(isolate()));
     108             : }
     109             : 
     110      446351 : bool TypeFeedbackOracle::CallIsMonomorphic(FeedbackSlot slot) {
     111      446351 :   Handle<Object> value = GetInfo(slot);
     112      892593 :   return value->IsAllocationSite() || value->IsJSFunction();
     113             : }
     114             : 
     115       32299 : bool TypeFeedbackOracle::CallNewIsMonomorphic(FeedbackSlot slot) {
     116       32299 :   Handle<Object> info = GetInfo(slot);
     117       64049 :   return info->IsAllocationSite() || info->IsJSFunction();
     118             : }
     119             : 
     120        2280 : byte TypeFeedbackOracle::ForInType(FeedbackSlot feedback_vector_slot) {
     121        1140 :   Handle<Object> value = GetInfo(feedback_vector_slot);
     122             :   return value.is_identical_to(FeedbackVector::UninitializedSentinel(isolate()))
     123             :              ? ForInStatement::FAST_FOR_IN
     124        1140 :              : ForInStatement::SLOW_FOR_IN;
     125             : }
     126             : 
     127       50955 : void TypeFeedbackOracle::GetStoreModeAndKeyType(
     128             :     FeedbackSlot slot, KeyedAccessStoreMode* store_mode,
     129             :     IcCheckType* key_type) {
     130       61378 :   if (!slot.IsInvalid() && feedback_vector_->IsKeyedStoreIC(slot)) {
     131             :     KeyedStoreICNexus nexus(feedback_vector_, slot);
     132        5219 :     *store_mode = nexus.GetKeyedAccessStoreMode();
     133        5219 :     *key_type = nexus.GetKeyType();
     134             :   } else {
     135       45736 :     *store_mode = STANDARD_STORE;
     136       45736 :     *key_type = ELEMENT;
     137             :   }
     138       50955 : }
     139             : 
     140       73134 : Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(FeedbackSlot slot) {
     141       73025 :   Handle<Object> info = GetInfo(slot);
     142       73025 :   if (info->IsAllocationSite()) {
     143         218 :     return Handle<JSFunction>(isolate()->native_context()->array_function());
     144             :   }
     145             : 
     146             :   return Handle<JSFunction>::cast(info);
     147             : }
     148             : 
     149        5561 : Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(FeedbackSlot slot) {
     150        5012 :   Handle<Object> info = GetInfo(slot);
     151        5012 :   if (info->IsJSFunction()) {
     152             :     return Handle<JSFunction>::cast(info);
     153             :   }
     154             : 
     155             :   DCHECK(info->IsAllocationSite());
     156        1098 :   return Handle<JSFunction>(isolate()->native_context()->array_function());
     157             : }
     158             : 
     159       73025 : Handle<AllocationSite> TypeFeedbackOracle::GetCallAllocationSite(
     160             :     FeedbackSlot slot) {
     161       73025 :   Handle<Object> info = GetInfo(slot);
     162       73025 :   if (info->IsAllocationSite()) {
     163             :     return Handle<AllocationSite>::cast(info);
     164             :   }
     165             :   return Handle<AllocationSite>::null();
     166             : }
     167             : 
     168       32299 : Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(
     169             :     FeedbackSlot slot) {
     170       32299 :   Handle<Object> info = GetInfo(slot);
     171       32299 :   if (info->IsAllocationSite()) {
     172             :     return Handle<AllocationSite>::cast(info);
     173             :   }
     174             :   return Handle<AllocationSite>::null();
     175             : }
     176             : 
     177             : namespace {
     178             : 
     179      448214 : AstType* CompareOpHintToType(CompareOperationHint hint) {
     180      448214 :   switch (hint) {
     181             :     case CompareOperationHint::kNone:
     182             :       return AstType::None();
     183             :     case CompareOperationHint::kSignedSmall:
     184         447 :       return AstType::SignedSmall();
     185             :     case CompareOperationHint::kNumber:
     186           0 :       return AstType::Number();
     187             :     case CompareOperationHint::kNumberOrOddball:
     188           0 :       return AstType::NumberOrOddball();
     189             :     case CompareOperationHint::kInternalizedString:
     190           2 :       return AstType::InternalizedString();
     191             :     case CompareOperationHint::kString:
     192           0 :       return AstType::String();
     193             :     case CompareOperationHint::kReceiver:
     194           0 :       return AstType::Receiver();
     195             :     case CompareOperationHint::kAny:
     196           0 :       return AstType::Any();
     197             :   }
     198           0 :   UNREACHABLE();
     199             :   return AstType::None();
     200             : }
     201             : 
     202      428387 : AstType* BinaryOpFeedbackToType(int hint) {
     203      428387 :   switch (hint) {
     204             :     case BinaryOperationFeedback::kNone:
     205             :       return AstType::None();
     206             :     case BinaryOperationFeedback::kSignedSmall:
     207         670 :       return AstType::SignedSmall();
     208             :     case BinaryOperationFeedback::kNumber:
     209           0 :       return AstType::Number();
     210             :     case BinaryOperationFeedback::kString:
     211         792 :       return AstType::String();
     212             :     case BinaryOperationFeedback::kNumberOrOddball:
     213           0 :       return AstType::NumberOrOddball();
     214             :     case BinaryOperationFeedback::kAny:
     215             :     default:
     216           0 :       return AstType::Any();
     217             :   }
     218             :   UNREACHABLE();
     219             :   return AstType::None();
     220             : }
     221             : 
     222             : }  // end anonymous namespace
     223             : 
     224      535012 : void TypeFeedbackOracle::CompareType(TypeFeedbackId id, FeedbackSlot slot,
     225             :                                      AstType** left_type, AstType** right_type,
     226     2228417 :                                      AstType** combined_type) {
     227      535012 :   Handle<Object> info = GetInfo(id);
     228             :   // A check for a valid slot is not sufficient here. InstanceOf collects
     229             :   // type feedback in a General slot.
     230      535012 :   if (!info->IsCode()) {
     231             :     // For some comparisons we don't have type feedback, e.g.
     232             :     // LiteralCompareTypeof.
     233       86798 :     *left_type = *right_type = *combined_type = AstType::None();
     234      621810 :     return;
     235             :   }
     236             : 
     237             :   // Feedback from Ignition. The feedback slot will be allocated and initialized
     238             :   // to AstType::None() even when ignition is not enabled. So it is safe to get
     239             :   // feedback from the type feedback vector.
     240             :   DCHECK(!slot.IsInvalid());
     241             :   CompareICNexus nexus(feedback_vector_, slot);
     242             :   *left_type = *right_type = *combined_type =
     243      448214 :       CompareOpHintToType(nexus.GetCompareOperationFeedback());
     244             : 
     245             :   // Merge the feedback from full-codegen if available.
     246             :   Handle<Code> code = Handle<Code>::cast(info);
     247             :   Handle<Map> map;
     248      448214 :   Map* raw_map = code->FindFirstMap();
     249      554988 :   if (raw_map != NULL) Map::TryUpdate(handle(raw_map)).ToHandle(&map);
     250             : 
     251      448214 :   if (code->is_compare_ic_stub()) {
     252             :     CompareICStub stub(code->stub_key(), isolate());
     253             :     AstType* left_type_from_ic =
     254      448214 :         CompareICState::StateToType(zone(), stub.left());
     255             :     AstType* right_type_from_ic =
     256      448214 :         CompareICState::StateToType(zone(), stub.right());
     257             :     AstType* combined_type_from_ic =
     258      448214 :         CompareICState::StateToType(zone(), stub.state(), map);
     259             :     // Full-codegen collects lhs and rhs feedback seperately and Crankshaft
     260             :     // could use this information to optimize better. So if combining the
     261             :     // feedback has made the feedback less precise, we should use the feedback
     262             :     // only from Full-codegen. If the union of the feedback from Full-codegen
     263             :     // is same as that of Ignition, there is no need to combine feedback from
     264             :     // from Ignition.
     265             :     AstType* combined_type_from_fcg = AstType::Union(
     266             :         left_type_from_ic,
     267             :         AstType::Union(right_type_from_ic, combined_type_from_ic, zone()),
     268      448214 :         zone());
     269      448214 :     if (combined_type_from_fcg == *left_type) {
     270             :       // Full-codegen collects information about lhs, rhs and result types
     271             :       // seperately. So just retain that information.
     272      303027 :       *left_type = left_type_from_ic;
     273      303027 :       *right_type = right_type_from_ic;
     274      303027 :       *combined_type = combined_type_from_ic;
     275             :     } else {
     276             :       // Combine Ignition and Full-codegen feedbacks.
     277      145187 :       *left_type = AstType::Union(*left_type, left_type_from_ic, zone());
     278      145187 :       *right_type = AstType::Union(*right_type, right_type_from_ic, zone());
     279             :       *combined_type =
     280      145187 :           AstType::Union(*combined_type, combined_type_from_ic, zone());
     281             :     }
     282             :   }
     283             : }
     284             : 
     285      511901 : void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, FeedbackSlot slot,
     286             :                                     AstType** left, AstType** right,
     287             :                                     AstType** result,
     288             :                                     Maybe<int>* fixed_right_arg,
     289             :                                     Handle<AllocationSite>* allocation_site,
     290     1654333 :                                     Token::Value op) {
     291      511901 :   Handle<Object> object = GetInfo(id);
     292      511901 :   if (slot.IsInvalid()) {
     293             :     // For some binary ops we don't have ICs or feedback slots,
     294             :     // e.g. Token::COMMA, but for the operations covered by the BinaryOpIC we
     295             :     // should always have them.
     296             :     DCHECK(!object->IsCode());
     297             :     DCHECK(op < BinaryOpICState::FIRST_TOKEN ||
     298             :            op > BinaryOpICState::LAST_TOKEN);
     299      129495 :     *left = *right = *result = AstType::None();
     300      129495 :     *fixed_right_arg = Nothing<int>();
     301      129495 :     *allocation_site = Handle<AllocationSite>::null();
     302      258990 :     return;
     303             :   }
     304             : 
     305             :   // Feedback from Ignition. The feedback slot will be allocated and initialized
     306             :   // to AstType::None() even when ignition is not enabled. So it is safe to get
     307             :   // feedback from the type feedback vector.
     308             :   DCHECK(!slot.IsInvalid());
     309             :   BinaryOpICNexus nexus(feedback_vector_, slot);
     310             :   *left = *right = *result =
     311      764812 :       BinaryOpFeedbackToType(Smi::cast(nexus.GetFeedback())->value());
     312      382406 :   *fixed_right_arg = Nothing<int>();
     313      382406 :   *allocation_site = Handle<AllocationSite>::null();
     314             : 
     315      382406 :   if (!object->IsCode()) return;
     316             : 
     317             :   // Merge the feedback from full-codegen if available.
     318             :   Handle<Code> code = Handle<Code>::cast(object);
     319             :   DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
     320      382406 :   BinaryOpICState state(isolate(), code->extra_ic_state());
     321             :   DCHECK_EQ(op, state.op());
     322             : 
     323             :   // Full-codegen collects lhs and rhs feedback seperately and Crankshaft
     324             :   // could use this information to optimize better. So if combining the
     325             :   // feedback has made the feedback less precise, we should use the feedback
     326             :   // only from Full-codegen. If the union of the feedback from Full-codegen
     327             :   // is same as that of Ignition, there is no need to combine feedback from
     328             :   // from Ignition.
     329             :   AstType* combined_type_from_fcg = AstType::Union(
     330             :       state.GetLeftType(),
     331             :       AstType::Union(state.GetRightType(), state.GetResultType(), zone()),
     332     1147218 :       zone());
     333      382406 :   if (combined_type_from_fcg == *left) {
     334             :     // Full-codegen collects information about lhs, rhs and result types
     335             :     // seperately. So just retain that information.
     336      171798 :     *left = state.GetLeftType();
     337      171798 :     *right = state.GetRightType();
     338       85899 :     *result = state.GetResultType();
     339             :   } else {
     340             :     // Combine Ignition and Full-codegen feedback.
     341      593014 :     *left = AstType::Union(*left, state.GetLeftType(), zone());
     342      593014 :     *right = AstType::Union(*right, state.GetRightType(), zone());
     343      296507 :     *result = AstType::Union(*result, state.GetResultType(), zone());
     344             :   }
     345             :   // Ignition does not collect this feedback.
     346      382406 :   *fixed_right_arg = state.fixed_right_arg();
     347             : 
     348      382406 :   AllocationSite* first_allocation_site = code->FindFirstAllocationSite();
     349      382406 :   if (first_allocation_site != NULL) {
     350       22603 :     *allocation_site = handle(first_allocation_site);
     351             :   } else {
     352      359803 :     *allocation_site = Handle<AllocationSite>::null();
     353             :   }
     354             : }
     355             : 
     356      137943 : AstType* TypeFeedbackOracle::CountType(TypeFeedbackId id, FeedbackSlot slot) {
     357       45981 :   Handle<Object> object = GetInfo(id);
     358       45981 :   if (slot.IsInvalid()) {
     359             :     DCHECK(!object->IsCode());
     360             :     return AstType::None();
     361             :   }
     362             : 
     363             :   DCHECK(!slot.IsInvalid());
     364             :   BinaryOpICNexus nexus(feedback_vector_, slot);
     365             :   AstType* type =
     366       91962 :       BinaryOpFeedbackToType(Smi::cast(nexus.GetFeedback())->value());
     367             : 
     368       45981 :   if (!object->IsCode()) return type;
     369             : 
     370             :   Handle<Code> code = Handle<Code>::cast(object);
     371             :   DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
     372       45981 :   BinaryOpICState state(isolate(), code->extra_ic_state());
     373       91962 :   return AstType::Union(type, state.GetLeftType(), zone());
     374             : }
     375             : 
     376             : 
     377       24524 : bool TypeFeedbackOracle::HasOnlyStringMaps(SmallMapList* receiver_types) {
     378       24524 :   bool all_strings = receiver_types->length() > 0;
     379       91318 :   for (int i = 0; i < receiver_types->length(); i++) {
     380       21135 :     all_strings &= receiver_types->at(i)->IsStringMap();
     381             :   }
     382       24524 :   return all_strings;
     383             : }
     384             : 
     385      329966 : void TypeFeedbackOracle::PropertyReceiverTypes(FeedbackSlot slot,
     386             :                                                Handle<Name> name,
     387      272886 :                                                SmallMapList* receiver_types) {
     388             :   receiver_types->Clear();
     389      329966 :   if (!slot.IsInvalid()) {
     390             :     LoadICNexus nexus(feedback_vector_, slot);
     391             :     CollectReceiverTypes(isolate()->load_stub_cache(), &nexus, name,
     392      272886 :                          receiver_types);
     393             :   }
     394      329966 : }
     395             : 
     396       40157 : void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
     397             :     FeedbackSlot slot, SmallMapList* receiver_types, bool* is_string,
     398             :     IcCheckType* key_type) {
     399             :   receiver_types->Clear();
     400       40157 :   if (slot.IsInvalid()) {
     401       15633 :     *is_string = false;
     402       15633 :     *key_type = ELEMENT;
     403             :   } else {
     404             :     KeyedLoadICNexus nexus(feedback_vector_, slot);
     405       24524 :     CollectReceiverTypes(&nexus, receiver_types);
     406       24524 :     *is_string = HasOnlyStringMaps(receiver_types);
     407       24524 :     *key_type = nexus.GetKeyType();
     408             :   }
     409       40157 : }
     410             : 
     411       13269 : void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackSlot slot,
     412             :                                                  Handle<Name> name,
     413       13269 :                                                  SmallMapList* receiver_types) {
     414             :   receiver_types->Clear();
     415             :   CollectReceiverTypes(isolate()->store_stub_cache(), slot, name,
     416       13269 :                        receiver_types);
     417       13269 : }
     418             : 
     419        4974 : void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
     420             :     FeedbackSlot slot, SmallMapList* receiver_types,
     421             :     KeyedAccessStoreMode* store_mode, IcCheckType* key_type) {
     422             :   receiver_types->Clear();
     423        4974 :   CollectReceiverTypes(slot, receiver_types);
     424        4974 :   GetStoreModeAndKeyType(slot, store_mode, key_type);
     425        4974 : }
     426             : 
     427       45981 : void TypeFeedbackOracle::CountReceiverTypes(FeedbackSlot slot,
     428             :                                             SmallMapList* receiver_types) {
     429             :   receiver_types->Clear();
     430       45981 :   if (!slot.IsInvalid()) CollectReceiverTypes(slot, receiver_types);
     431       45981 : }
     432             : 
     433       13269 : void TypeFeedbackOracle::CollectReceiverTypes(StubCache* stub_cache,
     434             :                                               FeedbackSlot slot,
     435             :                                               Handle<Name> name,
     436             :                                               SmallMapList* types) {
     437             :   StoreICNexus nexus(feedback_vector_, slot);
     438       13269 :   CollectReceiverTypes(stub_cache, &nexus, name, types);
     439       13269 : }
     440             : 
     441      286155 : void TypeFeedbackOracle::CollectReceiverTypes(StubCache* stub_cache,
     442             :                                               FeedbackNexus* nexus,
     443             :                                               Handle<Name> name,
     444           0 :                                               SmallMapList* types) {
     445      286155 :   if (FLAG_collect_megamorphic_maps_from_stub_cache &&
     446             :       nexus->ic_state() == MEGAMORPHIC) {
     447             :     types->Reserve(4, zone());
     448           0 :     stub_cache->CollectMatchingMaps(types, name, native_context_, zone());
     449             :   } else {
     450      286155 :     CollectReceiverTypes(nexus, types);
     451             :   }
     452      286155 : }
     453             : 
     454       35713 : void TypeFeedbackOracle::CollectReceiverTypes(FeedbackSlot slot,
     455             :                                               SmallMapList* types) {
     456       35713 :   FeedbackSlotKind kind = feedback_vector_->GetKind(slot);
     457       44782 :   if (IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
     458             :       IsStoreGlobalICKind(kind)) {
     459             :     StoreICNexus nexus(feedback_vector_, slot);
     460       30494 :     CollectReceiverTypes(&nexus, types);
     461             :   } else {
     462             :     DCHECK(IsKeyedStoreICKind(kind));
     463             :     KeyedStoreICNexus nexus(feedback_vector_, slot);
     464        5219 :     CollectReceiverTypes(&nexus, types);
     465             :   }
     466       35713 : }
     467             : 
     468      346392 : void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus,
     469      371951 :                                               SmallMapList* types) {
     470             :   MapHandleList maps;
     471      346392 :   if (nexus->ic_state() == MONOMORPHIC) {
     472      160083 :     Map* map = nexus->FindFirstMap();
     473      319568 :     if (map != NULL) maps.Add(handle(map));
     474      186309 :   } else if (nexus->ic_state() == POLYMORPHIC) {
     475             :     nexus->FindAllMaps(&maps);
     476             :   } else {
     477      346392 :     return;
     478             :   }
     479      175865 :   types->Reserve(maps.length(), zone());
     480      373268 :   for (int i = 0; i < maps.length(); i++) {
     481      197403 :     Handle<Map> map(maps.at(i));
     482      197403 :     if (IsRelevantFeedback(*map, *native_context_)) {
     483      196086 :       types->AddMapIfMissing(maps.at(i), zone());
     484             :     }
     485             :   }
     486             : }
     487             : 
     488             : 
     489     1357149 : uint16_t TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) {
     490     1357149 :   Handle<Object> object = GetInfo(id);
     491     2714298 :   return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
     492             : }
     493             : 
     494             : 
     495             : // Things are a bit tricky here: The iterator for the RelocInfos and the infos
     496             : // themselves are not GC-safe, so we first get all infos, then we create the
     497             : // dictionary (possibly triggering GC), and finally we relocate the collected
     498             : // infos before we process them.
     499      742622 : void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) {
     500             :   DisallowHeapAllocation no_allocation;
     501      371311 :   ZoneList<RelocInfo> infos(16, zone());
     502             :   HandleScope scope(isolate());
     503      371311 :   GetRelocInfos(code, &infos);
     504      371311 :   CreateDictionary(code, &infos);
     505      371311 :   ProcessRelocInfos(&infos);
     506             :   // Allocate handle in the parent scope.
     507      371311 :   dictionary_ = scope.CloseAndEscape(dictionary_);
     508      371311 : }
     509             : 
     510             : 
     511      371311 : void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code,
     512     1013052 :                                        ZoneList<RelocInfo>* infos) {
     513             :   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
     514     1384363 :   for (RelocIterator it(*code, mask); !it.done(); it.next()) {
     515             :     infos->Add(*it.rinfo(), zone());
     516             :   }
     517      371311 : }
     518             : 
     519             : 
     520      371311 : void TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
     521      371311 :                                           ZoneList<RelocInfo>* infos) {
     522             :   AllowHeapAllocation allocation_allowed;
     523             :   Code* old_code = *code;
     524      742622 :   dictionary_ = UnseededNumberDictionary::New(isolate(), infos->length());
     525             :   RelocateRelocInfos(infos, old_code, *code);
     526      371311 : }
     527             : 
     528             : 
     529           0 : void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos,
     530             :                                             Code* old_code,
     531             :                                             Code* new_code) {
     532     2397415 :   for (int i = 0; i < infos->length(); i++) {
     533     3410467 :     RelocInfo* info = &(*infos)[i];
     534             :     info->set_host(new_code);
     535     1013052 :     info->set_pc(new_code->instruction_start() +
     536     1013052 :                  (info->pc() - old_code->instruction_start()));
     537             :   }
     538           0 : }
     539             : 
     540             : 
     541      371311 : void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
     542     2768726 :   for (int i = 0; i < infos->length(); i++) {
     543     3410467 :     RelocInfo reloc_entry = (*infos)[i];
     544             :     Address target_address = reloc_entry.target_address();
     545             :     TypeFeedbackId ast_id =
     546     1013052 :         TypeFeedbackId(static_cast<unsigned>((*infos)[i].data()));
     547     1013052 :     Code* target = Code::GetCodeFromTargetAddress(target_address);
     548     1013052 :     switch (target->kind()) {
     549             :       case Code::LOAD_IC:
     550             :       case Code::STORE_IC:
     551             :       case Code::KEYED_LOAD_IC:
     552             :       case Code::KEYED_STORE_IC:
     553             :       case Code::BINARY_OP_IC:
     554             :       case Code::COMPARE_IC:
     555             :       case Code::TO_BOOLEAN_IC:
     556     1013052 :         SetInfo(ast_id, target);
     557     1013052 :         break;
     558             : 
     559             :       default:
     560             :         break;
     561             :     }
     562             :   }
     563      371311 : }
     564             : 
     565             : 
     566     1013052 : void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) {
     567             :   DCHECK(dictionary_->FindEntry(IdToKey(ast_id)) ==
     568             :          UnseededNumberDictionary::kNotFound);
     569             :   // Dictionary has been allocated with sufficient size for all elements.
     570             :   DisallowHeapAllocation no_need_to_resize_dictionary;
     571             :   HandleScope scope(isolate());
     572             :   USE(UnseededNumberDictionary::AtNumberPut(
     573     1013052 :       dictionary_, IdToKey(ast_id), handle(target, isolate())));
     574     1013052 : }
     575             : 
     576             : 
     577             : }  // namespace internal
     578             : }  // namespace v8

Generated by: LCOV version 1.10