blob: 5f5c1e87311661cb95c24bd6e27a05daa290f480 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/type-info.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +01006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/ast/ast.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/code-stubs.h"
9#include "src/compiler.h"
10#include "src/ic/ic.h"
11#include "src/ic/stub-cache.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/objects-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010013
Steve Blocka7e24c12009-10-30 11:49:00 +000014namespace v8 {
15namespace internal {
16
Steve Block6ded16b2010-05-10 14:33:55 +010017
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018TypeFeedbackOracle::TypeFeedbackOracle(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019 Isolate* isolate, Zone* zone, Handle<Code> code,
20 Handle<TypeFeedbackVector> feedback_vector, Handle<Context> native_context)
21 : native_context_(native_context), isolate_(isolate), zone_(zone) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000022 BuildDictionary(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023 DCHECK(dictionary_->IsDictionary());
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.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 feedback_vector_ = TypeFeedbackVector::Copy(isolate, feedback_vector);
Ben Murdochb0fe1622011-05-05 13:52:32 +010029}
30
31
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032static uint32_t IdToKey(TypeFeedbackId ast_id) {
33 return static_cast<uint32_t>(ast_id.ToInt());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010034}
35
36
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) {
38 int entry = dictionary_->FindEntry(IdToKey(ast_id));
39 if (entry != UnseededNumberDictionary::kNotFound) {
40 Object* value = dictionary_->ValueAt(entry);
41 if (value->IsCell()) {
42 Cell* cell = Cell::cast(value);
43 return Handle<Object>(cell->value(), isolate());
44 } else {
45 return Handle<Object>(value, isolate());
46 }
47 }
48 return Handle<Object>::cast(isolate()->factory()->undefined_value());
49}
50
51
Emily Bernierd0a1eb72015-03-24 16:35:39 -040052Handle<Object> TypeFeedbackOracle::GetInfo(FeedbackVectorSlot slot) {
53 DCHECK(slot.ToInt() >= 0 && slot.ToInt() < feedback_vector_->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 Handle<Object> undefined =
55 Handle<Object>::cast(isolate()->factory()->undefined_value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056 Object* obj = feedback_vector_->Get(slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057
58 // Slots do not embed direct pointers to maps, functions. Instead
59 // a WeakCell is always used.
60 if (obj->IsWeakCell()) {
61 WeakCell* cell = WeakCell::cast(obj);
62 if (cell->cleared()) return undefined;
63 obj = cell->value();
64 }
65
66 if (obj->IsJSFunction() || obj->IsAllocationSite() || obj->IsSymbol() ||
67 obj->IsSimd128Value()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040068 return Handle<Object>(obj, isolate());
69 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070
71 return undefined;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072}
73
74
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075InlineCacheState TypeFeedbackOracle::LoadInlineCacheState(
76 FeedbackVectorSlot slot) {
77 if (!slot.IsInvalid()) {
78 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot);
79 if (kind == FeedbackVectorSlotKind::LOAD_IC) {
80 LoadICNexus nexus(feedback_vector_, slot);
81 return nexus.StateFromFeedback();
82 } else if (kind == FeedbackVectorSlotKind::KEYED_LOAD_IC) {
83 KeyedLoadICNexus nexus(feedback_vector_, slot);
84 return nexus.StateFromFeedback();
85 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086 }
87
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 // If we can't find an IC, assume we've seen *something*, but we don't know
89 // what. PREMONOMORPHIC roughly encodes this meaning.
90 return PREMONOMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091}
92
93
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackVectorSlot slot) {
95 if (!slot.IsInvalid()) {
96 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot);
97 if (kind == FeedbackVectorSlotKind::STORE_IC) {
98 StoreICNexus nexus(feedback_vector_, slot);
99 return nexus.StateFromFeedback() == UNINITIALIZED;
100 } else if (kind == FeedbackVectorSlotKind::KEYED_STORE_IC) {
101 KeyedStoreICNexus nexus(feedback_vector_, slot);
102 return nexus.StateFromFeedback() == UNINITIALIZED;
103 }
104 }
105 return true;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100106}
107
108
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109bool TypeFeedbackOracle::CallIsUninitialized(FeedbackVectorSlot slot) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110 Handle<Object> value = GetInfo(slot);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100111 return value->IsUndefined(isolate()) ||
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112 value.is_identical_to(
113 TypeFeedbackVector::UninitializedSentinel(isolate()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000114}
115
116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117bool TypeFeedbackOracle::CallIsMonomorphic(FeedbackVectorSlot slot) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 Handle<Object> value = GetInfo(slot);
119 return value->IsAllocationSite() || value->IsJSFunction();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100120}
121
122
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123bool TypeFeedbackOracle::CallNewIsMonomorphic(FeedbackVectorSlot slot) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124 Handle<Object> info = GetInfo(slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 return info->IsAllocationSite() || info->IsJSFunction();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100126}
127
128
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400129byte TypeFeedbackOracle::ForInType(FeedbackVectorSlot feedback_vector_slot) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 Handle<Object> value = GetInfo(feedback_vector_slot);
131 return value.is_identical_to(
132 TypeFeedbackVector::UninitializedSentinel(isolate()))
133 ? ForInStatement::FAST_FOR_IN
134 : ForInStatement::SLOW_FOR_IN;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100135}
136
137
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400138void TypeFeedbackOracle::GetStoreModeAndKeyType(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 FeedbackVectorSlot slot, KeyedAccessStoreMode* store_mode,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400140 IcCheckType* key_type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 if (!slot.IsInvalid() &&
142 feedback_vector_->GetKind(slot) ==
143 FeedbackVectorSlotKind::KEYED_STORE_IC) {
144 KeyedStoreICNexus nexus(feedback_vector_, slot);
145 *store_mode = nexus.GetKeyedAccessStoreMode();
146 *key_type = nexus.GetKeyType();
147 } else {
148 *store_mode = STANDARD_STORE;
149 *key_type = ELEMENT;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100150 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100151}
152
Ben Murdochb8e0da22011-05-16 14:20:40 +0100153
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(FeedbackVectorSlot slot) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155 Handle<Object> info = GetInfo(slot);
156 if (info->IsAllocationSite()) {
157 return Handle<JSFunction>(isolate()->native_context()->array_function());
158 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100159
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000160 return Handle<JSFunction>::cast(info);
161}
162
163
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400164Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(
165 FeedbackVectorSlot slot) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166 Handle<Object> info = GetInfo(slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 if (info->IsJSFunction()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 return Handle<JSFunction>::cast(info);
169 }
170
171 DCHECK(info->IsAllocationSite());
172 return Handle<JSFunction>(isolate()->native_context()->array_function());
173}
174
175
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400176Handle<AllocationSite> TypeFeedbackOracle::GetCallAllocationSite(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 FeedbackVectorSlot slot) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178 Handle<Object> info = GetInfo(slot);
179 if (info->IsAllocationSite()) {
180 return Handle<AllocationSite>::cast(info);
181 }
182 return Handle<AllocationSite>::null();
183}
184
185
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(
187 FeedbackVectorSlot slot) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 Handle<Object> info = GetInfo(slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 if (info->IsAllocationSite()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 return Handle<AllocationSite>::cast(info);
191 }
192 return Handle<AllocationSite>::null();
193}
194
195
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196void TypeFeedbackOracle::CompareType(TypeFeedbackId id,
197 Type** left_type,
198 Type** right_type,
199 Type** combined_type) {
200 Handle<Object> info = GetInfo(id);
201 if (!info->IsCode()) {
202 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100203 *left_type = *right_type = *combined_type = Type::None();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 return;
205 }
206 Handle<Code> code = Handle<Code>::cast(info);
207
208 Handle<Map> map;
209 Map* raw_map = code->FindFirstMap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 if (raw_map != NULL) Map::TryUpdate(handle(raw_map)).ToHandle(&map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000211
212 if (code->is_compare_ic_stub()) {
213 CompareICStub stub(code->stub_key(), isolate());
214 *left_type = CompareICState::StateToType(zone(), stub.left());
215 *right_type = CompareICState::StateToType(zone(), stub.right());
216 *combined_type = CompareICState::StateToType(zone(), stub.state(), map);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100217 }
218}
219
220
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221void TypeFeedbackOracle::BinaryType(TypeFeedbackId id,
222 Type** left,
223 Type** right,
224 Type** result,
225 Maybe<int>* fixed_right_arg,
226 Handle<AllocationSite>* allocation_site,
227 Token::Value op) {
228 Handle<Object> object = GetInfo(id);
229 if (!object->IsCode()) {
230 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the
231 // operations covered by the BinaryOpIC we should always have them.
232 DCHECK(op < BinaryOpICState::FIRST_TOKEN ||
233 op > BinaryOpICState::LAST_TOKEN);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100234 *left = *right = *result = Type::None();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 *fixed_right_arg = Nothing<int>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 *allocation_site = Handle<AllocationSite>::null();
237 return;
Ben Murdoch257744e2011-11-30 15:57:28 +0000238 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 Handle<Code> code = Handle<Code>::cast(object);
240 DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
241 BinaryOpICState state(isolate(), code->extra_ic_state());
242 DCHECK_EQ(op, state.op());
243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 *left = state.GetLeftType();
245 *right = state.GetRightType();
246 *result = state.GetResultType();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 *fixed_right_arg = state.fixed_right_arg();
248
249 AllocationSite* first_allocation_site = code->FindFirstAllocationSite();
250 if (first_allocation_site != NULL) {
251 *allocation_site = handle(first_allocation_site);
252 } else {
253 *allocation_site = Handle<AllocationSite>::null();
254 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000255}
256
257
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) {
259 Handle<Object> object = GetInfo(id);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100260 if (!object->IsCode()) return Type::None();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 Handle<Code> code = Handle<Code>::cast(object);
262 DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
263 BinaryOpICState state(isolate(), code->extra_ic_state());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 return state.GetLeftType();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265}
266
267
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268bool TypeFeedbackOracle::HasOnlyStringMaps(SmallMapList* receiver_types) {
269 bool all_strings = receiver_types->length() > 0;
270 for (int i = 0; i < receiver_types->length(); i++) {
271 all_strings &= receiver_types->at(i)->IsStringMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400273 return all_strings;
274}
275
276
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277void TypeFeedbackOracle::PropertyReceiverTypes(FeedbackVectorSlot slot,
278 Handle<Name> name,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400279 SmallMapList* receiver_types) {
280 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 if (!slot.IsInvalid()) {
282 LoadICNexus nexus(feedback_vector_, slot);
283 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
284 CollectReceiverTypes(&nexus, name, flags, receiver_types);
285 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400286}
287
288
289void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 FeedbackVectorSlot slot, SmallMapList* receiver_types, bool* is_string,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291 IcCheckType* key_type) {
292 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 if (slot.IsInvalid()) {
294 *is_string = false;
295 *key_type = ELEMENT;
296 } else {
297 KeyedLoadICNexus nexus(feedback_vector_, slot);
Ben Murdochc5610432016-08-08 18:44:38 +0100298 CollectReceiverTypes(&nexus, receiver_types);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 *is_string = HasOnlyStringMaps(receiver_types);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300 *key_type = nexus.GetKeyType();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302}
303
304
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackVectorSlot slot,
306 Handle<Name> name,
307 SmallMapList* receiver_types) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 receiver_types->Clear();
309 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 CollectReceiverTypes(slot, name, flags, receiver_types);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311}
312
313
314void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 FeedbackVectorSlot slot, SmallMapList* receiver_types,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316 KeyedAccessStoreMode* store_mode, IcCheckType* key_type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 CollectReceiverTypes(slot, receiver_types);
319 GetStoreModeAndKeyType(slot, store_mode, key_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320}
321
322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323void TypeFeedbackOracle::CountReceiverTypes(FeedbackVectorSlot slot,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324 SmallMapList* receiver_types) {
325 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000326 if (!slot.IsInvalid()) CollectReceiverTypes(slot, receiver_types);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327}
328
329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot,
331 Handle<Name> name,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000332 Code::Flags flags,
333 SmallMapList* types) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 StoreICNexus nexus(feedback_vector_, slot);
Ben Murdochc5610432016-08-08 18:44:38 +0100335 CollectReceiverTypes(&nexus, name, flags, types);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400336}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337
Ben Murdochc5610432016-08-08 18:44:38 +0100338void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus,
339 Handle<Name> name,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340 Code::Flags flags,
341 SmallMapList* types) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 if (FLAG_collect_megamorphic_maps_from_stub_cache &&
Ben Murdochc5610432016-08-08 18:44:38 +0100343 nexus->ic_state() == MEGAMORPHIC) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 types->Reserve(4, zone());
345 isolate()->stub_cache()->CollectMatchingMaps(
346 types, name, flags, native_context_, zone());
347 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100348 CollectReceiverTypes(nexus, types);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100349 }
350}
351
352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354 SmallMapList* types) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot);
356 if (kind == FeedbackVectorSlotKind::STORE_IC) {
357 StoreICNexus nexus(feedback_vector_, slot);
Ben Murdochc5610432016-08-08 18:44:38 +0100358 CollectReceiverTypes(&nexus, types);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 } else {
360 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, kind);
361 KeyedStoreICNexus nexus(feedback_vector_, slot);
Ben Murdochc5610432016-08-08 18:44:38 +0100362 CollectReceiverTypes(&nexus, types);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400364}
365
Ben Murdochc5610432016-08-08 18:44:38 +0100366void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus,
367 SmallMapList* types) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368 MapHandleList maps;
Ben Murdochc5610432016-08-08 18:44:38 +0100369 if (nexus->ic_state() == MONOMORPHIC) {
370 Map* map = nexus->FindFirstMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 if (map != NULL) maps.Add(handle(map));
Ben Murdochc5610432016-08-08 18:44:38 +0100372 } else if (nexus->ic_state() == POLYMORPHIC) {
373 nexus->FindAllMaps(&maps);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 } else {
375 return;
376 }
377 types->Reserve(maps.length(), zone());
378 for (int i = 0; i < maps.length(); i++) {
379 Handle<Map> map(maps.at(i));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 if (IsRelevantFeedback(*map, *native_context_)) {
381 types->AddMapIfMissing(maps.at(i), zone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000382 }
383 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100384}
385
386
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387uint16_t TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 Handle<Object> object = GetInfo(id);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000389 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
390}
391
392
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000393// Things are a bit tricky here: The iterator for the RelocInfos and the infos
394// themselves are not GC-safe, so we first get all infos, then we create the
395// dictionary (possibly triggering GC), and finally we relocate the collected
396// infos before we process them.
397void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 DisallowHeapAllocation no_allocation;
399 ZoneList<RelocInfo> infos(16, zone());
400 HandleScope scope(isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000401 GetRelocInfos(code, &infos);
402 CreateDictionary(code, &infos);
403 ProcessRelocInfos(&infos);
Steve Block44f0eee2011-05-26 01:26:41 +0100404 // Allocate handle in the parent scope.
405 dictionary_ = scope.CloseAndEscape(dictionary_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100406}
407
408
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000409void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code,
410 ZoneList<RelocInfo>* infos) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000411 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000412 for (RelocIterator it(*code, mask); !it.done(); it.next()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 infos->Add(*it.rinfo(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100414 }
415}
416
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000417
418void TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
419 ZoneList<RelocInfo>* infos) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 AllowHeapAllocation allocation_allowed;
421 Code* old_code = *code;
422 dictionary_ = UnseededNumberDictionary::New(isolate(), infos->length());
423 RelocateRelocInfos(infos, old_code, *code);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000424}
425
426
427void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000428 Code* old_code,
429 Code* new_code) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000430 for (int i = 0; i < infos->length(); i++) {
431 RelocInfo* info = &(*infos)[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 info->set_host(new_code);
433 info->set_pc(new_code->instruction_start() +
434 (info->pc() - old_code->instruction_start()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000435 }
436}
437
438
439void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
440 for (int i = 0; i < infos->length(); i++) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100441 RelocInfo reloc_entry = (*infos)[i];
442 Address target_address = reloc_entry.target_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 TypeFeedbackId ast_id =
444 TypeFeedbackId(static_cast<unsigned>((*infos)[i].data()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100445 Code* target = Code::GetCodeFromTargetAddress(target_address);
446 switch (target->kind()) {
447 case Code::LOAD_IC:
448 case Code::STORE_IC:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100449 case Code::KEYED_LOAD_IC:
450 case Code::KEYED_STORE_IC:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100451 case Code::BINARY_OP_IC:
452 case Code::COMPARE_IC:
453 case Code::TO_BOOLEAN_IC:
454 SetInfo(ast_id, target);
455 break;
456
457 default:
458 break;
459 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000460 }
461}
462
463
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) {
465 DCHECK(dictionary_->FindEntry(IdToKey(ast_id)) ==
466 UnseededNumberDictionary::kNotFound);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000467 // Dictionary has been allocated with sufficient size for all elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468 DisallowHeapAllocation no_need_to_resize_dictionary;
469 HandleScope scope(isolate());
470 USE(UnseededNumberDictionary::AtNumberPut(
471 dictionary_, IdToKey(ast_id), handle(target, isolate())));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000472}
473
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475} // namespace internal
476} // namespace v8