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
|