OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 62 |
63 | 63 |
64 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 64 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
65 Handle<Context> global_context) { | 65 Handle<Context> global_context) { |
66 global_context_ = global_context; | 66 global_context_ = global_context; |
67 PopulateMap(code); | 67 PopulateMap(code); |
68 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); | 68 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); |
69 } | 69 } |
70 | 70 |
71 | 71 |
72 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { | 72 Handle<Object> TypeFeedbackOracle::GetInfo(int pos) { |
73 int entry = dictionary_->FindEntry(ast_id); | 73 int entry = dictionary_->FindEntry(pos); |
74 return entry != NumberDictionary::kNotFound | 74 return entry != NumberDictionary::kNotFound |
75 ? Handle<Object>(dictionary_->ValueAt(entry)) | 75 ? Handle<Object>(dictionary_->ValueAt(entry)) |
76 : Isolate::Current()->factory()->undefined_value(); | 76 : Isolate::Current()->factory()->undefined_value(); |
77 } | 77 } |
78 | 78 |
79 | 79 |
80 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) { | 80 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) { |
81 Handle<Object> map_or_code(GetInfo(expr->id())); | 81 Handle<Object> map_or_code(GetInfo(expr->position())); |
82 if (map_or_code->IsMap()) return true; | 82 if (map_or_code->IsMap()) return true; |
83 if (map_or_code->IsCode()) { | 83 if (map_or_code->IsCode()) { |
84 Handle<Code> code(Code::cast(*map_or_code)); | 84 Handle<Code> code(Code::cast(*map_or_code)); |
85 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC && | 85 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC && |
86 code->FindFirstMap() != NULL; | 86 code->FindFirstMap() != NULL; |
87 } | 87 } |
88 return false; | 88 return false; |
89 } | 89 } |
90 | 90 |
91 | 91 |
92 bool TypeFeedbackOracle::StoreIsMonomorphic(Expression* expr) { | 92 bool TypeFeedbackOracle::StoreIsMonomorphic(Expression* expr) { |
93 Handle<Object> map_or_code(GetInfo(expr->id())); | 93 Handle<Object> map_or_code(GetInfo(expr->position())); |
94 if (map_or_code->IsMap()) return true; | 94 if (map_or_code->IsMap()) return true; |
95 if (map_or_code->IsCode()) { | 95 if (map_or_code->IsCode()) { |
96 Handle<Code> code(Code::cast(*map_or_code)); | 96 Handle<Code> code(Code::cast(*map_or_code)); |
97 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_STORE_IC && | 97 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_STORE_IC && |
98 code->FindFirstMap() != NULL; | 98 code->FindFirstMap() != NULL; |
99 } | 99 } |
100 return false; | 100 return false; |
101 } | 101 } |
102 | 102 |
103 | 103 |
104 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { | 104 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { |
105 Handle<Object> value = GetInfo(expr->id()); | 105 Handle<Object> value = GetInfo(expr->position()); |
106 return value->IsMap() || value->IsSmi(); | 106 return value->IsMap() || value->IsSmi(); |
107 } | 107 } |
108 | 108 |
109 | 109 |
110 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { | 110 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { |
111 ASSERT(LoadIsMonomorphic(expr)); | 111 ASSERT(LoadIsMonomorphic(expr)); |
112 Handle<Object> map_or_code( | 112 Handle<Object> map_or_code( |
113 Handle<HeapObject>::cast(GetInfo(expr->id()))); | 113 Handle<HeapObject>::cast(GetInfo(expr->position()))); |
114 if (map_or_code->IsCode()) { | 114 if (map_or_code->IsCode()) { |
115 Handle<Code> code(Code::cast(*map_or_code)); | 115 Handle<Code> code(Code::cast(*map_or_code)); |
116 return Handle<Map>(code->FindFirstMap()); | 116 return Handle<Map>(code->FindFirstMap()); |
117 } | 117 } |
118 return Handle<Map>(Map::cast(*map_or_code)); | 118 return Handle<Map>(Map::cast(*map_or_code)); |
119 } | 119 } |
120 | 120 |
121 | 121 |
122 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { | 122 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { |
123 ASSERT(StoreIsMonomorphic(expr)); | 123 ASSERT(StoreIsMonomorphic(expr)); |
124 Handle<HeapObject> map_or_code( | 124 Handle<HeapObject> map_or_code( |
125 Handle<HeapObject>::cast(GetInfo(expr->id()))); | 125 Handle<HeapObject>::cast(GetInfo(expr->position()))); |
126 if (map_or_code->IsCode()) { | 126 if (map_or_code->IsCode()) { |
127 Handle<Code> code(Code::cast(*map_or_code)); | 127 Handle<Code> code(Code::cast(*map_or_code)); |
128 return Handle<Map>(code->FindFirstMap()); | 128 return Handle<Map>(code->FindFirstMap()); |
129 } | 129 } |
130 return Handle<Map>(Map::cast(*map_or_code)); | 130 return Handle<Map>(Map::cast(*map_or_code)); |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, | 134 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, |
135 Handle<String> name) { | 135 Handle<String> name) { |
136 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); | 136 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); |
137 return CollectReceiverTypes(expr->id(), name, flags); | 137 return CollectReceiverTypes(expr->position(), name, flags); |
138 } | 138 } |
139 | 139 |
140 | 140 |
141 ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, | 141 ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, |
142 Handle<String> name) { | 142 Handle<String> name) { |
143 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); | 143 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); |
144 return CollectReceiverTypes(expr->id(), name, flags); | 144 return CollectReceiverTypes(expr->position(), name, flags); |
145 } | 145 } |
146 | 146 |
147 | 147 |
148 ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr, | 148 ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr, |
149 Handle<String> name) { | 149 Handle<String> name) { |
150 int arity = expr->arguments()->length(); | 150 int arity = expr->arguments()->length(); |
151 // Note: these flags won't let us get maps from stubs with | 151 // Note: these flags won't let us get maps from stubs with |
152 // non-default extra ic state in the megamorphic case. In the more | 152 // non-default extra ic state in the megamorphic case. In the more |
153 // important monomorphic case the map is obtained directly, so it's | 153 // important monomorphic case the map is obtained directly, so it's |
154 // not a problem until we decide to emit more polymorphic code. | 154 // not a problem until we decide to emit more polymorphic code. |
155 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 155 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, |
156 NORMAL, | 156 NORMAL, |
157 Code::kNoExtraICState, | 157 Code::kNoExtraICState, |
158 OWN_MAP, | 158 OWN_MAP, |
159 NOT_IN_LOOP, | 159 NOT_IN_LOOP, |
160 arity); | 160 arity); |
161 return CollectReceiverTypes(expr->id(), name, flags); | 161 return CollectReceiverTypes(expr->position(), name, flags); |
162 } | 162 } |
163 | 163 |
164 | 164 |
165 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { | 165 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { |
166 Handle<Object> value = GetInfo(expr->id()); | 166 Handle<Object> value = GetInfo(expr->position()); |
167 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 167 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; |
168 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 168 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); |
169 ASSERT(check != RECEIVER_MAP_CHECK); | 169 ASSERT(check != RECEIVER_MAP_CHECK); |
170 return check; | 170 return check; |
171 } | 171 } |
172 | 172 |
173 ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType( | 173 ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType( |
174 Property* expr) { | 174 Property* expr) { |
175 Handle<Object> stub = GetInfo(expr->id()); | 175 Handle<Object> stub = GetInfo(expr->position()); |
176 ASSERT(stub->IsCode()); | 176 ASSERT(stub->IsCode()); |
177 return Code::cast(*stub)->external_array_type(); | 177 return Code::cast(*stub)->external_array_type(); |
178 } | 178 } |
179 | 179 |
180 ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType( | 180 ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType( |
181 Expression* expr) { | 181 Expression* expr) { |
182 Handle<Object> stub = GetInfo(expr->id()); | 182 Handle<Object> stub = GetInfo(expr->position()); |
183 ASSERT(stub->IsCode()); | 183 ASSERT(stub->IsCode()); |
184 return Code::cast(*stub)->external_array_type(); | 184 return Code::cast(*stub)->external_array_type(); |
185 } | 185 } |
186 | 186 |
187 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( | 187 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( |
188 CheckType check) { | 188 CheckType check) { |
189 JSFunction* function = NULL; | 189 JSFunction* function = NULL; |
190 switch (check) { | 190 switch (check) { |
191 case RECEIVER_MAP_CHECK: | 191 case RECEIVER_MAP_CHECK: |
192 UNREACHABLE(); | 192 UNREACHABLE(); |
193 break; | 193 break; |
194 case STRING_CHECK: | 194 case STRING_CHECK: |
195 function = global_context_->string_function(); | 195 function = global_context_->string_function(); |
196 break; | 196 break; |
197 case NUMBER_CHECK: | 197 case NUMBER_CHECK: |
198 function = global_context_->number_function(); | 198 function = global_context_->number_function(); |
199 break; | 199 break; |
200 case BOOLEAN_CHECK: | 200 case BOOLEAN_CHECK: |
201 function = global_context_->boolean_function(); | 201 function = global_context_->boolean_function(); |
202 break; | 202 break; |
203 } | 203 } |
204 ASSERT(function != NULL); | 204 ASSERT(function != NULL); |
205 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); | 205 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); |
206 } | 206 } |
207 | 207 |
208 | 208 |
209 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { | 209 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { |
210 return *GetInfo(expr->id()) == | 210 return *GetInfo(expr->position()) == |
211 Isolate::Current()->builtins()->builtin(id); | 211 Isolate::Current()->builtins()->builtin(id); |
212 } | 212 } |
213 | 213 |
214 | 214 |
215 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { | 215 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { |
216 Handle<Object> object = GetInfo(expr->id()); | 216 Handle<Object> object = GetInfo(expr->position()); |
217 TypeInfo unknown = TypeInfo::Unknown(); | 217 TypeInfo unknown = TypeInfo::Unknown(); |
218 if (!object->IsCode()) return unknown; | 218 if (!object->IsCode()) return unknown; |
219 Handle<Code> code = Handle<Code>::cast(object); | 219 Handle<Code> code = Handle<Code>::cast(object); |
220 if (!code->is_compare_ic_stub()) return unknown; | 220 if (!code->is_compare_ic_stub()) return unknown; |
221 | 221 |
222 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 222 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
223 switch (state) { | 223 switch (state) { |
224 case CompareIC::UNINITIALIZED: | 224 case CompareIC::UNINITIALIZED: |
225 // Uninitialized means never executed. | 225 // Uninitialized means never executed. |
226 // TODO(fschneider): Introduce a separate value for never-executed ICs. | 226 // TODO(fschneider): Introduce a separate value for never-executed ICs. |
227 return unknown; | 227 return unknown; |
228 case CompareIC::SMIS: | 228 case CompareIC::SMIS: |
229 return TypeInfo::Smi(); | 229 return TypeInfo::Smi(); |
230 case CompareIC::HEAP_NUMBERS: | 230 case CompareIC::HEAP_NUMBERS: |
231 return TypeInfo::Number(); | 231 return TypeInfo::Number(); |
232 case CompareIC::OBJECTS: | 232 case CompareIC::OBJECTS: |
233 // TODO(kasperl): We really need a type for JS objects here. | 233 // TODO(kasperl): We really need a type for JS objects here. |
234 return TypeInfo::NonPrimitive(); | 234 return TypeInfo::NonPrimitive(); |
235 case CompareIC::GENERIC: | 235 case CompareIC::GENERIC: |
236 default: | 236 default: |
237 return unknown; | 237 return unknown; |
238 } | 238 } |
239 } | 239 } |
240 | 240 |
241 | 241 |
242 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { | 242 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { |
243 Handle<Object> object = GetInfo(expr->id()); | 243 Handle<Object> object = GetInfo(expr->position()); |
244 TypeInfo unknown = TypeInfo::Unknown(); | 244 TypeInfo unknown = TypeInfo::Unknown(); |
245 if (!object->IsCode()) return unknown; | 245 if (!object->IsCode()) return unknown; |
246 Handle<Code> code = Handle<Code>::cast(object); | 246 Handle<Code> code = Handle<Code>::cast(object); |
247 if (code->is_type_recording_binary_op_stub()) { | 247 if (code->is_type_recording_binary_op_stub()) { |
248 TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>( | 248 TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>( |
249 code->type_recording_binary_op_type()); | 249 code->type_recording_binary_op_type()); |
250 TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>( | 250 TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>( |
251 code->type_recording_binary_op_result_type()); | 251 code->type_recording_binary_op_result_type()); |
252 | 252 |
253 switch (type) { | 253 switch (type) { |
(...skipping 28 matching lines...) Expand all Loading... |
282 return unknown; | 282 return unknown; |
283 default: | 283 default: |
284 return unknown; | 284 return unknown; |
285 } | 285 } |
286 } | 286 } |
287 return unknown; | 287 return unknown; |
288 } | 288 } |
289 | 289 |
290 | 290 |
291 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { | 291 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { |
292 Handle<Object> object = GetInfo(clause->label()->id()); | 292 Handle<Object> object = GetInfo(clause->position()); |
293 TypeInfo unknown = TypeInfo::Unknown(); | 293 TypeInfo unknown = TypeInfo::Unknown(); |
294 if (!object->IsCode()) return unknown; | 294 if (!object->IsCode()) return unknown; |
295 Handle<Code> code = Handle<Code>::cast(object); | 295 Handle<Code> code = Handle<Code>::cast(object); |
296 if (!code->is_compare_ic_stub()) return unknown; | 296 if (!code->is_compare_ic_stub()) return unknown; |
297 | 297 |
298 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 298 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
299 switch (state) { | 299 switch (state) { |
300 case CompareIC::UNINITIALIZED: | 300 case CompareIC::UNINITIALIZED: |
301 // Uninitialized means never executed. | 301 // Uninitialized means never executed. |
302 // TODO(fschneider): Introduce a separate value for never-executed ICs. | 302 // TODO(fschneider): Introduce a separate value for never-executed ICs. |
303 return unknown; | 303 return unknown; |
304 case CompareIC::SMIS: | 304 case CompareIC::SMIS: |
305 return TypeInfo::Smi(); | 305 return TypeInfo::Smi(); |
306 case CompareIC::HEAP_NUMBERS: | 306 case CompareIC::HEAP_NUMBERS: |
307 return TypeInfo::Number(); | 307 return TypeInfo::Number(); |
308 case CompareIC::OBJECTS: | 308 case CompareIC::OBJECTS: |
309 // TODO(kasperl): We really need a type for JS objects here. | 309 // TODO(kasperl): We really need a type for JS objects here. |
310 return TypeInfo::NonPrimitive(); | 310 return TypeInfo::NonPrimitive(); |
311 case CompareIC::GENERIC: | 311 case CompareIC::GENERIC: |
312 default: | 312 default: |
313 return unknown; | 313 return unknown; |
314 } | 314 } |
315 } | 315 } |
316 | 316 |
317 | 317 |
318 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, | 318 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, |
319 Handle<String> name, | 319 Handle<String> name, |
320 Code::Flags flags) { | 320 Code::Flags flags) { |
321 Isolate* isolate = Isolate::Current(); | 321 Isolate* isolate = Isolate::Current(); |
322 Handle<Object> object = GetInfo(ast_id); | 322 Handle<Object> object = GetInfo(position); |
323 if (object->IsUndefined() || object->IsSmi()) return NULL; | 323 if (object->IsUndefined() || object->IsSmi()) return NULL; |
324 | 324 |
325 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 325 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { |
326 // TODO(fschneider): We could collect the maps and signal that | 326 // TODO(fschneider): We could collect the maps and signal that |
327 // we need a generic store (or load) here. | 327 // we need a generic store (or load) here. |
328 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); | 328 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); |
329 return NULL; | 329 return NULL; |
330 } else if (object->IsMap()) { | 330 } else if (object->IsMap()) { |
331 ZoneMapList* types = new ZoneMapList(1); | 331 ZoneMapList* types = new ZoneMapList(1); |
332 types->Add(Handle<Map>::cast(object)); | 332 types->Add(Handle<Map>::cast(object)); |
333 return types; | 333 return types; |
334 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { | 334 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { |
335 ZoneMapList* types = new ZoneMapList(4); | 335 ZoneMapList* types = new ZoneMapList(4); |
336 ASSERT(object->IsCode()); | 336 ASSERT(object->IsCode()); |
337 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); | 337 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); |
338 return types->length() > 0 ? types : NULL; | 338 return types->length() > 0 ? types : NULL; |
339 } else { | 339 } else { |
340 return NULL; | 340 return NULL; |
341 } | 341 } |
342 } | 342 } |
343 | 343 |
344 | 344 |
345 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { | 345 void TypeFeedbackOracle::SetInfo(int position, Object* target) { |
346 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound); | 346 MaybeObject* maybe_result = dictionary_->AtNumberPut(position, target); |
347 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); | |
348 USE(maybe_result); | 347 USE(maybe_result); |
349 #ifdef DEBUG | 348 #ifdef DEBUG |
350 Object* result; | 349 Object* result; |
351 // Dictionary has been allocated with sufficient size for all elements. | 350 // Dictionary has been allocated with sufficient size for all elements. |
352 ASSERT(maybe_result->ToObject(&result)); | 351 ASSERT(maybe_result->ToObject(&result)); |
353 ASSERT(*dictionary_ == result); | 352 ASSERT(*dictionary_ == result); |
354 #endif | 353 #endif |
355 } | 354 } |
356 | 355 |
357 | 356 |
358 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { | 357 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { |
359 Isolate* isolate = Isolate::Current(); | 358 Isolate* isolate = Isolate::Current(); |
360 HandleScope scope(isolate); | 359 HandleScope scope(isolate); |
361 | 360 |
362 const int kInitialCapacity = 16; | 361 const int kInitialCapacity = 16; |
363 List<int> code_positions(kInitialCapacity); | 362 List<int> code_positions(kInitialCapacity); |
364 List<unsigned> ast_ids(kInitialCapacity); | 363 List<int> source_positions(kInitialCapacity); |
365 CollectIds(*code, &code_positions, &ast_ids); | 364 CollectPositions(*code, &code_positions, &source_positions); |
366 | 365 |
367 ASSERT(dictionary_.is_null()); // Only initialize once. | 366 ASSERT(dictionary_.is_null()); // Only initialize once. |
368 dictionary_ = isolate->factory()->NewNumberDictionary( | 367 dictionary_ = isolate->factory()->NewNumberDictionary( |
369 code_positions.length()); | 368 code_positions.length()); |
370 | 369 |
371 const int length = code_positions.length(); | 370 int length = code_positions.length(); |
372 ASSERT(ast_ids.length() == length); | 371 ASSERT(source_positions.length() == length); |
373 for (int i = 0; i < length; i++) { | 372 for (int i = 0; i < length; i++) { |
374 AssertNoAllocation no_allocation; | 373 AssertNoAllocation no_allocation; |
375 RelocInfo info(code->instruction_start() + code_positions[i], | 374 RelocInfo info(code->instruction_start() + code_positions[i], |
376 RelocInfo::CODE_TARGET, 0); | 375 RelocInfo::CODE_TARGET, 0); |
377 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); | 376 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); |
378 unsigned id = ast_ids[i]; | 377 int position = source_positions[i]; |
379 InlineCacheState state = target->ic_state(); | 378 InlineCacheState state = target->ic_state(); |
380 Code::Kind kind = target->kind(); | 379 Code::Kind kind = target->kind(); |
381 | 380 |
382 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || | 381 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || |
383 kind == Code::COMPARE_IC) { | 382 kind == Code::COMPARE_IC) { |
384 SetInfo(id, target); | 383 // TODO(kasperl): Avoid having multiple ICs with the same |
| 384 // position by making sure that we have position information |
| 385 // recorded for all binary ICs. |
| 386 int entry = dictionary_->FindEntry(position); |
| 387 if (entry == NumberDictionary::kNotFound) { |
| 388 SetInfo(position, target); |
| 389 } |
385 } else if (state == MONOMORPHIC) { | 390 } else if (state == MONOMORPHIC) { |
386 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || | 391 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || |
387 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { | 392 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { |
388 SetInfo(id, target); | 393 SetInfo(position, target); |
389 } else if (kind != Code::CALL_IC || | 394 } else if (target->kind() != Code::CALL_IC || |
390 target->check_type() == RECEIVER_MAP_CHECK) { | 395 target->check_type() == RECEIVER_MAP_CHECK) { |
391 Map* map = target->FindFirstMap(); | 396 Map* map = target->FindFirstMap(); |
392 if (map == NULL) { | 397 if (map == NULL) { |
393 SetInfo(id, target); | 398 SetInfo(position, target); |
394 } else { | 399 } else { |
395 SetInfo(id, map); | 400 SetInfo(position, map); |
396 } | 401 } |
397 } else { | 402 } else { |
398 ASSERT(target->kind() == Code::CALL_IC); | 403 ASSERT(target->kind() == Code::CALL_IC); |
399 CheckType check = target->check_type(); | 404 CheckType check = target->check_type(); |
400 ASSERT(check != RECEIVER_MAP_CHECK); | 405 ASSERT(check != RECEIVER_MAP_CHECK); |
401 SetInfo(id, Smi::FromInt(check)); | 406 SetInfo(position, Smi::FromInt(check)); |
402 } | 407 } |
403 } else if (state == MEGAMORPHIC) { | 408 } else if (state == MEGAMORPHIC) { |
404 SetInfo(id, target); | 409 SetInfo(position, target); |
405 } | 410 } |
406 } | 411 } |
407 // Allocate handle in the parent scope. | 412 // Allocate handle in the parent scope. |
408 dictionary_ = scope.CloseAndEscape(dictionary_); | 413 dictionary_ = scope.CloseAndEscape(dictionary_); |
409 } | 414 } |
410 | 415 |
411 | 416 |
412 void TypeFeedbackOracle::CollectIds(Code* code, | 417 void TypeFeedbackOracle::CollectPositions(Code* code, |
413 List<int>* code_positions, | 418 List<int>* code_positions, |
414 List<unsigned>* ast_ids) { | 419 List<int>* source_positions) { |
415 AssertNoAllocation no_allocation; | 420 AssertNoAllocation no_allocation; |
416 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 421 int position = 0; |
| 422 // Because the ICs we use for global variables access in the full |
| 423 // code generator do not have any meaningful positions, we avoid |
| 424 // collecting those by filtering out contextual code targets. |
| 425 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| 426 RelocInfo::kPositionMask; |
417 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 427 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
418 RelocInfo* info = it.rinfo(); | 428 RelocInfo* info = it.rinfo(); |
419 ASSERT(RelocInfo::IsCodeTarget(info->rmode())); | 429 RelocInfo::Mode mode = info->rmode(); |
420 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); | 430 if (RelocInfo::IsCodeTarget(mode)) { |
421 if (target->is_inline_cache_stub()) { | 431 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); |
422 InlineCacheState state = target->ic_state(); | 432 if (target->is_inline_cache_stub()) { |
423 Code::Kind kind = target->kind(); | 433 InlineCacheState state = target->ic_state(); |
424 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { | 434 Code::Kind kind = target->kind(); |
425 if (target->type_recording_binary_op_type() == | 435 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { |
426 TRBinaryOpIC::GENERIC) { | 436 if (target->type_recording_binary_op_type() == |
427 continue; | 437 TRBinaryOpIC::GENERIC) { |
| 438 continue; |
| 439 } |
| 440 } else if (kind == Code::COMPARE_IC) { |
| 441 if (target->compare_state() == CompareIC::GENERIC) continue; |
| 442 } else { |
| 443 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; |
428 } | 444 } |
429 } else if (kind == Code::COMPARE_IC) { | 445 code_positions->Add( |
430 if (target->compare_state() == CompareIC::GENERIC) continue; | 446 static_cast<int>(info->pc() - code->instruction_start())); |
431 } else { | 447 source_positions->Add(position); |
432 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; | |
433 } | 448 } |
434 code_positions->Add( | 449 } else { |
435 static_cast<int>(info->pc() - code->instruction_start())); | 450 ASSERT(RelocInfo::IsPosition(mode)); |
436 ast_ids->Add(static_cast<unsigned>(info->data())); | 451 position = static_cast<int>(info->data()); |
437 } | 452 } |
438 } | 453 } |
439 } | 454 } |
440 | 455 |
441 } } // namespace v8::internal | 456 } } // namespace v8::internal |
OLD | NEW |