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

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

Issue 6625054: Make the typefeedback oracle use a NumberDictionary instead of JSObject as it... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months 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 | Annotate | Revision Log
« no previous file with comments | « src/type-info.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 return info; 57 return info;
58 } 58 }
59 59
60 60
61 STATIC_ASSERT(DEFAULT_STRING_STUB == Code::kNoExtraICState); 61 STATIC_ASSERT(DEFAULT_STRING_STUB == Code::kNoExtraICState);
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 Initialize(code); 67 PopulateMap(code);
68 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue);
68 } 69 }
69 70
70 71
71 void TypeFeedbackOracle::Initialize(Handle<Code> code) { 72 Handle<Object> TypeFeedbackOracle::GetInfo(int pos) {
72 ASSERT(map_.is_null()); // Only initialize once. 73 int entry = dictionary_->FindEntry(pos);
73 map_ = Factory::NewJSObject(Top::object_function()); 74 return entry != NumberDictionary::kNotFound
74 PopulateMap(code); 75 ? Handle<Object>(dictionary_->ValueAt(entry))
76 : Factory::undefined_value();
75 } 77 }
76 78
77 79
78 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) { 80 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
79 return GetElement(map_, expr->position())->IsMap(); 81 return GetInfo(expr->position())->IsMap();
80 } 82 }
81 83
82 84
83 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) { 85 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
84 return GetElement(map_, expr->position())->IsMap(); 86 return GetInfo(expr->position())->IsMap();
85 } 87 }
86 88
87 89
88 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { 90 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
89 Handle<Object> value = GetElement(map_, expr->position()); 91 Handle<Object> value = GetInfo(expr->position());
90 return value->IsMap() || value->IsSmi(); 92 return value->IsMap() || value->IsSmi();
91 } 93 }
92 94
93 95
94 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { 96 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
95 ASSERT(LoadIsMonomorphic(expr)); 97 ASSERT(LoadIsMonomorphic(expr));
96 return Handle<Map>::cast(GetElement(map_, expr->position())); 98 return Handle<Map>::cast(GetInfo(expr->position()));
97 } 99 }
98 100
99 101
100 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) { 102 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
101 ASSERT(StoreIsMonomorphic(expr)); 103 ASSERT(StoreIsMonomorphic(expr));
102 return Handle<Map>::cast(GetElement(map_, expr->position())); 104 return Handle<Map>::cast(GetInfo(expr->position()));
103 } 105 }
104 106
105 107
106 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, 108 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
107 Handle<String> name) { 109 Handle<String> name) {
108 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); 110 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
109 return CollectReceiverTypes(expr->position(), name, flags); 111 return CollectReceiverTypes(expr->position(), name, flags);
110 } 112 }
111 113
112 114
(...skipping 15 matching lines...) Expand all
128 NORMAL, 130 NORMAL,
129 Code::kNoExtraICState, 131 Code::kNoExtraICState,
130 OWN_MAP, 132 OWN_MAP,
131 NOT_IN_LOOP, 133 NOT_IN_LOOP,
132 arity); 134 arity);
133 return CollectReceiverTypes(expr->position(), name, flags); 135 return CollectReceiverTypes(expr->position(), name, flags);
134 } 136 }
135 137
136 138
137 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { 139 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
138 Handle<Object> value = GetElement(map_, expr->position()); 140 Handle<Object> value = GetInfo(expr->position());
139 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; 141 if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
140 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); 142 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
141 ASSERT(check != RECEIVER_MAP_CHECK); 143 ASSERT(check != RECEIVER_MAP_CHECK);
142 return check; 144 return check;
143 } 145 }
144 146
145 147
146 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( 148 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
147 CheckType check) { 149 CheckType check) {
148 JSFunction* function = NULL; 150 JSFunction* function = NULL;
(...skipping 10 matching lines...) Expand all
159 case BOOLEAN_CHECK: 161 case BOOLEAN_CHECK:
160 function = global_context_->boolean_function(); 162 function = global_context_->boolean_function();
161 break; 163 break;
162 } 164 }
163 ASSERT(function != NULL); 165 ASSERT(function != NULL);
164 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); 166 return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
165 } 167 }
166 168
167 169
168 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { 170 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
169 Handle<Object> object = GetElement(map_, expr->position()); 171 return *GetInfo(expr->position()) == Builtins::builtin(id);
170 return *object == Builtins::builtin(id);
171 } 172 }
172 173
173 174
174 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { 175 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
175 Handle<Object> object = GetElement(map_, expr->position()); 176 Handle<Object> object = GetInfo(expr->position());
176 TypeInfo unknown = TypeInfo::Unknown(); 177 TypeInfo unknown = TypeInfo::Unknown();
177 if (!object->IsCode()) return unknown; 178 if (!object->IsCode()) return unknown;
178 Handle<Code> code = Handle<Code>::cast(object); 179 Handle<Code> code = Handle<Code>::cast(object);
179 if (!code->is_compare_ic_stub()) return unknown; 180 if (!code->is_compare_ic_stub()) return unknown;
180 181
181 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 182 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
182 switch (state) { 183 switch (state) {
183 case CompareIC::UNINITIALIZED: 184 case CompareIC::UNINITIALIZED:
184 // Uninitialized means never executed. 185 // Uninitialized means never executed.
185 // TODO(fschneider): Introduce a separate value for never-executed ICs. 186 // TODO(fschneider): Introduce a separate value for never-executed ICs.
186 return unknown; 187 return unknown;
187 case CompareIC::SMIS: 188 case CompareIC::SMIS:
188 return TypeInfo::Smi(); 189 return TypeInfo::Smi();
189 case CompareIC::HEAP_NUMBERS: 190 case CompareIC::HEAP_NUMBERS:
190 return TypeInfo::Number(); 191 return TypeInfo::Number();
191 case CompareIC::OBJECTS: 192 case CompareIC::OBJECTS:
192 // TODO(kasperl): We really need a type for JS objects here. 193 // TODO(kasperl): We really need a type for JS objects here.
193 return TypeInfo::NonPrimitive(); 194 return TypeInfo::NonPrimitive();
194 case CompareIC::GENERIC: 195 case CompareIC::GENERIC:
195 default: 196 default:
196 return unknown; 197 return unknown;
197 } 198 }
198 } 199 }
199 200
200 201
201 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { 202 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) {
202 Handle<Object> object = GetElement(map_, expr->position()); 203 Handle<Object> object = GetInfo(expr->position());
203 TypeInfo unknown = TypeInfo::Unknown(); 204 TypeInfo unknown = TypeInfo::Unknown();
204 if (!object->IsCode()) return unknown; 205 if (!object->IsCode()) return unknown;
205 Handle<Code> code = Handle<Code>::cast(object); 206 Handle<Code> code = Handle<Code>::cast(object);
206 if (code->is_binary_op_stub()) { 207 if (code->is_binary_op_stub()) {
207 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 208 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
208 code->binary_op_type()); 209 code->binary_op_type());
209 switch (type) { 210 switch (type) {
210 case BinaryOpIC::UNINIT_OR_SMI: 211 case BinaryOpIC::UNINIT_OR_SMI:
211 return TypeInfo::Smi(); 212 return TypeInfo::Smi();
212 case BinaryOpIC::DEFAULT: 213 case BinaryOpIC::DEFAULT:
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 return unknown; 255 return unknown;
255 default: 256 default:
256 return unknown; 257 return unknown;
257 } 258 }
258 } 259 }
259 return unknown; 260 return unknown;
260 } 261 }
261 262
262 263
263 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { 264 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
264 Handle<Object> object = GetElement(map_, clause->position()); 265 Handle<Object> object = GetInfo(clause->position());
265 TypeInfo unknown = TypeInfo::Unknown(); 266 TypeInfo unknown = TypeInfo::Unknown();
266 if (!object->IsCode()) return unknown; 267 if (!object->IsCode()) return unknown;
267 Handle<Code> code = Handle<Code>::cast(object); 268 Handle<Code> code = Handle<Code>::cast(object);
268 if (!code->is_compare_ic_stub()) return unknown; 269 if (!code->is_compare_ic_stub()) return unknown;
269 270
270 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 271 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
271 switch (state) { 272 switch (state) {
272 case CompareIC::UNINITIALIZED: 273 case CompareIC::UNINITIALIZED:
273 // Uninitialized means never executed. 274 // Uninitialized means never executed.
274 // TODO(fschneider): Introduce a separate value for never-executed ICs. 275 // TODO(fschneider): Introduce a separate value for never-executed ICs.
275 return unknown; 276 return unknown;
276 case CompareIC::SMIS: 277 case CompareIC::SMIS:
277 return TypeInfo::Smi(); 278 return TypeInfo::Smi();
278 case CompareIC::HEAP_NUMBERS: 279 case CompareIC::HEAP_NUMBERS:
279 return TypeInfo::Number(); 280 return TypeInfo::Number();
280 case CompareIC::OBJECTS: 281 case CompareIC::OBJECTS:
281 // TODO(kasperl): We really need a type for JS objects here. 282 // TODO(kasperl): We really need a type for JS objects here.
282 return TypeInfo::NonPrimitive(); 283 return TypeInfo::NonPrimitive();
283 case CompareIC::GENERIC: 284 case CompareIC::GENERIC:
284 default: 285 default:
285 return unknown; 286 return unknown;
286 } 287 }
287 } 288 }
288 289
289 290
290 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, 291 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position,
291 Handle<String> name, 292 Handle<String> name,
292 Code::Flags flags) { 293 Code::Flags flags) {
293 Handle<Object> object = GetElement(map_, position); 294 Handle<Object> object = GetInfo(position);
294 if (object->IsUndefined() || object->IsSmi()) return NULL; 295 if (object->IsUndefined() || object->IsSmi()) return NULL;
295 296
296 if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) { 297 if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) {
297 // TODO(fschneider): We could collect the maps and signal that 298 // TODO(fschneider): We could collect the maps and signal that
298 // we need a generic store (or load) here. 299 // we need a generic store (or load) here.
299 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); 300 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
300 return NULL; 301 return NULL;
301 } else if (object->IsMap()) { 302 } else if (object->IsMap()) {
302 ZoneMapList* types = new ZoneMapList(1); 303 ZoneMapList* types = new ZoneMapList(1);
303 types->Add(Handle<Map>::cast(object)); 304 types->Add(Handle<Map>::cast(object));
(...skipping 10 matching lines...) Expand all
314 315
315 316
316 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { 317 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
317 HandleScope scope; 318 HandleScope scope;
318 319
319 const int kInitialCapacity = 16; 320 const int kInitialCapacity = 16;
320 List<int> code_positions(kInitialCapacity); 321 List<int> code_positions(kInitialCapacity);
321 List<int> source_positions(kInitialCapacity); 322 List<int> source_positions(kInitialCapacity);
322 CollectPositions(*code, &code_positions, &source_positions); 323 CollectPositions(*code, &code_positions, &source_positions);
323 324
325 ASSERT(dictionary_.is_null()); // Only initialize once.
326 dictionary_ = Factory::NewNumberDictionary(code_positions.length());
327
324 int length = code_positions.length(); 328 int length = code_positions.length();
325 ASSERT(source_positions.length() == length); 329 ASSERT(source_positions.length() == length);
326 for (int i = 0; i < length; i++) { 330 for (int i = 0; i < length; i++) {
331 HandleScope loop_scope;
327 RelocInfo info(code->instruction_start() + code_positions[i], 332 RelocInfo info(code->instruction_start() + code_positions[i],
328 RelocInfo::CODE_TARGET, 0); 333 RelocInfo::CODE_TARGET, 0);
329 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address())); 334 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address()));
330 int position = source_positions[i]; 335 int position = source_positions[i];
331 InlineCacheState state = target->ic_state(); 336 InlineCacheState state = target->ic_state();
332 Code::Kind kind = target->kind(); 337 Code::Kind kind = target->kind();
338 Handle<Object> value;
333 if (kind == Code::BINARY_OP_IC || 339 if (kind == Code::BINARY_OP_IC ||
334 kind == Code::TYPE_RECORDING_BINARY_OP_IC || 340 kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
335 kind == Code::COMPARE_IC) { 341 kind == Code::COMPARE_IC) {
336 // TODO(kasperl): Avoid having multiple ICs with the same 342 // TODO(kasperl): Avoid having multiple ICs with the same
337 // position by making sure that we have position information 343 // position by making sure that we have position information
338 // recorded for all binary ICs. 344 // recorded for all binary ICs.
339 if (GetElement(map_, position)->IsUndefined()) { 345 int entry = dictionary_->FindEntry(position);
340 SetElement(map_, position, target, kNonStrictMode); 346 if (entry == NumberDictionary::kNotFound) {
347 value = target;
341 } 348 }
342 } else if (state == MONOMORPHIC) { 349 } else if (state == MONOMORPHIC) {
343 if (target->kind() != Code::CALL_IC || 350 if (target->kind() != Code::CALL_IC ||
344 target->check_type() == RECEIVER_MAP_CHECK) { 351 target->check_type() == RECEIVER_MAP_CHECK) {
345 Handle<Map> map = Handle<Map>(target->FindFirstMap()); 352 Handle<Map> map = Handle<Map>(target->FindFirstMap());
346 if (*map == NULL) { 353 if (*map == NULL) {
347 SetElement(map_, position, target, kNonStrictMode); 354 value = target;
348 } else { 355 } else {
349 SetElement(map_, position, map, kNonStrictMode); 356 value = map;
350 } 357 }
351 } else { 358 } else {
352 ASSERT(target->kind() == Code::CALL_IC); 359 ASSERT(target->kind() == Code::CALL_IC);
353 CheckType check = target->check_type(); 360 CheckType check = target->check_type();
354 ASSERT(check != RECEIVER_MAP_CHECK); 361 ASSERT(check != RECEIVER_MAP_CHECK);
355 SetElement(map_, position, 362 value = Handle<Object>(Smi::FromInt(check));
356 Handle<Object>(Smi::FromInt(check)), kNonStrictMode);
357 ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
358 } 363 }
359 } else if (state == MEGAMORPHIC) { 364 } else if (state == MEGAMORPHIC) {
360 SetElement(map_, position, target, kNonStrictMode); 365 value = target;
366 }
367
368 if (!value.is_null()) {
369 Handle<NumberDictionary> new_dict =
370 Factory::DictionaryAtNumberPut(dictionary_, position, value);
371 dictionary_ = loop_scope.CloseAndEscape(new_dict);
361 } 372 }
362 } 373 }
374 // Allocate handle in the parent scope.
375 dictionary_ = scope.CloseAndEscape(dictionary_);
363 } 376 }
364 377
365 378
366 void TypeFeedbackOracle::CollectPositions(Code* code, 379 void TypeFeedbackOracle::CollectPositions(Code* code,
367 List<int>* code_positions, 380 List<int>* code_positions,
368 List<int>* source_positions) { 381 List<int>* source_positions) {
369 AssertNoAllocation no_allocation; 382 AssertNoAllocation no_allocation;
370 int position = 0; 383 int position = 0;
371 // Because the ICs we use for global variables access in the full 384 // Because the ICs we use for global variables access in the full
372 // code generator do not have any meaningful positions, we avoid 385 // code generator do not have any meaningful positions, we avoid
(...skipping 25 matching lines...) Expand all
398 source_positions->Add(position); 411 source_positions->Add(position);
399 } 412 }
400 } else { 413 } else {
401 ASSERT(RelocInfo::IsPosition(mode)); 414 ASSERT(RelocInfo::IsPosition(mode));
402 position = static_cast<int>(info->data()); 415 position = static_cast<int>(info->data());
403 } 416 }
404 } 417 }
405 } 418 }
406 419
407 } } // namespace v8::internal 420 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698