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

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

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
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') | src/v8.cc » ('j') | 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 Handle<Object> map_or_code(GetInfo(expr->position()));
82 if (map_or_code->IsMap()) return true;
83 if (map_or_code->IsCode()) {
84 Handle<Code> code(Code::cast(*map_or_code));
85 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC &&
86 code->FindFirstMap() != NULL;
87 }
88 return false;
80 } 89 }
81 90
82 91
83 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) { 92 bool TypeFeedbackOracle::StoreIsMonomorphic(Assignment* expr) {
84 return GetElement(map_, expr->position())->IsMap(); 93 Handle<Object> map_or_code(GetInfo(expr->position()));
94 if (map_or_code->IsMap()) return true;
95 if (map_or_code->IsCode()) {
96 Handle<Code> code(Code::cast(*map_or_code));
97 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_STORE_IC &&
98 code->FindFirstMap() != NULL;
99 }
100 return false;
85 } 101 }
86 102
87 103
88 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { 104 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
89 Handle<Object> value = GetElement(map_, expr->position()); 105 Handle<Object> value = GetInfo(expr->position());
90 return value->IsMap() || value->IsSmi(); 106 return value->IsMap() || value->IsSmi();
91 } 107 }
92 108
93 109
94 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { 110 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
95 ASSERT(LoadIsMonomorphic(expr)); 111 ASSERT(LoadIsMonomorphic(expr));
96 return Handle<Map>::cast(GetElement(map_, expr->position())); 112 Handle<Object> map_or_code(
113 Handle<HeapObject>::cast(GetInfo(expr->position())));
114 if (map_or_code->IsCode()) {
115 Handle<Code> code(Code::cast(*map_or_code));
116 return Handle<Map>(code->FindFirstMap());
117 }
118 return Handle<Map>(Map::cast(*map_or_code));
97 } 119 }
98 120
99 121
100 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) { 122 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
101 ASSERT(StoreIsMonomorphic(expr)); 123 ASSERT(StoreIsMonomorphic(expr));
102 return Handle<Map>::cast(GetElement(map_, expr->position())); 124 Handle<HeapObject> map_or_code(
125 Handle<HeapObject>::cast(GetInfo(expr->position())));
126 if (map_or_code->IsCode()) {
127 Handle<Code> code(Code::cast(*map_or_code));
128 return Handle<Map>(code->FindFirstMap());
129 }
130 return Handle<Map>(Map::cast(*map_or_code));
103 } 131 }
104 132
105 133
106 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, 134 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
107 Handle<String> name) { 135 Handle<String> name) {
108 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); 136 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
109 return CollectReceiverTypes(expr->position(), name, flags); 137 return CollectReceiverTypes(expr->position(), name, flags);
110 } 138 }
111 139
112 140
(...skipping 15 matching lines...) Expand all
128 NORMAL, 156 NORMAL,
129 Code::kNoExtraICState, 157 Code::kNoExtraICState,
130 OWN_MAP, 158 OWN_MAP,
131 NOT_IN_LOOP, 159 NOT_IN_LOOP,
132 arity); 160 arity);
133 return CollectReceiverTypes(expr->position(), name, flags); 161 return CollectReceiverTypes(expr->position(), name, flags);
134 } 162 }
135 163
136 164
137 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { 165 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
138 Handle<Object> value = GetElement(map_, expr->position()); 166 Handle<Object> value = GetInfo(expr->position());
139 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; 167 if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
140 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); 168 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
141 ASSERT(check != RECEIVER_MAP_CHECK); 169 ASSERT(check != RECEIVER_MAP_CHECK);
142 return check; 170 return check;
143 } 171 }
144 172
173 ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType(
174 Property* expr) {
175 Handle<Object> stub = GetInfo(expr->position());
176 ASSERT(stub->IsCode());
177 return Code::cast(*stub)->external_array_type();
178 }
179
180 ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType(
181 Assignment* expr) {
182 Handle<Object> stub = GetInfo(expr->position());
183 ASSERT(stub->IsCode());
184 return Code::cast(*stub)->external_array_type();
185 }
145 186
146 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( 187 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
147 CheckType check) { 188 CheckType check) {
148 JSFunction* function = NULL; 189 JSFunction* function = NULL;
149 switch (check) { 190 switch (check) {
150 case RECEIVER_MAP_CHECK: 191 case RECEIVER_MAP_CHECK:
151 UNREACHABLE(); 192 UNREACHABLE();
152 break; 193 break;
153 case STRING_CHECK: 194 case STRING_CHECK:
154 function = global_context_->string_function(); 195 function = global_context_->string_function();
155 break; 196 break;
156 case NUMBER_CHECK: 197 case NUMBER_CHECK:
157 function = global_context_->number_function(); 198 function = global_context_->number_function();
158 break; 199 break;
159 case BOOLEAN_CHECK: 200 case BOOLEAN_CHECK:
160 function = global_context_->boolean_function(); 201 function = global_context_->boolean_function();
161 break; 202 break;
162 } 203 }
163 ASSERT(function != NULL); 204 ASSERT(function != NULL);
164 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); 205 return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
165 } 206 }
166 207
167 208
168 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { 209 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
169 Handle<Object> object = GetElement(map_, expr->position()); 210 return *GetInfo(expr->position()) == Builtins::builtin(id);
170 return *object == Builtins::builtin(id);
171 } 211 }
172 212
173 213
174 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { 214 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
175 Handle<Object> object = GetElement(map_, expr->position()); 215 Handle<Object> object = GetInfo(expr->position());
176 TypeInfo unknown = TypeInfo::Unknown(); 216 TypeInfo unknown = TypeInfo::Unknown();
177 if (!object->IsCode()) return unknown; 217 if (!object->IsCode()) return unknown;
178 Handle<Code> code = Handle<Code>::cast(object); 218 Handle<Code> code = Handle<Code>::cast(object);
179 if (!code->is_compare_ic_stub()) return unknown; 219 if (!code->is_compare_ic_stub()) return unknown;
180 220
181 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 221 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
182 switch (state) { 222 switch (state) {
183 case CompareIC::UNINITIALIZED: 223 case CompareIC::UNINITIALIZED:
184 // Uninitialized means never executed. 224 // Uninitialized means never executed.
185 // TODO(fschneider): Introduce a separate value for never-executed ICs. 225 // TODO(fschneider): Introduce a separate value for never-executed ICs.
186 return unknown; 226 return unknown;
187 case CompareIC::SMIS: 227 case CompareIC::SMIS:
188 return TypeInfo::Smi(); 228 return TypeInfo::Smi();
189 case CompareIC::HEAP_NUMBERS: 229 case CompareIC::HEAP_NUMBERS:
190 return TypeInfo::Number(); 230 return TypeInfo::Number();
191 case CompareIC::OBJECTS: 231 case CompareIC::OBJECTS:
192 // TODO(kasperl): We really need a type for JS objects here. 232 // TODO(kasperl): We really need a type for JS objects here.
193 return TypeInfo::NonPrimitive(); 233 return TypeInfo::NonPrimitive();
194 case CompareIC::GENERIC: 234 case CompareIC::GENERIC:
195 default: 235 default:
196 return unknown; 236 return unknown;
197 } 237 }
198 } 238 }
199 239
200 240
201 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { 241 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) {
202 Handle<Object> object = GetElement(map_, expr->position()); 242 Handle<Object> object = GetInfo(expr->position());
203 TypeInfo unknown = TypeInfo::Unknown(); 243 TypeInfo unknown = TypeInfo::Unknown();
204 if (!object->IsCode()) return unknown; 244 if (!object->IsCode()) return unknown;
205 Handle<Code> code = Handle<Code>::cast(object); 245 Handle<Code> code = Handle<Code>::cast(object);
206 if (code->is_binary_op_stub()) { 246 if (code->is_binary_op_stub()) {
207 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 247 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
208 code->binary_op_type()); 248 code->binary_op_type());
209 switch (type) { 249 switch (type) {
210 case BinaryOpIC::UNINIT_OR_SMI: 250 case BinaryOpIC::UNINIT_OR_SMI:
211 return TypeInfo::Smi(); 251 return TypeInfo::Smi();
212 case BinaryOpIC::DEFAULT: 252 case BinaryOpIC::DEFAULT:
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 return unknown; 294 return unknown;
255 default: 295 default:
256 return unknown; 296 return unknown;
257 } 297 }
258 } 298 }
259 return unknown; 299 return unknown;
260 } 300 }
261 301
262 302
263 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { 303 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
264 Handle<Object> object = GetElement(map_, clause->position()); 304 Handle<Object> object = GetInfo(clause->position());
265 TypeInfo unknown = TypeInfo::Unknown(); 305 TypeInfo unknown = TypeInfo::Unknown();
266 if (!object->IsCode()) return unknown; 306 if (!object->IsCode()) return unknown;
267 Handle<Code> code = Handle<Code>::cast(object); 307 Handle<Code> code = Handle<Code>::cast(object);
268 if (!code->is_compare_ic_stub()) return unknown; 308 if (!code->is_compare_ic_stub()) return unknown;
269 309
270 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 310 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
271 switch (state) { 311 switch (state) {
272 case CompareIC::UNINITIALIZED: 312 case CompareIC::UNINITIALIZED:
273 // Uninitialized means never executed. 313 // Uninitialized means never executed.
274 // TODO(fschneider): Introduce a separate value for never-executed ICs. 314 // TODO(fschneider): Introduce a separate value for never-executed ICs.
275 return unknown; 315 return unknown;
276 case CompareIC::SMIS: 316 case CompareIC::SMIS:
277 return TypeInfo::Smi(); 317 return TypeInfo::Smi();
278 case CompareIC::HEAP_NUMBERS: 318 case CompareIC::HEAP_NUMBERS:
279 return TypeInfo::Number(); 319 return TypeInfo::Number();
280 case CompareIC::OBJECTS: 320 case CompareIC::OBJECTS:
281 // TODO(kasperl): We really need a type for JS objects here. 321 // TODO(kasperl): We really need a type for JS objects here.
282 return TypeInfo::NonPrimitive(); 322 return TypeInfo::NonPrimitive();
283 case CompareIC::GENERIC: 323 case CompareIC::GENERIC:
284 default: 324 default:
285 return unknown; 325 return unknown;
286 } 326 }
287 } 327 }
288 328
289 329
290 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, 330 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position,
291 Handle<String> name, 331 Handle<String> name,
292 Code::Flags flags) { 332 Code::Flags flags) {
293 Handle<Object> object = GetElement(map_, position); 333 Handle<Object> object = GetInfo(position);
294 if (object->IsUndefined() || object->IsSmi()) return NULL; 334 if (object->IsUndefined() || object->IsSmi()) return NULL;
295 335
296 if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) { 336 if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) {
297 // TODO(fschneider): We could collect the maps and signal that 337 // TODO(fschneider): We could collect the maps and signal that
298 // we need a generic store (or load) here. 338 // we need a generic store (or load) here.
299 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); 339 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
300 return NULL; 340 return NULL;
301 } else if (object->IsMap()) { 341 } else if (object->IsMap()) {
302 ZoneMapList* types = new ZoneMapList(1); 342 ZoneMapList* types = new ZoneMapList(1);
303 types->Add(Handle<Map>::cast(object)); 343 types->Add(Handle<Map>::cast(object));
(...skipping 10 matching lines...) Expand all
314 354
315 355
316 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { 356 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
317 HandleScope scope; 357 HandleScope scope;
318 358
319 const int kInitialCapacity = 16; 359 const int kInitialCapacity = 16;
320 List<int> code_positions(kInitialCapacity); 360 List<int> code_positions(kInitialCapacity);
321 List<int> source_positions(kInitialCapacity); 361 List<int> source_positions(kInitialCapacity);
322 CollectPositions(*code, &code_positions, &source_positions); 362 CollectPositions(*code, &code_positions, &source_positions);
323 363
364 ASSERT(dictionary_.is_null()); // Only initialize once.
365 dictionary_ = Factory::NewNumberDictionary(code_positions.length());
366
324 int length = code_positions.length(); 367 int length = code_positions.length();
325 ASSERT(source_positions.length() == length); 368 ASSERT(source_positions.length() == length);
326 for (int i = 0; i < length; i++) { 369 for (int i = 0; i < length; i++) {
370 HandleScope loop_scope;
327 RelocInfo info(code->instruction_start() + code_positions[i], 371 RelocInfo info(code->instruction_start() + code_positions[i],
328 RelocInfo::CODE_TARGET, 0); 372 RelocInfo::CODE_TARGET, 0);
329 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address())); 373 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address()));
330 int position = source_positions[i]; 374 int position = source_positions[i];
331 InlineCacheState state = target->ic_state(); 375 InlineCacheState state = target->ic_state();
332 Code::Kind kind = target->kind(); 376 Code::Kind kind = target->kind();
377 Handle<Object> value;
333 if (kind == Code::BINARY_OP_IC || 378 if (kind == Code::BINARY_OP_IC ||
334 kind == Code::TYPE_RECORDING_BINARY_OP_IC || 379 kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
335 kind == Code::COMPARE_IC) { 380 kind == Code::COMPARE_IC) {
336 // TODO(kasperl): Avoid having multiple ICs with the same 381 // TODO(kasperl): Avoid having multiple ICs with the same
337 // position by making sure that we have position information 382 // position by making sure that we have position information
338 // recorded for all binary ICs. 383 // recorded for all binary ICs.
339 if (GetElement(map_, position)->IsUndefined()) { 384 int entry = dictionary_->FindEntry(position);
340 SetElement(map_, position, target); 385 if (entry == NumberDictionary::kNotFound) {
386 value = target;
341 } 387 }
342 } else if (state == MONOMORPHIC) { 388 } else if (state == MONOMORPHIC) {
343 if (target->kind() != Code::CALL_IC || 389 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC ||
344 target->check_type() == RECEIVER_MAP_CHECK) { 390 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) {
391 value = target;
392 } else if (kind != Code::CALL_IC ||
393 target->check_type() == RECEIVER_MAP_CHECK) {
345 Handle<Map> map = Handle<Map>(target->FindFirstMap()); 394 Handle<Map> map = Handle<Map>(target->FindFirstMap());
346 if (*map == NULL) { 395 if (*map == NULL) {
347 SetElement(map_, position, target); 396 value = target;
348 } else { 397 } else {
349 SetElement(map_, position, map); 398 value = map;
350 } 399 }
351 } else { 400 } else {
352 ASSERT(target->kind() == Code::CALL_IC); 401 ASSERT(target->kind() == Code::CALL_IC);
353 CheckType check = target->check_type(); 402 CheckType check = target->check_type();
354 ASSERT(check != RECEIVER_MAP_CHECK); 403 ASSERT(check != RECEIVER_MAP_CHECK);
355 SetElement(map_, position, Handle<Object>(Smi::FromInt(check))); 404 value = Handle<Object>(Smi::FromInt(check));
356 ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
357 } 405 }
358 } else if (state == MEGAMORPHIC) { 406 } else if (state == MEGAMORPHIC) {
359 SetElement(map_, position, target); 407 value = target;
408 }
409
410 if (!value.is_null()) {
411 Handle<NumberDictionary> new_dict =
412 Factory::DictionaryAtNumberPut(dictionary_, position, value);
413 dictionary_ = loop_scope.CloseAndEscape(new_dict);
360 } 414 }
361 } 415 }
416 // Allocate handle in the parent scope.
417 dictionary_ = scope.CloseAndEscape(dictionary_);
362 } 418 }
363 419
364 420
365 void TypeFeedbackOracle::CollectPositions(Code* code, 421 void TypeFeedbackOracle::CollectPositions(Code* code,
366 List<int>* code_positions, 422 List<int>* code_positions,
367 List<int>* source_positions) { 423 List<int>* source_positions) {
368 AssertNoAllocation no_allocation; 424 AssertNoAllocation no_allocation;
369 int position = 0; 425 int position = 0;
370 // Because the ICs we use for global variables access in the full 426 // Because the ICs we use for global variables access in the full
371 // code generator do not have any meaningful positions, we avoid 427 // code generator do not have any meaningful positions, we avoid
(...skipping 25 matching lines...) Expand all
397 source_positions->Add(position); 453 source_positions->Add(position);
398 } 454 }
399 } else { 455 } else {
400 ASSERT(RelocInfo::IsPosition(mode)); 456 ASSERT(RelocInfo::IsPosition(mode));
401 position = static_cast<int>(info->data()); 457 position = static_cast<int>(info->data());
402 } 458 }
403 } 459 }
404 } 460 }
405 461
406 } } // namespace v8::internal 462 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | src/v8.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698