Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: src/type-feedback-vector.cc

Issue 754303003: Flesh out vector ic state query and set mechanisms. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/type-feedback-vector.h ('k') | src/type-info.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/ic/ic.h" 7 #include "src/ic/ic.h"
8 #include "src/ic/ic-state.h" 8 #include "src/ic/ic-state.h"
9 #include "src/objects.h" 9 #include "src/objects.h"
10 #include "src/type-feedback-vector-inl.h" 10 #include "src/type-feedback-vector-inl.h"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 69
70 VectorICKind b = FromCodeKind(kind); 70 VectorICKind b = FromCodeKind(kind);
71 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); 71 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
72 int data = Smi::cast(get(index))->value(); 72 int data = Smi::cast(get(index))->value();
73 int new_data = VectorICComputer::encode(data, slot.ToInt(), b); 73 int new_data = VectorICComputer::encode(data, slot.ToInt(), b);
74 set(index, Smi::FromInt(new_data)); 74 set(index, Smi::FromInt(new_data));
75 } 75 }
76 76
77 77
78 // static 78 // static
79 Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, 79 Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(
80 int slot_count, 80 Isolate* isolate, const FeedbackVectorSpec& spec) {
81 int ic_slot_count) { 81 const int slot_count = spec.slots();
82 int index_count = 82 const int ic_slot_count = spec.ic_slots();
83 const int index_count =
83 FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0; 84 FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0;
84 int length = slot_count + ic_slot_count + index_count + kReservedIndexCount; 85 const int length =
86 slot_count + ic_slot_count + index_count + kReservedIndexCount;
85 if (length == kReservedIndexCount) { 87 if (length == kReservedIndexCount) {
86 return Handle<TypeFeedbackVector>::cast( 88 return Handle<TypeFeedbackVector>::cast(
87 isolate->factory()->empty_fixed_array()); 89 isolate->factory()->empty_fixed_array());
88 } 90 }
89 91
90 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); 92 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
91 if (ic_slot_count > 0) { 93 if (ic_slot_count > 0) {
92 array->set(kFirstICSlotIndex, 94 array->set(kFirstICSlotIndex,
93 Smi::FromInt(slot_count + index_count + kReservedIndexCount)); 95 Smi::FromInt(slot_count + index_count + kReservedIndexCount));
94 } else { 96 } else {
95 array->set(kFirstICSlotIndex, Smi::FromInt(length)); 97 array->set(kFirstICSlotIndex, Smi::FromInt(length));
96 } 98 }
97 array->set(kWithTypesIndex, Smi::FromInt(0)); 99 array->set(kWithTypesIndex, Smi::FromInt(0));
98 array->set(kGenericCountIndex, Smi::FromInt(0)); 100 array->set(kGenericCountIndex, Smi::FromInt(0));
99 // Fill the indexes with zeros.
100 for (int i = 0; i < index_count; i++) {
101 array->set(kReservedIndexCount + i, Smi::FromInt(0));
102 }
103 101
104 // Ensure we can skip the write barrier 102 // Ensure we can skip the write barrier
105 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); 103 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
106 DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel); 104 DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel);
107 for (int i = kReservedIndexCount + index_count; i < length; i++) { 105 for (int i = kReservedIndexCount + index_count; i < length; i++) {
108 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); 106 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
109 } 107 }
110 return Handle<TypeFeedbackVector>::cast(array); 108
109 Handle<TypeFeedbackVector> vector = Handle<TypeFeedbackVector>::cast(array);
110 if (FLAG_vector_ics) {
111 for (int i = 0; i < ic_slot_count; i++) {
112 vector->SetKind(FeedbackVectorICSlot(i), spec.GetKind(i));
113 }
114 }
115 return vector;
111 } 116 }
112 117
113 118
114 // static 119 // static
115 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( 120 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
116 Isolate* isolate, Handle<TypeFeedbackVector> vector) { 121 Isolate* isolate, Handle<TypeFeedbackVector> vector) {
117 Handle<TypeFeedbackVector> result; 122 Handle<TypeFeedbackVector> result;
118 result = Handle<TypeFeedbackVector>::cast( 123 result = Handle<TypeFeedbackVector>::cast(
119 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); 124 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
120 return result; 125 return result;
121 } 126 }
122 127
123 128
129 // This logic is copied from
130 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
131 // TODO(mvstanton): with weak handling of all vector ics, this logic should
132 // actually be completely eliminated and we no longer need to clear the
133 // vector ICs.
134 static bool ClearLogic(Heap* heap, int ic_age, Code::Kind kind,
135 InlineCacheState state) {
136 if (FLAG_cleanup_code_caches_at_gc &&
137 (kind == Code::CALL_IC || state == MEGAMORPHIC || state == GENERIC ||
138 state == POLYMORPHIC || heap->flush_monomorphic_ics() ||
139 // TODO(mvstanton): is this ic_age granular enough? it comes from
140 // the SharedFunctionInfo which may change on a different schedule
141 // than ic targets.
142 // ic_age != heap->global_ic_age() ||
143 // is_invalidated_weak_stub ||
144 heap->isolate()->serializer_enabled())) {
145 return true;
146 }
147 return false;
148 }
149
150
124 void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { 151 void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) {
125 int slots = Slots(); 152 int slots = Slots();
126 Isolate* isolate = GetIsolate(); 153 Isolate* isolate = GetIsolate();
127 Object* uninitialized_sentinel = 154 Object* uninitialized_sentinel =
128 TypeFeedbackVector::RawUninitializedSentinel(isolate->heap()); 155 TypeFeedbackVector::RawUninitializedSentinel(isolate->heap());
129 156
130 for (int i = 0; i < slots; i++) { 157 for (int i = 0; i < slots; i++) {
131 FeedbackVectorSlot slot(i); 158 FeedbackVectorSlot slot(i);
132 Object* obj = Get(slot); 159 Object* obj = Get(slot);
133 if (obj->IsHeapObject()) { 160 if (obj->IsHeapObject()) {
134 InstanceType instance_type = 161 InstanceType instance_type =
135 HeapObject::cast(obj)->map()->instance_type(); 162 HeapObject::cast(obj)->map()->instance_type();
136 // AllocationSites are exempt from clearing. They don't store Maps 163 // AllocationSites are exempt from clearing. They don't store Maps
137 // or Code pointers which can cause memory leaks if not cleared 164 // or Code pointers which can cause memory leaks if not cleared
138 // regularly. 165 // regularly.
139 if (instance_type != ALLOCATION_SITE_TYPE) { 166 if (instance_type != ALLOCATION_SITE_TYPE) {
140 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); 167 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
141 } 168 }
142 } 169 }
143 } 170 }
144 171
145 slots = ICSlots(); 172 slots = ICSlots();
146 if (slots == 0) return; 173 if (slots == 0) return;
147 174
148 // Now clear vector-based ICs. They are all CallICs. 175 // Now clear vector-based ICs.
149 // Try and pass the containing code (the "host"). 176 // Try and pass the containing code (the "host").
177 Heap* heap = isolate->heap();
150 Code* host = shared->code(); 178 Code* host = shared->code();
179 // I'm not sure yet if this ic age is the correct one.
180 int ic_age = shared->ic_age();
151 for (int i = 0; i < slots; i++) { 181 for (int i = 0; i < slots; i++) {
152 FeedbackVectorICSlot slot(i); 182 FeedbackVectorICSlot slot(i);
153 Object* obj = Get(slot); 183 Object* obj = Get(slot);
154 if (obj != uninitialized_sentinel) { 184 if (obj != uninitialized_sentinel) {
155 // TODO(mvstanton): To make this code work with --vector-ics, 185 Code::Kind kind = GetKind(slot);
156 // additional Nexus types must be created. 186 if (kind == Code::CALL_IC) {
157 DCHECK(!FLAG_vector_ics); 187 CallICNexus nexus(this, slot);
158 DCHECK(GetKind(slot) == Code::CALL_IC); 188 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
159 CallICNexus nexus(this, slot); 189 nexus.Clear(host);
160 ICUtility::Clear(isolate, Code::CALL_IC, host, &nexus); 190 }
191 } else if (kind == Code::LOAD_IC) {
192 LoadICNexus nexus(this, slot);
193 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
194 nexus.Clear(host);
195 }
196 } else if (kind == Code::KEYED_LOAD_IC) {
197 KeyedLoadICNexus nexus(this, slot);
198 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
199 nexus.Clear(host);
200 }
201 }
161 } 202 }
162 } 203 }
163 } 204 }
164 205
165 206
166 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { 207 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
167 Isolate* isolate = GetIsolate(); 208 Isolate* isolate = GetIsolate();
168 Handle<Object> feedback = handle(GetFeedback(), isolate); 209 Handle<Object> feedback = handle(GetFeedback(), isolate);
169 if (!feedback->IsFixedArray() || 210 if (!feedback->IsFixedArray() ||
170 FixedArray::cast(*feedback)->length() != length) { 211 FixedArray::cast(*feedback)->length() != length) {
(...skipping 12 matching lines...) Expand all
183 int receiver_count = types->length(); 224 int receiver_count = types->length();
184 for (int current = 0; current < receiver_count; ++current) { 225 for (int current = 0; current < receiver_count; ++current) {
185 Handle<HeapType> type = types->at(current); 226 Handle<HeapType> type = types->at(current);
186 Handle<Map> map = IC::TypeToMap(*type, isolate); 227 Handle<Map> map = IC::TypeToMap(*type, isolate);
187 array->set(start_index + (current * 2), *map); 228 array->set(start_index + (current * 2), *map);
188 array->set(start_index + (current * 2 + 1), *handlers->at(current)); 229 array->set(start_index + (current * 2 + 1), *handlers->at(current));
189 } 230 }
190 } 231 }
191 232
192 233
234 InlineCacheState LoadICNexus::StateFromFeedback() const {
235 Isolate* isolate = GetIsolate();
236 Object* feedback = GetFeedback();
237 if (feedback == *vector()->UninitializedSentinel(isolate)) {
238 return UNINITIALIZED;
239 } else if (feedback == *vector()->MegamorphicSentinel(isolate)) {
240 return MEGAMORPHIC;
241 } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) {
242 return PREMONOMORPHIC;
243 } else if (feedback->IsFixedArray()) {
244 FixedArray* array = FixedArray::cast(feedback);
245 int length = array->length();
246 DCHECK(length >= 2);
247 return length == 2 ? MONOMORPHIC : POLYMORPHIC;
248 }
249
250 return UNINITIALIZED;
251 }
252
253
254 InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
255 Isolate* isolate = GetIsolate();
256 Object* feedback = GetFeedback();
257 if (feedback == *vector()->UninitializedSentinel(isolate)) {
258 return UNINITIALIZED;
259 } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) {
260 return PREMONOMORPHIC;
261 } else if (feedback == *vector()->MegamorphicSentinel(isolate)) {
262 return MEGAMORPHIC;
263 } else if (feedback == *vector()->GenericSentinel(isolate)) {
264 return GENERIC;
265 } else if (feedback->IsFixedArray()) {
266 FixedArray* array = FixedArray::cast(feedback);
267 int length = array->length();
268 DCHECK(length >= 3);
269 return length == 3 ? MONOMORPHIC : POLYMORPHIC;
270 }
271
272 return UNINITIALIZED;
273 }
274
275
193 InlineCacheState CallICNexus::StateFromFeedback() const { 276 InlineCacheState CallICNexus::StateFromFeedback() const {
194 Isolate* isolate = GetIsolate(); 277 Isolate* isolate = GetIsolate();
195 InlineCacheState state = UNINITIALIZED;
196 Object* feedback = GetFeedback(); 278 Object* feedback = GetFeedback();
197 279
198 if (feedback == *vector()->MegamorphicSentinel(isolate)) { 280 if (feedback == *vector()->MegamorphicSentinel(isolate)) {
199 state = GENERIC; 281 return GENERIC;
200 } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { 282 } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) {
201 state = MONOMORPHIC; 283 return MONOMORPHIC;
202 } else {
203 CHECK(feedback == *vector()->UninitializedSentinel(isolate));
204 } 284 }
205 285
206 return state; 286 CHECK(feedback == *vector()->UninitializedSentinel(isolate));
287 return UNINITIALIZED;
207 } 288 }
208 289
209 290
291 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
292
293
210 void CallICNexus::ConfigureGeneric() { 294 void CallICNexus::ConfigureGeneric() {
211 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); 295 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
212 } 296 }
213 297
214 298
215 void CallICNexus::ConfigureMonomorphicArray() { 299 void CallICNexus::ConfigureMonomorphicArray() {
216 Object* feedback = GetFeedback(); 300 Object* feedback = GetFeedback();
217 if (!feedback->IsAllocationSite()) { 301 if (!feedback->IsAllocationSite()) {
218 Handle<AllocationSite> new_site = 302 Handle<AllocationSite> new_site =
219 GetIsolate()->factory()->NewAllocationSite(); 303 GetIsolate()->factory()->NewAllocationSite();
220 SetFeedback(*new_site); 304 SetFeedback(*new_site);
221 } 305 }
222 } 306 }
223 307
224 308
225 void CallICNexus::ConfigureUninitialized() { 309 void CallICNexus::ConfigureUninitialized() {
226 SetFeedback(*vector()->UninitializedSentinel(GetIsolate()), 310 SetFeedback(*vector()->UninitializedSentinel(GetIsolate()),
227 SKIP_WRITE_BARRIER); 311 SKIP_WRITE_BARRIER);
228 } 312 }
229 313
230 314
231 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { 315 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
232 SetFeedback(*function); 316 SetFeedback(*function);
233 } 317 }
234 318
235 319
320 void KeyedLoadICNexus::ConfigureGeneric() {
321 SetFeedback(*vector()->GenericSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
322 }
323
324
325 void KeyedLoadICNexus::ConfigureMegamorphic() {
326 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
327 }
328
329
330 void LoadICNexus::ConfigureMegamorphic() {
331 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
332 }
333
334
335 void LoadICNexus::ConfigurePremonomorphic() {
336 SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()),
337 SKIP_WRITE_BARRIER);
338 }
339
340
341 void KeyedLoadICNexus::ConfigurePremonomorphic() {
342 SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()),
343 SKIP_WRITE_BARRIER);
344 }
345
346
347 void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type,
348 Handle<Code> handler) {
349 Handle<FixedArray> array = EnsureArrayOfSize(2);
350 Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
351 array->set(0, *receiver_map);
352 array->set(1, *handler);
353 }
354
355
356 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
357 Handle<HeapType> type,
358 Handle<Code> handler) {
359 Handle<FixedArray> array = EnsureArrayOfSize(3);
360 Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
361 if (name.is_null()) {
362 array->set(0, Smi::FromInt(0));
363 } else {
364 array->set(0, *name);
365 }
366 array->set(1, *receiver_map);
367 array->set(2, *handler);
368 }
369
370
371 void LoadICNexus::ConfigurePolymorphic(TypeHandleList* types,
372 CodeHandleList* handlers) {
373 int receiver_count = types->length();
374 EnsureArrayOfSize(receiver_count * 2);
375 InstallHandlers(0, types, handlers);
376 }
377
378
379 void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
380 TypeHandleList* types,
381 CodeHandleList* handlers) {
382 int receiver_count = types->length();
383 Handle<FixedArray> array = EnsureArrayOfSize(1 + receiver_count * 2);
384 if (name.is_null()) {
385 array->set(0, Smi::FromInt(0));
386 } else {
387 array->set(0, *name);
388 }
389 InstallHandlers(1, types, handlers);
390 }
391
392
236 int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { 393 int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const {
237 Isolate* isolate = GetIsolate(); 394 Isolate* isolate = GetIsolate();
238 Object* feedback = GetFeedback(); 395 Object* feedback = GetFeedback();
239 if (feedback->IsFixedArray()) { 396 if (feedback->IsFixedArray()) {
240 FixedArray* array = FixedArray::cast(feedback); 397 FixedArray* array = FixedArray::cast(feedback);
241 // The array should be of the form [<optional name>], then 398 // The array should be of the form [<optional name>], then
242 // [map, handler, map, handler, ... ] 399 // [map, handler, map, handler, ... ]
243 DCHECK(array->length() >= (2 + start_index)); 400 DCHECK(array->length() >= (2 + start_index));
244 for (int i = start_index; i < array->length(); i += 2) { 401 for (int i = start_index; i < array->length(); i += 2) {
245 Map* map = Map::cast(array->get(i)); 402 Map* map = Map::cast(array->get(i));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 DCHECK(array->length() >= (2 + start_index)); 439 DCHECK(array->length() >= (2 + start_index));
283 for (int i = start_index; i < array->length(); i += 2) { 440 for (int i = start_index; i < array->length(); i += 2) {
284 Code* code = Code::cast(array->get(i + 1)); 441 Code* code = Code::cast(array->get(i + 1));
285 DCHECK(code->kind() == Code::HANDLER); 442 DCHECK(code->kind() == Code::HANDLER);
286 code_list->Add(handle(code)); 443 code_list->Add(handle(code));
287 count++; 444 count++;
288 } 445 }
289 } 446 }
290 return count == length; 447 return count == length;
291 } 448 }
449
450
451 int LoadICNexus::ExtractMaps(MapHandleList* maps) const {
452 return FeedbackNexus::ExtractMaps(0, maps);
453 }
454
455
456 void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
457
458
459 void KeyedLoadICNexus::Clear(Code* host) {
460 KeyedLoadIC::Clear(GetIsolate(), host, this);
461 }
462
463
464 int KeyedLoadICNexus::ExtractMaps(MapHandleList* maps) const {
465 return FeedbackNexus::ExtractMaps(1, maps);
466 }
467
468
469 MaybeHandle<Code> LoadICNexus::FindHandlerForMap(Handle<Map> map) const {
470 return FeedbackNexus::FindHandlerForMap(0, map);
471 }
472
473
474 MaybeHandle<Code> KeyedLoadICNexus::FindHandlerForMap(Handle<Map> map) const {
475 return FeedbackNexus::FindHandlerForMap(1, map);
476 }
477
478
479 bool LoadICNexus::FindHandlers(CodeHandleList* code_list, int length) const {
480 return FeedbackNexus::FindHandlers(0, code_list, length);
481 }
482
483
484 bool KeyedLoadICNexus::FindHandlers(CodeHandleList* code_list,
485 int length) const {
486 return FeedbackNexus::FindHandlers(1, code_list, length);
487 }
488
489
490 Name* KeyedLoadICNexus::FindFirstName() const {
491 Object* feedback = GetFeedback();
492 if (feedback->IsFixedArray()) {
493 FixedArray* array = FixedArray::cast(feedback);
494 DCHECK(array->length() >= 3);
495 Object* name = array->get(0);
496 if (name->IsName()) return Name::cast(name);
497 }
498 return NULL;
499 }
292 } 500 }
293 } // namespace v8::internal 501 } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-feedback-vector.h ('k') | src/type-info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698