OLD | NEW |
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-state.h" | 8 #include "src/ic/ic-state.h" |
8 #include "src/objects.h" | 9 #include "src/objects.h" |
9 #include "src/type-feedback-vector-inl.h" | 10 #include "src/type-feedback-vector-inl.h" |
10 | 11 |
11 namespace v8 { | 12 namespace v8 { |
12 namespace internal { | 13 namespace internal { |
13 | 14 |
14 // static | 15 // static |
| 16 TypeFeedbackVector::VectorICKind TypeFeedbackVector::FromCodeKind( |
| 17 Code::Kind kind) { |
| 18 if (kind == Code::CALL_IC) { |
| 19 return KindCallIC; |
| 20 } else if (kind == Code::LOAD_IC) { |
| 21 return KindLoadIC; |
| 22 } else if (kind == Code::KEYED_LOAD_IC) { |
| 23 return KindKeyedLoadIC; |
| 24 } |
| 25 |
| 26 // Shouldn't get here. |
| 27 UNREACHABLE(); |
| 28 return KindUnused; |
| 29 } |
| 30 |
| 31 |
| 32 // static |
| 33 Code::Kind TypeFeedbackVector::FromVectorICKind(VectorICKind kind) { |
| 34 if (kind == KindCallIC) |
| 35 return Code::CALL_IC; |
| 36 else if (kind == KindLoadIC) |
| 37 return Code::LOAD_IC; |
| 38 else if (kind == KindKeyedLoadIC) |
| 39 return Code::KEYED_LOAD_IC; |
| 40 DCHECK(kind == KindUnused); |
| 41 return Code::NUMBER_OF_KINDS; // Sentinel for no information. |
| 42 } |
| 43 |
| 44 |
| 45 Code::Kind TypeFeedbackVector::GetKind(FeedbackVectorICSlot slot) const { |
| 46 if (!FLAG_vector_ics) { |
| 47 // We only have CALL_ICs |
| 48 return Code::CALL_IC; |
| 49 } |
| 50 |
| 51 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
| 52 int data = Smi::cast(get(index))->value(); |
| 53 VectorICKind b = VectorICComputer::decode(data, slot.ToInt()); |
| 54 return FromVectorICKind(b); |
| 55 } |
| 56 |
| 57 |
| 58 void TypeFeedbackVector::SetKind(FeedbackVectorICSlot slot, Code::Kind kind) { |
| 59 if (!FLAG_vector_ics) { |
| 60 // Nothing to do if we only have CALL_ICs |
| 61 return; |
| 62 } |
| 63 |
| 64 VectorICKind b = FromCodeKind(kind); |
| 65 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
| 66 int data = Smi::cast(get(index))->value(); |
| 67 int new_data = VectorICComputer::encode(data, slot.ToInt(), b); |
| 68 set(index, Smi::FromInt(new_data)); |
| 69 } |
| 70 |
| 71 |
| 72 // static |
15 Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, | 73 Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, |
16 int slot_count, | 74 int slot_count, |
17 int ic_slot_count) { | 75 int ic_slot_count) { |
18 int length = slot_count + ic_slot_count + kReservedIndexCount; | 76 int index_count = |
| 77 FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0; |
| 78 int length = slot_count + ic_slot_count + index_count + kReservedIndexCount; |
19 if (length == kReservedIndexCount) { | 79 if (length == kReservedIndexCount) { |
20 return Handle<TypeFeedbackVector>::cast( | 80 return Handle<TypeFeedbackVector>::cast( |
21 isolate->factory()->empty_fixed_array()); | 81 isolate->factory()->empty_fixed_array()); |
22 } | 82 } |
23 | 83 |
24 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); | 84 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); |
25 if (ic_slot_count > 0) { | 85 if (ic_slot_count > 0) { |
26 array->set(kFirstICSlotIndex, | 86 array->set(kFirstICSlotIndex, |
27 Smi::FromInt(slot_count + kReservedIndexCount)); | 87 Smi::FromInt(slot_count + index_count + kReservedIndexCount)); |
28 } else { | 88 } else { |
29 array->set(kFirstICSlotIndex, Smi::FromInt(length)); | 89 array->set(kFirstICSlotIndex, Smi::FromInt(length)); |
30 } | 90 } |
31 array->set(kWithTypesIndex, Smi::FromInt(0)); | 91 array->set(kWithTypesIndex, Smi::FromInt(0)); |
32 array->set(kGenericCountIndex, Smi::FromInt(0)); | 92 array->set(kGenericCountIndex, Smi::FromInt(0)); |
| 93 // Fill the indexes with zeros. |
| 94 for (int i = 0; i < index_count; i++) { |
| 95 array->set(kReservedIndexCount + i, Smi::FromInt(0)); |
| 96 } |
33 | 97 |
34 // Ensure we can skip the write barrier | 98 // Ensure we can skip the write barrier |
35 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); | 99 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); |
36 DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel); | 100 DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel); |
37 for (int i = kReservedIndexCount; i < length; i++) { | 101 for (int i = kReservedIndexCount + index_count; i < length; i++) { |
38 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); | 102 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); |
39 } | 103 } |
40 return Handle<TypeFeedbackVector>::cast(array); | 104 return Handle<TypeFeedbackVector>::cast(array); |
41 } | 105 } |
42 | 106 |
43 | 107 |
44 // static | 108 // static |
45 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( | 109 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( |
46 Isolate* isolate, Handle<TypeFeedbackVector> vector) { | 110 Isolate* isolate, Handle<TypeFeedbackVector> vector) { |
47 Handle<TypeFeedbackVector> result; | 111 Handle<TypeFeedbackVector> result; |
(...skipping 27 matching lines...) Expand all Loading... |
75 slots = ICSlots(); | 139 slots = ICSlots(); |
76 if (slots == 0) return; | 140 if (slots == 0) return; |
77 | 141 |
78 // Now clear vector-based ICs. They are all CallICs. | 142 // Now clear vector-based ICs. They are all CallICs. |
79 // Try and pass the containing code (the "host"). | 143 // Try and pass the containing code (the "host"). |
80 Code* host = shared->code(); | 144 Code* host = shared->code(); |
81 for (int i = 0; i < slots; i++) { | 145 for (int i = 0; i < slots; i++) { |
82 FeedbackVectorICSlot slot(i); | 146 FeedbackVectorICSlot slot(i); |
83 Object* obj = Get(slot); | 147 Object* obj = Get(slot); |
84 if (obj != uninitialized_sentinel) { | 148 if (obj != uninitialized_sentinel) { |
85 ICUtility::Clear(isolate, Code::CALL_IC, host, this, slot); | 149 // TODO(mvstanton): To make this code work with --vector-ics, |
| 150 // additional Nexus types must be created. |
| 151 DCHECK(!FLAG_vector_ics); |
| 152 DCHECK(GetKind(slot) == Code::CALL_IC); |
| 153 CallICNexus nexus(this, slot); |
| 154 ICUtility::Clear(isolate, Code::CALL_IC, host, &nexus); |
86 } | 155 } |
87 } | 156 } |
88 } | 157 } |
| 158 |
| 159 |
| 160 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
| 161 Isolate* isolate = GetIsolate(); |
| 162 Handle<Object> feedback = handle(GetFeedback(), isolate); |
| 163 if (!feedback->IsFixedArray() || |
| 164 FixedArray::cast(*feedback)->length() != length) { |
| 165 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); |
| 166 SetFeedback(*array); |
| 167 return array; |
| 168 } |
| 169 return Handle<FixedArray>::cast(feedback); |
| 170 } |
| 171 |
| 172 |
| 173 void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types, |
| 174 CodeHandleList* handlers) { |
| 175 Isolate* isolate = GetIsolate(); |
| 176 FixedArray* array = FixedArray::cast(GetFeedback()); |
| 177 int receiver_count = types->length(); |
| 178 for (int current = 0; current < receiver_count; ++current) { |
| 179 Handle<HeapType> type = types->at(current); |
| 180 Handle<Map> map = IC::TypeToMap(*type, isolate); |
| 181 array->set(start_index + (current * 2), *map); |
| 182 array->set(start_index + (current * 2 + 1), *handlers->at(current)); |
| 183 } |
| 184 } |
| 185 |
| 186 |
| 187 InlineCacheState CallICNexus::StateFromFeedback() const { |
| 188 Isolate* isolate = GetIsolate(); |
| 189 InlineCacheState state = UNINITIALIZED; |
| 190 Object* feedback = GetFeedback(); |
| 191 |
| 192 if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
| 193 state = GENERIC; |
| 194 } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { |
| 195 state = MONOMORPHIC; |
| 196 } else { |
| 197 CHECK(feedback == *vector()->UninitializedSentinel(isolate)); |
| 198 } |
| 199 |
| 200 return state; |
| 201 } |
| 202 |
| 203 |
| 204 void CallICNexus::ConfigureGeneric() { |
| 205 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
| 206 } |
| 207 |
| 208 |
| 209 void CallICNexus::ConfigureMonomorphicArray() { |
| 210 Object* feedback = GetFeedback(); |
| 211 if (!feedback->IsAllocationSite()) { |
| 212 Handle<AllocationSite> new_site = |
| 213 GetIsolate()->factory()->NewAllocationSite(); |
| 214 SetFeedback(*new_site); |
| 215 } |
| 216 } |
| 217 |
| 218 |
| 219 void CallICNexus::ConfigureUninitialized() { |
| 220 SetFeedback(*vector()->UninitializedSentinel(GetIsolate()), |
| 221 SKIP_WRITE_BARRIER); |
| 222 } |
| 223 |
| 224 |
| 225 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
| 226 SetFeedback(*function); |
| 227 } |
| 228 |
| 229 |
| 230 int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { |
| 231 Isolate* isolate = GetIsolate(); |
| 232 Object* feedback = GetFeedback(); |
| 233 if (feedback->IsFixedArray()) { |
| 234 FixedArray* array = FixedArray::cast(feedback); |
| 235 // The array should be of the form [<optional name>], then |
| 236 // [map, handler, map, handler, ... ] |
| 237 DCHECK(array->length() >= (2 + start_index)); |
| 238 for (int i = start_index; i < array->length(); i += 2) { |
| 239 Map* map = Map::cast(array->get(i)); |
| 240 maps->Add(handle(map, isolate)); |
| 241 } |
| 242 return (array->length() - start_index) / 2; |
| 243 } |
| 244 |
| 245 return 0; |
| 246 } |
| 247 |
| 248 |
| 249 MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(int start_index, |
| 250 Handle<Map> map) const { |
| 251 Object* feedback = GetFeedback(); |
| 252 if (feedback->IsFixedArray()) { |
| 253 FixedArray* array = FixedArray::cast(feedback); |
| 254 for (int i = start_index; i < array->length(); i += 2) { |
| 255 Map* array_map = Map::cast(array->get(i)); |
| 256 if (array_map == *map) { |
| 257 Code* code = Code::cast(array->get(i + 1)); |
| 258 DCHECK(code->kind() == Code::HANDLER); |
| 259 return handle(code); |
| 260 } |
| 261 } |
| 262 } |
| 263 |
| 264 return MaybeHandle<Code>(); |
| 265 } |
| 266 |
| 267 |
| 268 bool FeedbackNexus::FindHandlers(int start_index, CodeHandleList* code_list, |
| 269 int length) const { |
| 270 Object* feedback = GetFeedback(); |
| 271 int count = 0; |
| 272 if (feedback->IsFixedArray()) { |
| 273 FixedArray* array = FixedArray::cast(feedback); |
| 274 // The array should be of the form [<optional name>], then |
| 275 // [map, handler, map, handler, ... ] |
| 276 DCHECK(array->length() >= (2 + start_index)); |
| 277 for (int i = start_index; i < array->length(); i += 2) { |
| 278 Code* code = Code::cast(array->get(i + 1)); |
| 279 DCHECK(code->kind() == Code::HANDLER); |
| 280 code_list->Add(handle(code)); |
| 281 count++; |
| 282 } |
| 283 } |
| 284 return count == length; |
| 285 } |
89 } | 286 } |
90 } // namespace v8::internal | 287 } // namespace v8::internal |
OLD | NEW |