blob: a8a406efde989ebec8de4d3e0deb68472c480734 [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);
111 return value->IsUndefined() ||
112 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.
203 *left_type = *right_type = *combined_type = Type::None(zone());
204 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);
217 } else if (code->is_compare_nil_ic_stub()) {
218 CompareNilICStub stub(isolate(), code->extra_ic_state());
219 *combined_type = stub.GetType(zone(), map);
220 *left_type = *right_type = stub.GetInputType(zone(), map);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100221 }
222}
223
224
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225void TypeFeedbackOracle::BinaryType(TypeFeedbackId id,
226 Type** left,
227 Type** right,
228 Type** result,
229 Maybe<int>* fixed_right_arg,
230 Handle<AllocationSite>* allocation_site,
231 Token::Value op) {
232 Handle<Object> object = GetInfo(id);
233 if (!object->IsCode()) {
234 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the
235 // operations covered by the BinaryOpIC we should always have them.
236 DCHECK(op < BinaryOpICState::FIRST_TOKEN ||
237 op > BinaryOpICState::LAST_TOKEN);
238 *left = *right = *result = Type::None(zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 *fixed_right_arg = Nothing<int>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240 *allocation_site = Handle<AllocationSite>::null();
241 return;
Ben Murdoch257744e2011-11-30 15:57:28 +0000242 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 Handle<Code> code = Handle<Code>::cast(object);
244 DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
245 BinaryOpICState state(isolate(), code->extra_ic_state());
246 DCHECK_EQ(op, state.op());
247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 *left = state.GetLeftType();
249 *right = state.GetRightType();
250 *result = state.GetResultType();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251 *fixed_right_arg = state.fixed_right_arg();
252
253 AllocationSite* first_allocation_site = code->FindFirstAllocationSite();
254 if (first_allocation_site != NULL) {
255 *allocation_site = handle(first_allocation_site);
256 } else {
257 *allocation_site = Handle<AllocationSite>::null();
258 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000259}
260
261
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) {
263 Handle<Object> object = GetInfo(id);
264 if (!object->IsCode()) return Type::None(zone());
265 Handle<Code> code = Handle<Code>::cast(object);
266 DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
267 BinaryOpICState state(isolate(), code->extra_ic_state());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 return state.GetLeftType();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269}
270
271
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272bool TypeFeedbackOracle::HasOnlyStringMaps(SmallMapList* receiver_types) {
273 bool all_strings = receiver_types->length() > 0;
274 for (int i = 0; i < receiver_types->length(); i++) {
275 all_strings &= receiver_types->at(i)->IsStringMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400277 return all_strings;
278}
279
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281void TypeFeedbackOracle::PropertyReceiverTypes(FeedbackVectorSlot slot,
282 Handle<Name> name,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283 SmallMapList* receiver_types) {
284 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 if (!slot.IsInvalid()) {
286 LoadICNexus nexus(feedback_vector_, slot);
287 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
288 CollectReceiverTypes(&nexus, name, flags, receiver_types);
289 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290}
291
292
293void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 FeedbackVectorSlot slot, SmallMapList* receiver_types, bool* is_string,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400295 IcCheckType* key_type) {
296 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 if (slot.IsInvalid()) {
298 *is_string = false;
299 *key_type = ELEMENT;
300 } else {
301 KeyedLoadICNexus nexus(feedback_vector_, slot);
302 CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types);
303 *is_string = HasOnlyStringMaps(receiver_types);
304 *key_type = nexus.FindFirstName() != NULL ? PROPERTY : ELEMENT;
305 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306}
307
308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackVectorSlot slot,
310 Handle<Name> name,
311 SmallMapList* receiver_types) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 receiver_types->Clear();
313 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 CollectReceiverTypes(slot, name, flags, receiver_types);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315}
316
317
318void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 FeedbackVectorSlot slot, SmallMapList* receiver_types,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400320 KeyedAccessStoreMode* store_mode, IcCheckType* key_type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322 CollectReceiverTypes(slot, receiver_types);
323 GetStoreModeAndKeyType(slot, store_mode, key_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324}
325
326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327void TypeFeedbackOracle::CountReceiverTypes(FeedbackVectorSlot slot,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 SmallMapList* receiver_types) {
329 receiver_types->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 if (!slot.IsInvalid()) CollectReceiverTypes(slot, receiver_types);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000331}
332
333
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot,
335 Handle<Name> name,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000336 Code::Flags flags,
337 SmallMapList* types) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 StoreICNexus nexus(feedback_vector_, slot);
339 CollectReceiverTypes<FeedbackNexus>(&nexus, name, flags, types);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400342
343template <class T>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344void TypeFeedbackOracle::CollectReceiverTypes(T* obj, Handle<Name> name,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400345 Code::Flags flags,
346 SmallMapList* types) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 if (FLAG_collect_megamorphic_maps_from_stub_cache &&
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400348 obj->ic_state() == MEGAMORPHIC) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349 types->Reserve(4, zone());
350 isolate()->stub_cache()->CollectMatchingMaps(
351 types, name, flags, native_context_, zone());
352 } else {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400353 CollectReceiverTypes<T>(obj, types);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100354 }
355}
356
357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 SmallMapList* types) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot);
361 if (kind == FeedbackVectorSlotKind::STORE_IC) {
362 StoreICNexus nexus(feedback_vector_, slot);
363 CollectReceiverTypes<FeedbackNexus>(&nexus, types);
364 } else {
365 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, kind);
366 KeyedStoreICNexus nexus(feedback_vector_, slot);
367 CollectReceiverTypes<FeedbackNexus>(&nexus, types);
368 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400369}
370
371
372template <class T>
373void TypeFeedbackOracle::CollectReceiverTypes(T* obj, SmallMapList* types) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 MapHandleList maps;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400375 if (obj->ic_state() == MONOMORPHIC) {
376 Map* map = obj->FindFirstMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 if (map != NULL) maps.Add(handle(map));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 } else if (obj->ic_state() == POLYMORPHIC) {
379 obj->FindAllMaps(&maps);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 } else {
381 return;
382 }
383 types->Reserve(maps.length(), zone());
384 for (int i = 0; i < maps.length(); i++) {
385 Handle<Map> map(maps.at(i));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 if (IsRelevantFeedback(*map, *native_context_)) {
387 types->AddMapIfMissing(maps.at(i), zone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000388 }
389 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100390}
391
392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393uint16_t TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 Handle<Object> object = GetInfo(id);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000395 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
396}
397
398
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000399// Things are a bit tricky here: The iterator for the RelocInfos and the infos
400// themselves are not GC-safe, so we first get all infos, then we create the
401// dictionary (possibly triggering GC), and finally we relocate the collected
402// infos before we process them.
403void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000404 DisallowHeapAllocation no_allocation;
405 ZoneList<RelocInfo> infos(16, zone());
406 HandleScope scope(isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000407 GetRelocInfos(code, &infos);
408 CreateDictionary(code, &infos);
409 ProcessRelocInfos(&infos);
Steve Block44f0eee2011-05-26 01:26:41 +0100410 // Allocate handle in the parent scope.
411 dictionary_ = scope.CloseAndEscape(dictionary_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100412}
413
414
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000415void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code,
416 ZoneList<RelocInfo>* infos) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000417 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000418 for (RelocIterator it(*code, mask); !it.done(); it.next()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419 infos->Add(*it.rinfo(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100420 }
421}
422
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000423
424void TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
425 ZoneList<RelocInfo>* infos) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 AllowHeapAllocation allocation_allowed;
427 Code* old_code = *code;
428 dictionary_ = UnseededNumberDictionary::New(isolate(), infos->length());
429 RelocateRelocInfos(infos, old_code, *code);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000430}
431
432
433void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000434 Code* old_code,
435 Code* new_code) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000436 for (int i = 0; i < infos->length(); i++) {
437 RelocInfo* info = &(*infos)[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 info->set_host(new_code);
439 info->set_pc(new_code->instruction_start() +
440 (info->pc() - old_code->instruction_start()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000441 }
442}
443
444
445void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
446 for (int i = 0; i < infos->length(); i++) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100447 RelocInfo reloc_entry = (*infos)[i];
448 Address target_address = reloc_entry.target_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449 TypeFeedbackId ast_id =
450 TypeFeedbackId(static_cast<unsigned>((*infos)[i].data()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100451 Code* target = Code::GetCodeFromTargetAddress(target_address);
452 switch (target->kind()) {
453 case Code::LOAD_IC:
454 case Code::STORE_IC:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100455 case Code::KEYED_LOAD_IC:
456 case Code::KEYED_STORE_IC:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100457 case Code::BINARY_OP_IC:
458 case Code::COMPARE_IC:
459 case Code::TO_BOOLEAN_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000460 case Code::COMPARE_NIL_IC:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100461 SetInfo(ast_id, target);
462 break;
463
464 default:
465 break;
466 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000467 }
468}
469
470
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) {
472 DCHECK(dictionary_->FindEntry(IdToKey(ast_id)) ==
473 UnseededNumberDictionary::kNotFound);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000474 // Dictionary has been allocated with sufficient size for all elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475 DisallowHeapAllocation no_need_to_resize_dictionary;
476 HandleScope scope(isolate());
477 USE(UnseededNumberDictionary::AtNumberPut(
478 dictionary_, IdToKey(ast_id), handle(target, isolate())));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000479}
480
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482} // namespace internal
483} // namespace v8