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...) 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(int pos) { | 72 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { |
73 int entry = dictionary_->FindEntry(pos); | 73 int entry = dictionary_->FindEntry(ast_id); |
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->position())); | 81 Handle<Object> map_or_code(GetInfo(expr->id())); |
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->position())); | 93 Handle<Object> map_or_code(GetInfo(expr->id())); |
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->position()); | 105 Handle<Object> value = GetInfo(expr->id()); |
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->position()))); | 113 Handle<HeapObject>::cast(GetInfo(expr->id()))); |
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->position()))); | 125 Handle<HeapObject>::cast(GetInfo(expr->id()))); |
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->position(), name, flags); | 137 return CollectReceiverTypes(expr->id(), 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->position(), name, flags); | 144 return CollectReceiverTypes(expr->id(), 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->position(), name, flags); | 161 return CollectReceiverTypes(expr->id(), 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->position()); | 166 Handle<Object> value = GetInfo(expr->id()); |
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->position()); | 175 Handle<Object> stub = GetInfo(expr->id()); |
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->position()); | 182 Handle<Object> stub = GetInfo(expr->id()); |
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->position()) == | 210 return *GetInfo(expr->id()) == |
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->position()); | 216 Handle<Object> object = GetInfo(expr->id()); |
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->position()); | 243 Handle<Object> object = GetInfo(expr->id()); |
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 26 matching lines...) Loading... | |
280 return unknown; | 280 return unknown; |
281 default: | 281 default: |
282 return unknown; | 282 return unknown; |
283 } | 283 } |
284 } | 284 } |
285 return unknown; | 285 return unknown; |
286 } | 286 } |
287 | 287 |
288 | 288 |
289 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { | 289 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { |
290 Handle<Object> object = GetInfo(clause->position()); | 290 Handle<Object> object = GetInfo(clause->label()->id()); |
291 TypeInfo unknown = TypeInfo::Unknown(); | 291 TypeInfo unknown = TypeInfo::Unknown(); |
292 if (!object->IsCode()) return unknown; | 292 if (!object->IsCode()) return unknown; |
293 Handle<Code> code = Handle<Code>::cast(object); | 293 Handle<Code> code = Handle<Code>::cast(object); |
294 if (!code->is_compare_ic_stub()) return unknown; | 294 if (!code->is_compare_ic_stub()) return unknown; |
295 | 295 |
296 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 296 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
297 switch (state) { | 297 switch (state) { |
298 case CompareIC::UNINITIALIZED: | 298 case CompareIC::UNINITIALIZED: |
299 // Uninitialized means never executed. | 299 // Uninitialized means never executed. |
300 // TODO(fschneider): Introduce a separate value for never-executed ICs. | 300 // TODO(fschneider): Introduce a separate value for never-executed ICs. |
301 return unknown; | 301 return unknown; |
302 case CompareIC::SMIS: | 302 case CompareIC::SMIS: |
303 return TypeInfo::Smi(); | 303 return TypeInfo::Smi(); |
304 case CompareIC::HEAP_NUMBERS: | 304 case CompareIC::HEAP_NUMBERS: |
305 return TypeInfo::Number(); | 305 return TypeInfo::Number(); |
306 case CompareIC::OBJECTS: | 306 case CompareIC::OBJECTS: |
307 // TODO(kasperl): We really need a type for JS objects here. | 307 // TODO(kasperl): We really need a type for JS objects here. |
308 return TypeInfo::NonPrimitive(); | 308 return TypeInfo::NonPrimitive(); |
309 case CompareIC::GENERIC: | 309 case CompareIC::GENERIC: |
310 default: | 310 default: |
311 return unknown; | 311 return unknown; |
312 } | 312 } |
313 } | 313 } |
314 | 314 |
315 | 315 |
316 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, | 316 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, |
317 Handle<String> name, | 317 Handle<String> name, |
318 Code::Flags flags) { | 318 Code::Flags flags) { |
319 Isolate* isolate = Isolate::Current(); | 319 Isolate* isolate = Isolate::Current(); |
320 Handle<Object> object = GetInfo(position); | 320 Handle<Object> object = GetInfo(ast_id); |
321 if (object->IsUndefined() || object->IsSmi()) return NULL; | 321 if (object->IsUndefined() || object->IsSmi()) return NULL; |
322 | 322 |
323 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 323 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { |
324 // TODO(fschneider): We could collect the maps and signal that | 324 // TODO(fschneider): We could collect the maps and signal that |
325 // we need a generic store (or load) here. | 325 // we need a generic store (or load) here. |
326 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); | 326 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); |
327 return NULL; | 327 return NULL; |
328 } else if (object->IsMap()) { | 328 } else if (object->IsMap()) { |
329 ZoneMapList* types = new ZoneMapList(1); | 329 ZoneMapList* types = new ZoneMapList(1); |
330 types->Add(Handle<Map>::cast(object)); | 330 types->Add(Handle<Map>::cast(object)); |
331 return types; | 331 return types; |
332 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { | 332 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { |
333 ZoneMapList* types = new ZoneMapList(4); | 333 ZoneMapList* types = new ZoneMapList(4); |
334 ASSERT(object->IsCode()); | 334 ASSERT(object->IsCode()); |
335 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); | 335 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); |
336 return types->length() > 0 ? types : NULL; | 336 return types->length() > 0 ? types : NULL; |
337 } else { | 337 } else { |
338 return NULL; | 338 return NULL; |
339 } | 339 } |
340 } | 340 } |
341 | 341 |
342 | 342 |
343 void TypeFeedbackOracle::SetInfo(int position, Object* target) { | 343 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { |
344 MaybeObject* maybe_result = dictionary_->AtNumberPut(position, target); | 344 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); |
Vitaly Repeshko
2011/04/15 01:24:43
It used to work fine with an extra assert that we
William Hesse
2011/04/15 11:51:27
Done.
| |
345 USE(maybe_result); | 345 USE(maybe_result); |
346 #ifdef DEBUG | 346 #ifdef DEBUG |
347 Object* result; | 347 Object* result; |
348 // Dictionary has been allocated with sufficient size for all elements. | 348 // Dictionary has been allocated with sufficient size for all elements. |
349 ASSERT(maybe_result->ToObject(&result)); | 349 ASSERT(maybe_result->ToObject(&result)); |
350 ASSERT(*dictionary_ == result); | 350 ASSERT(*dictionary_ == result); |
351 #endif | 351 #endif |
352 } | 352 } |
353 | 353 |
354 | 354 |
355 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { | 355 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { |
356 Isolate* isolate = Isolate::Current(); | 356 Isolate* isolate = Isolate::Current(); |
357 HandleScope scope(isolate); | 357 HandleScope scope(isolate); |
358 | 358 |
359 const int kInitialCapacity = 16; | 359 const int kInitialCapacity = 16; |
360 List<int> code_positions(kInitialCapacity); | 360 List<int> code_positions(kInitialCapacity); |
361 List<int> source_positions(kInitialCapacity); | 361 List<unsigned> ast_ids(kInitialCapacity); |
362 CollectPositions(*code, &code_positions, &source_positions); | 362 CollectIds(*code, &code_positions, &ast_ids); |
363 | 363 |
364 ASSERT(dictionary_.is_null()); // Only initialize once. | 364 ASSERT(dictionary_.is_null()); // Only initialize once. |
365 dictionary_ = isolate->factory()->NewNumberDictionary( | 365 dictionary_ = isolate->factory()->NewNumberDictionary( |
366 code_positions.length()); | 366 code_positions.length()); |
367 | 367 |
368 int length = code_positions.length(); | 368 const int length = code_positions.length(); |
369 ASSERT(source_positions.length() == length); | 369 ASSERT(ast_ids.length() == length); |
370 for (int i = 0; i < length; i++) { | 370 for (int i = 0; i < length; i++) { |
371 AssertNoAllocation no_allocation; | 371 AssertNoAllocation no_allocation; |
372 RelocInfo info(code->instruction_start() + code_positions[i], | 372 RelocInfo info(code->instruction_start() + code_positions[i], |
373 RelocInfo::CODE_TARGET, 0); | 373 RelocInfo::CODE_TARGET, 0); |
374 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); | 374 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); |
375 int position = source_positions[i]; | 375 unsigned id = ast_ids[i]; |
376 InlineCacheState state = target->ic_state(); | 376 InlineCacheState state = target->ic_state(); |
377 Code::Kind kind = target->kind(); | 377 Code::Kind kind = target->kind(); |
378 | 378 |
379 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || | 379 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || |
380 kind == Code::COMPARE_IC) { | 380 kind == Code::COMPARE_IC) { |
381 // TODO(kasperl): Avoid having multiple ICs with the same | 381 SetInfo(id, target); |
382 // position by making sure that we have position information | |
383 // recorded for all binary ICs. | |
384 int entry = dictionary_->FindEntry(position); | |
385 if (entry == NumberDictionary::kNotFound) { | |
386 SetInfo(position, target); | |
387 } | |
388 } else if (state == MONOMORPHIC) { | 382 } else if (state == MONOMORPHIC) { |
389 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || | 383 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || |
390 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { | 384 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { |
391 SetInfo(position, target); | 385 SetInfo(id, target); |
392 } else if (target->kind() != Code::CALL_IC || | 386 } else if (kind != Code::CALL_IC || |
393 target->check_type() == RECEIVER_MAP_CHECK) { | 387 target->check_type() == RECEIVER_MAP_CHECK) { |
394 Map* map = target->FindFirstMap(); | 388 Map* map = target->FindFirstMap(); |
395 if (map == NULL) { | 389 if (map == NULL) { |
396 SetInfo(position, target); | 390 SetInfo(id, target); |
397 } else { | 391 } else { |
398 SetInfo(position, map); | 392 SetInfo(id, map); |
399 } | 393 } |
400 } else { | 394 } else { |
401 ASSERT(target->kind() == Code::CALL_IC); | 395 ASSERT(target->kind() == Code::CALL_IC); |
402 CheckType check = target->check_type(); | 396 CheckType check = target->check_type(); |
403 ASSERT(check != RECEIVER_MAP_CHECK); | 397 ASSERT(check != RECEIVER_MAP_CHECK); |
404 SetInfo(position, Smi::FromInt(check)); | 398 SetInfo(id, Smi::FromInt(check)); |
405 } | 399 } |
406 } else if (state == MEGAMORPHIC) { | 400 } else if (state == MEGAMORPHIC) { |
407 SetInfo(position, target); | 401 SetInfo(id, target); |
408 } | 402 } |
409 } | 403 } |
410 // Allocate handle in the parent scope. | 404 // Allocate handle in the parent scope. |
411 dictionary_ = scope.CloseAndEscape(dictionary_); | 405 dictionary_ = scope.CloseAndEscape(dictionary_); |
412 } | 406 } |
413 | 407 |
414 | 408 |
415 void TypeFeedbackOracle::CollectPositions(Code* code, | 409 void TypeFeedbackOracle::CollectIds(Code* code, |
416 List<int>* code_positions, | 410 List<int>* code_positions, |
Vitaly Repeshko
2011/04/15 01:24:43
nit: Fix indentation.
| |
417 List<int>* source_positions) { | 411 List<unsigned>* ast_ids) { |
418 AssertNoAllocation no_allocation; | 412 AssertNoAllocation no_allocation; |
419 int position = 0; | 413 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
420 // Because the ICs we use for global variables access in the full | |
421 // code generator do not have any meaningful positions, we avoid | |
422 // collecting those by filtering out contextual code targets. | |
423 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | |
424 RelocInfo::kPositionMask; | |
425 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 414 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
426 RelocInfo* info = it.rinfo(); | 415 RelocInfo* info = it.rinfo(); |
427 RelocInfo::Mode mode = info->rmode(); | 416 RelocInfo::Mode mode = info->rmode(); |
428 if (RelocInfo::IsCodeTarget(mode)) { | 417 if (RelocInfo::IsCodeTarget(mode)) { |
Vitaly Repeshko
2011/04/15 01:24:43
This can be turned into an assert.
William Hesse
2011/04/15 11:51:27
Done.
| |
429 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); | 418 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); |
430 if (target->is_inline_cache_stub()) { | 419 if (target->is_inline_cache_stub()) { |
431 InlineCacheState state = target->ic_state(); | 420 InlineCacheState state = target->ic_state(); |
432 Code::Kind kind = target->kind(); | 421 Code::Kind kind = target->kind(); |
433 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { | 422 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { |
434 if (target->type_recording_binary_op_type() == | 423 if (target->type_recording_binary_op_type() == |
435 TRBinaryOpIC::GENERIC) { | 424 TRBinaryOpIC::GENERIC) { |
436 continue; | 425 continue; |
437 } | 426 } |
438 } else if (kind == Code::COMPARE_IC) { | 427 } else if (kind == Code::COMPARE_IC) { |
439 if (target->compare_state() == CompareIC::GENERIC) continue; | 428 if (target->compare_state() == CompareIC::GENERIC) continue; |
440 } else { | 429 } else { |
441 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; | 430 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; |
442 } | 431 } |
443 code_positions->Add( | 432 code_positions->Add( |
444 static_cast<int>(info->pc() - code->instruction_start())); | 433 static_cast<int>(info->pc() - code->instruction_start())); |
445 source_positions->Add(position); | 434 ast_ids->Add(static_cast<unsigned>(info->data())); |
446 } | 435 } |
447 } else { | |
448 ASSERT(RelocInfo::IsPosition(mode)); | |
449 position = static_cast<int>(info->data()); | |
450 } | 436 } |
451 } | 437 } |
452 } | 438 } |
453 | 439 |
454 } } // namespace v8::internal | 440 } } // namespace v8::internal |
OLD | NEW |