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

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

Issue 5699002: RFC: Switch to ast ids (instead of positions) for type feedback. (Closed)
Patch Set: Cleanup Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 64
65 65
66 void TypeFeedbackOracle::Initialize(Handle<Code> code) { 66 void TypeFeedbackOracle::Initialize(Handle<Code> code) {
67 ASSERT(map_.is_null()); // Only initialize once. 67 ASSERT(map_.is_null()); // Only initialize once.
68 map_ = Factory::NewJSObject(Top::object_function()); 68 map_ = Factory::NewJSObject(Top::object_function());
69 PopulateMap(code); 69 PopulateMap(code);
70 } 70 }
71 71
72 72
73 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) { 73 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
74 return IsMonomorphic(expr->position()); 74 return IsMonomorphic(expr->id());
75 } 75 }
76 76
77 77
78 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) { 78 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
79 return IsMonomorphic(expr->position()); 79 return IsMonomorphic(expr->id());
80 } 80 }
81 81
82 82
83 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { 83 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
84 return IsMonomorphic(expr->position()); 84 return IsMonomorphic(expr->id());
85 } 85 }
86 86
87 87
88 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { 88 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
89 ASSERT(LoadIsMonomorphic(expr)); 89 ASSERT(LoadIsMonomorphic(expr));
90 return Handle<Map>::cast(GetElement(map_, expr->position())); 90 return Handle<Map>::cast(GetElement(map_, expr->id()));
91 } 91 }
92 92
93 93
94 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) { 94 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
95 ASSERT(StoreIsMonomorphic(expr)); 95 ASSERT(StoreIsMonomorphic(expr));
96 return Handle<Map>::cast(GetElement(map_, expr->position())); 96 return Handle<Map>::cast(GetElement(map_, expr->id()));
97 } 97 }
98 98
99 99
100 Handle<Map> TypeFeedbackOracle::CallMonomorphicReceiverType(Call* expr) { 100 Handle<Map> TypeFeedbackOracle::CallMonomorphicReceiverType(Call* expr) {
101 ASSERT(CallIsMonomorphic(expr)); 101 ASSERT(CallIsMonomorphic(expr));
102 return Handle<Map>::cast(GetElement(map_, expr->position())); 102 return Handle<Map>::cast(GetElement(map_, expr->id()));
103 } 103 }
104 104
105 105
106 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, 106 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
107 Handle<String> name) { 107 Handle<String> name) {
108 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); 108 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
109 return CollectReceiverTypes(expr->position(), name, flags); 109 return CollectReceiverTypes(expr->id(), name, flags);
110 } 110 }
111 111
112 112
113 ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, 113 ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
114 Handle<String> name) { 114 Handle<String> name) {
115 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); 115 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
116 return CollectReceiverTypes(expr->position(), name, flags); 116 return CollectReceiverTypes(expr->id(), name, flags);
117 } 117 }
118 118
119 119
120 ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr, 120 ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
121 Handle<String> name) { 121 Handle<String> name) {
122 int arity = expr->arguments()->length(); 122 int arity = expr->arguments()->length();
123 Code::Flags flags = Code::ComputeMonomorphicFlags( 123 Code::Flags flags = Code::ComputeMonomorphicFlags(
124 Code::CALL_IC, NORMAL, OWN_MAP, NOT_IN_LOOP, arity); 124 Code::CALL_IC, NORMAL, OWN_MAP, NOT_IN_LOOP, arity);
125 return CollectReceiverTypes(expr->position(), name, flags); 125 return CollectReceiverTypes(expr->id(), name, flags);
126 } 126 }
127 127
128 128
129 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { 129 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
130 Handle<Object> object = GetElement(map_, expr->position()); 130 Handle<Object> object = GetElement(map_, expr->id());
131 return *object == Builtins::builtin(id); 131 return *object == Builtins::builtin(id);
132 } 132 }
133 133
134 134
135 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr, Side side) { 135 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr, Side side) {
136 Handle<Object> object = GetElement(map_, expr->position()); 136 Handle<Object> object = GetElement(map_, expr->id());
137 TypeInfo unknown = TypeInfo::Unknown(); 137 TypeInfo unknown = TypeInfo::Unknown();
138 if (!object->IsCode()) return unknown; 138 if (!object->IsCode()) return unknown;
139 Handle<Code> code = Handle<Code>::cast(object); 139 Handle<Code> code = Handle<Code>::cast(object);
140 if (!code->is_compare_ic_stub()) return unknown; 140 if (!code->is_compare_ic_stub()) return unknown;
141 141
142 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 142 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
143 switch (state) { 143 switch (state) {
144 case CompareIC::UNINITIALIZED: 144 case CompareIC::UNINITIALIZED:
145 case CompareIC::SMIS: 145 case CompareIC::SMIS:
146 return TypeInfo::Smi(); 146 return TypeInfo::Smi();
147 case CompareIC::HEAP_NUMBERS: 147 case CompareIC::HEAP_NUMBERS:
148 return TypeInfo::Number(); 148 return TypeInfo::Number();
149 case CompareIC::OBJECTS: 149 case CompareIC::OBJECTS:
150 // TODO(kasperl): We really need a type for JS objects here. 150 // TODO(kasperl): We really need a type for JS objects here.
151 return TypeInfo::NonPrimitive(); 151 return TypeInfo::NonPrimitive();
152 case CompareIC::GENERIC: 152 case CompareIC::GENERIC:
153 default: 153 default:
154 return unknown; 154 return unknown;
155 } 155 }
156 } 156 }
157 157
158 158
159 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr, Side side) { 159 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr, Side side) {
160 Handle<Object> object = GetElement(map_, expr->position()); 160 Handle<Object> object = GetElement(map_, expr->id());
161 TypeInfo unknown = TypeInfo::Unknown(); 161 TypeInfo unknown = TypeInfo::Unknown();
162 if (!object->IsCode()) return unknown; 162 if (!object->IsCode()) return unknown;
163 Handle<Code> code = Handle<Code>::cast(object); 163 Handle<Code> code = Handle<Code>::cast(object);
164 if (code->is_binary_op_stub()) { 164 if (code->is_binary_op_stub()) {
165 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 165 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
166 code->binary_op_type()); 166 code->binary_op_type());
167 switch (type) { 167 switch (type) {
168 case BinaryOpIC::UNINIT_OR_SMI: 168 case BinaryOpIC::UNINIT_OR_SMI:
169 return TypeInfo::Smi(); 169 return TypeInfo::Smi();
170 case BinaryOpIC::DEFAULT: 170 case BinaryOpIC::DEFAULT:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 case TRBinaryOpIC::GENERIC: 208 case TRBinaryOpIC::GENERIC:
209 return unknown; 209 return unknown;
210 default: 210 default:
211 return unknown; 211 return unknown;
212 } 212 }
213 } 213 }
214 return unknown; 214 return unknown;
215 } 215 }
216 216
217 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { 217 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
218 Handle<Object> object = GetElement(map_, clause->position()); 218 Handle<Object> object = GetElement(map_, clause->label()->id());
219 TypeInfo unknown = TypeInfo::Unknown(); 219 TypeInfo unknown = TypeInfo::Unknown();
220 if (!object->IsCode()) return unknown; 220 if (!object->IsCode()) return unknown;
221 Handle<Code> code = Handle<Code>::cast(object); 221 Handle<Code> code = Handle<Code>::cast(object);
222 if (!code->is_compare_ic_stub()) return unknown; 222 if (!code->is_compare_ic_stub()) return unknown;
223 223
224 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 224 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
225 switch (state) { 225 switch (state) {
226 case CompareIC::UNINITIALIZED: 226 case CompareIC::UNINITIALIZED:
227 case CompareIC::SMIS: 227 case CompareIC::SMIS:
228 return TypeInfo::Smi(); 228 return TypeInfo::Smi();
229 case CompareIC::HEAP_NUMBERS: 229 case CompareIC::HEAP_NUMBERS:
230 return TypeInfo::Number(); 230 return TypeInfo::Number();
231 case CompareIC::OBJECTS: 231 case CompareIC::OBJECTS:
232 // TODO(kasperl): We really need a type for JS objects here. 232 // TODO(kasperl): We really need a type for JS objects here.
233 return TypeInfo::NonPrimitive(); 233 return TypeInfo::NonPrimitive();
234 case CompareIC::GENERIC: 234 case CompareIC::GENERIC:
235 default: 235 default:
236 return unknown; 236 return unknown;
237 } 237 }
238 } 238 }
239 239
240 240
241 241
242 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, 242 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(AstId id,
243 Handle<String> name, 243 Handle<String> name,
244 Code::Flags flags) { 244 Code::Flags flags) {
245 Handle<Object> object = GetElement(map_, position); 245 Handle<Object> object = GetElement(map_, id);
246 if (object->IsUndefined()) return NULL; 246 if (object->IsUndefined()) return NULL;
247 247
248 if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) { 248 if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) {
249 // TODO(fschneider): We could collect the maps and signal that 249 // TODO(fschneider): We could collect the maps and signal that
250 // we need a generic store (or load) here. 250 // we need a generic store (or load) here.
251 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); 251 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
252 return NULL; 252 return NULL;
253 } else if (object->IsMap()) { 253 } else if (object->IsMap()) {
254 ZoneMapList* types = new ZoneMapList(1); 254 ZoneMapList* types = new ZoneMapList(1);
255 types->Add(Handle<Map>::cast(object)); 255 types->Add(Handle<Map>::cast(object));
256 return types; 256 return types;
257 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { 257 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
258 ZoneMapList* types = new ZoneMapList(4); 258 ZoneMapList* types = new ZoneMapList(4);
259 ASSERT(object->IsCode()); 259 ASSERT(object->IsCode());
260 StubCache::CollectMatchingMaps(types, *name, flags); 260 StubCache::CollectMatchingMaps(types, *name, flags);
261 return types->length() > 0 ? types : NULL; 261 return types->length() > 0 ? types : NULL;
262 } else { 262 } else {
263 return NULL; 263 return NULL;
264 } 264 }
265 } 265 }
266 266
267 267
268 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { 268 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
269 HandleScope scope; 269 HandleScope scope;
270 270
271 const int kInitialCapacity = 16; 271 const int kInitialCapacity = 16;
272 List<int> code_positions(kInitialCapacity); 272 List<int> code_positions(kInitialCapacity);
273 List<int> source_positions(kInitialCapacity); 273 List<AstId> ast_ids(kInitialCapacity);
274 CollectPositions(*code, &code_positions, &source_positions); 274 CollectIds(*code, &code_positions, &ast_ids);
275 275
276 int length = code_positions.length(); 276 const int length = code_positions.length();
277 ASSERT(source_positions.length() == length); 277 ASSERT(ast_ids.length() == length);
278 for (int i = 0; i < length; i++) { 278 for (int i = 0; i < length; i++) {
279 RelocInfo info(code->instruction_start() + code_positions[i], 279 RelocInfo info(code->instruction_start() + code_positions[i],
280 RelocInfo::CODE_TARGET, 0); 280 RelocInfo::CODE_TARGET, 0);
281 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address())); 281 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address()));
282 int position = source_positions[i]; 282 AstId id = ast_ids[i];
283 InlineCacheState state = target->ic_state(); 283 InlineCacheState state = target->ic_state();
284 Code::Kind kind = target->kind(); 284 Code::Kind kind = target->kind();
285 if (kind == Code::BINARY_OP_IC || 285 if (kind == Code::BINARY_OP_IC ||
286 kind == Code::TYPE_RECORDING_BINARY_OP_IC || 286 kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
287 kind == Code::COMPARE_IC) { 287 kind == Code::COMPARE_IC) {
288 // TODO(kasperl): Avoid having multiple ICs with the same 288 SetInfo(id, target);
289 // position by making sure that we have position information
290 // recorded for all binary ICs.
291 if (GetElement(map_, position)->IsUndefined()) {
292 SetElement(map_, position, target);
293 }
294 } else if (state == MONOMORPHIC) { 289 } else if (state == MONOMORPHIC) {
295 Handle<Map> map = Handle<Map>(target->FindFirstMap()); 290 Handle<Map> map = Handle<Map>(target->FindFirstMap());
296 if (*map == NULL) { 291 if (*map == NULL) {
297 SetElement(map_, position, target); 292 SetInfo(id, target);
298 } else { 293 } else {
299 SetElement(map_, position, map); 294 SetInfo(id, map);
300 } 295 }
301 } else if (state == MEGAMORPHIC) { 296 } else if (state == MEGAMORPHIC) {
302 SetElement(map_, position, target); 297 SetInfo(id, target);
303 } 298 }
304 } 299 }
305 } 300 }
306 301
307 302
308 void TypeFeedbackOracle::CollectPositions(Code* code, 303 void TypeFeedbackOracle::CollectIds(Code* code,
309 List<int>* code_positions, 304 List<int>* code_positions,
310 List<int>* source_positions) { 305 List<AstId>* ast_ids) {
311 AssertNoAllocation no_allocation; 306 AssertNoAllocation no_allocation;
312 int position = 0; 307 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
313 // Because the ICs we use for global variables access in the full
314 // code generator do not have any meaningful positions, we avoid
315 // collecting those by filtering out contextual code targets.
316 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
317 RelocInfo::kPositionMask;
318 for (RelocIterator it(code, mask); !it.done(); it.next()) { 308 for (RelocIterator it(code, mask); !it.done(); it.next()) {
319 RelocInfo* info = it.rinfo(); 309 RelocInfo* info = it.rinfo();
320 RelocInfo::Mode mode = info->rmode(); 310 Code* target = Code::GetCodeFromTargetAddress(info->target_address());
321 if (RelocInfo::IsCodeTarget(mode)) { 311 if (target->is_inline_cache_stub()) {
322 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); 312 InlineCacheState state = target->ic_state();
323 if (target->is_inline_cache_stub()) { 313 Code::Kind kind = target->kind();
324 InlineCacheState state = target->ic_state(); 314 if (kind == Code::BINARY_OP_IC) {
325 Code::Kind kind = target->kind(); 315 if (target->binary_op_type() == BinaryOpIC::GENERIC) continue;
326 if (kind == Code::BINARY_OP_IC) { 316 } else if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) {
327 if (target->binary_op_type() == BinaryOpIC::GENERIC) continue; 317 if (target->type_recording_binary_op_type() ==
328 } else if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { 318 TRBinaryOpIC::GENERIC) {
329 if (target->type_recording_binary_op_type() == 319 continue;
330 TRBinaryOpIC::GENERIC) {
331 continue;
332 }
333 } else if (kind == Code::COMPARE_IC) {
334 if (target->compare_state() == CompareIC::GENERIC) continue;
335 } else {
336 if (kind == Code::CALL_IC && state == MONOMORPHIC &&
337 target->check_type() != RECEIVER_MAP_CHECK) continue;
338 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
339 } 320 }
340 code_positions->Add( 321 } else if (kind == Code::COMPARE_IC) {
341 static_cast<int>(info->pc() - code->instruction_start())); 322 if (target->compare_state() == CompareIC::GENERIC) continue;
342 source_positions->Add(position); 323 } else {
324 if (kind == Code::CALL_IC && state == MONOMORPHIC &&
325 target->check_type() != RECEIVER_MAP_CHECK) continue;
326 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
343 } 327 }
344 } else { 328 code_positions->Add(
345 ASSERT(RelocInfo::IsPosition(mode)); 329 static_cast<int>(info->pc() - code->instruction_start()));
346 position = static_cast<int>(info->data()); 330 ast_ids->Add(static_cast<AstId>(info->data()));
347 } 331 }
348 } 332 }
349 } 333 }
350 334
335
336 void TypeFeedbackOracle::SetInfo(AstId id, Handle<Object> info) {
337 ASSERT(GetElement(map_, id)->IsUndefined());
338 SetElement(map_, id, info);
339 }
340
351 } } // namespace v8::internal 341 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698