Chromium Code Reviews

Side by Side Diff: src/type-info.cc

Issue 6793016: Record AST ids in relocation info at spots where we collect dynamic type feedback. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add ARM port Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
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...)
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...)
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
OLDNEW
« src/ia32/assembler-ia32.h ('K') | « src/type-info.h ('k') | src/x64/assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine