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

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

Issue 8974009: Fix bug with filtering of foreign context maps in the type feedback. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | test/cctest/cctest.status » ('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 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 78
79 79
80 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { 80 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) {
81 Handle<Object> map_or_code = GetInfo(expr->id()); 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 = Handle<Code>::cast(map_or_code); 84 Handle<Code> code = Handle<Code>::cast(map_or_code);
85 return code->is_keyed_load_stub() && 85 return code->is_keyed_load_stub() &&
86 code->ic_state() == MONOMORPHIC && 86 code->ic_state() == MONOMORPHIC &&
87 Code::ExtractTypeFromFlags(code->flags()) == NORMAL && 87 Code::ExtractTypeFromFlags(code->flags()) == NORMAL &&
88 code->FindFirstMap() != NULL; 88 code->FindFirstMap() != NULL &&
89 !CanRetainOtherContext(code->FindFirstMap(), *global_context_);
89 } 90 }
90 return false; 91 return false;
91 } 92 }
92 93
93 94
94 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) { 95 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) {
95 Handle<Object> map_or_code = GetInfo(expr->id()); 96 Handle<Object> map_or_code = GetInfo(expr->id());
96 if (map_or_code->IsCode()) { 97 if (map_or_code->IsCode()) {
97 Handle<Code> code = Handle<Code>::cast(map_or_code); 98 Handle<Code> code = Handle<Code>::cast(map_or_code);
98 Builtins* builtins = isolate_->builtins(); 99 Builtins* builtins = isolate_->builtins();
99 return code->is_keyed_load_stub() && 100 return code->is_keyed_load_stub() &&
100 *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) && 101 *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) &&
101 code->ic_state() == MEGAMORPHIC; 102 code->ic_state() == MEGAMORPHIC;
102 } 103 }
103 return false; 104 return false;
104 } 105 }
105 106
106 107
107 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) { 108 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) {
108 Handle<Object> map_or_code = GetInfo(expr->id()); 109 Handle<Object> map_or_code = GetInfo(expr->id());
109 if (map_or_code->IsMap()) return true; 110 if (map_or_code->IsMap()) return true;
110 if (map_or_code->IsCode()) { 111 if (map_or_code->IsCode()) {
111 Handle<Code> code = Handle<Code>::cast(map_or_code); 112 Handle<Code> code = Handle<Code>::cast(map_or_code);
112 return code->is_keyed_store_stub() && 113 return code->is_keyed_store_stub() &&
113 code->ic_state() == MONOMORPHIC && 114 code->ic_state() == MONOMORPHIC &&
114 Code::ExtractTypeFromFlags(code->flags()) == NORMAL; 115 Code::ExtractTypeFromFlags(code->flags()) == NORMAL &&
116 code->FindFirstMap() != NULL &&
117 !CanRetainOtherContext(code->FindFirstMap(), *global_context_);
115 } 118 }
116 return false; 119 return false;
117 } 120 }
118 121
119 122
120 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(Expression* expr) { 123 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(Expression* expr) {
121 Handle<Object> map_or_code = GetInfo(expr->id()); 124 Handle<Object> map_or_code = GetInfo(expr->id());
122 if (map_or_code->IsCode()) { 125 if (map_or_code->IsCode()) {
123 Handle<Code> code = Handle<Code>::cast(map_or_code); 126 Handle<Code> code = Handle<Code>::cast(map_or_code);
124 Builtins* builtins = isolate_->builtins(); 127 Builtins* builtins = isolate_->builtins();
(...skipping 12 matching lines...) Expand all
137 } 140 }
138 141
139 142
140 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { 143 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
141 ASSERT(LoadIsMonomorphicNormal(expr)); 144 ASSERT(LoadIsMonomorphicNormal(expr));
142 Handle<Object> map_or_code = GetInfo(expr->id()); 145 Handle<Object> map_or_code = GetInfo(expr->id());
143 if (map_or_code->IsCode()) { 146 if (map_or_code->IsCode()) {
144 Handle<Code> code = Handle<Code>::cast(map_or_code); 147 Handle<Code> code = Handle<Code>::cast(map_or_code);
145 Map* first_map = code->FindFirstMap(); 148 Map* first_map = code->FindFirstMap();
146 ASSERT(first_map != NULL); 149 ASSERT(first_map != NULL);
147 return Handle<Map>(first_map); 150 return CanRetainOtherContext(first_map, *global_context_)
151 ? Handle<Map>::null()
152 : Handle<Map>(first_map);
148 } 153 }
149 return Handle<Map>::cast(map_or_code); 154 return Handle<Map>::cast(map_or_code);
150 } 155 }
151 156
152 157
153 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { 158 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) {
154 ASSERT(StoreIsMonomorphicNormal(expr)); 159 ASSERT(StoreIsMonomorphicNormal(expr));
155 Handle<Object> map_or_code = GetInfo(expr->id()); 160 Handle<Object> map_or_code = GetInfo(expr->id());
156 if (map_or_code->IsCode()) { 161 if (map_or_code->IsCode()) {
157 Handle<Code> code = Handle<Code>::cast(map_or_code); 162 Handle<Code> code = Handle<Code>::cast(map_or_code);
158 return Handle<Map>(code->FindFirstMap()); 163 Map* first_map = code->FindFirstMap();
164 ASSERT(first_map != NULL);
165 return CanRetainOtherContext(first_map, *global_context_)
166 ? Handle<Map>::null()
167 : Handle<Map>(first_map);
159 } 168 }
160 return Handle<Map>::cast(map_or_code); 169 return Handle<Map>::cast(map_or_code);
161 } 170 }
162 171
163 172
164 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr, 173 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
165 Handle<String> name, 174 Handle<String> name,
166 SmallMapList* types) { 175 SmallMapList* types) {
167 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); 176 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
168 CollectReceiverTypes(expr->id(), name, flags, types); 177 CollectReceiverTypes(expr->id(), name, flags, types);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 290
282 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { 291 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) {
283 Handle<Object> object = GetInfo(expr->id()); 292 Handle<Object> object = GetInfo(expr->id());
284 if (!object->IsCode()) return Handle<Map>::null(); 293 if (!object->IsCode()) return Handle<Map>::null();
285 Handle<Code> code = Handle<Code>::cast(object); 294 Handle<Code> code = Handle<Code>::cast(object);
286 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); 295 if (!code->is_compare_ic_stub()) return Handle<Map>::null();
287 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 296 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
288 if (state != CompareIC::KNOWN_OBJECTS) { 297 if (state != CompareIC::KNOWN_OBJECTS) {
289 return Handle<Map>::null(); 298 return Handle<Map>::null();
290 } 299 }
291 return Handle<Map>(code->FindFirstMap()); 300 Map* first_map = code->FindFirstMap();
301 ASSERT(first_map != NULL);
302 return CanRetainOtherContext(first_map, *global_context_)
303 ? Handle<Map>::null()
304 : Handle<Map>(first_map);
292 } 305 }
293 306
294 307
295 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { 308 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) {
296 Handle<Object> object = GetInfo(expr->id()); 309 Handle<Object> object = GetInfo(expr->id());
297 TypeInfo unknown = TypeInfo::Unknown(); 310 TypeInfo unknown = TypeInfo::Unknown();
298 if (!object->IsCode()) return unknown; 311 if (!object->IsCode()) return unknown;
299 Handle<Code> code = Handle<Code>::cast(object); 312 Handle<Code> code = Handle<Code>::cast(object);
300 ASSERT(code->is_unary_op_stub()); 313 ASSERT(code->is_unary_op_stub());
301 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( 314 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>(
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 global_context_); 457 global_context_);
445 } 458 }
446 } 459 }
447 460
448 461
449 // Check if a map originates from a given global context. We use this 462 // Check if a map originates from a given global context. We use this
450 // information to filter out maps from different context to avoid 463 // information to filter out maps from different context to avoid
451 // retaining objects from different tabs in Chrome via optimized code. 464 // retaining objects from different tabs in Chrome via optimized code.
452 bool TypeFeedbackOracle::CanRetainOtherContext(Map* map, 465 bool TypeFeedbackOracle::CanRetainOtherContext(Map* map,
453 Context* global_context) { 466 Context* global_context) {
454 Object* constructor = map->constructor(); 467 Object* constructor = NULL;
455 ASSERT(constructor != NULL); 468 while (!map->prototype()->IsNull()) {
456 while (!constructor->IsJSFunction()) {
457 // If the constructor is not null or a JSFunction, we have to
458 // conservatively assume that it may retain a global context.
459 if (!constructor->IsNull()) return true;
460
461 // If both, constructor and prototype are null, we conclude
462 // that no global context will be retained by this map.
463 if (map->prototype()->IsNull()) return false;
464
465 map = JSObject::cast(map->prototype())->map();
466 constructor = map->constructor(); 469 constructor = map->constructor();
470 if (!constructor->IsNull()) {
471 // If the constructor is not null or a JSFunction, we have to
472 // conservatively assume that it may retain a global context.
473 if (!constructor->IsJSFunction()) return true;
474 // Check if the constructor directly references a foreign context.
475 if (CanRetainOtherContext(JSFunction::cast(constructor),
476 global_context)) {
477 return true;
478 }
479 }
480 map = HeapObject::cast(map->prototype())->map();
467 } 481 }
482 constructor = map->constructor();
483 if (constructor->IsNull()) return false;
468 JSFunction* function = JSFunction::cast(constructor); 484 JSFunction* function = JSFunction::cast(constructor);
469 return CanRetainOtherContext(function, global_context); 485 return CanRetainOtherContext(function, global_context);
470 } 486 }
471 487
472 488
473 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function, 489 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function,
474 Context* global_context) { 490 Context* global_context) {
475 return function->context()->global() != global_context->global() 491 return function->context()->global() != global_context->global()
476 && function->context()->global() != global_context->builtins(); 492 && function->context()->global() != global_context->builtins();
477 } 493 }
(...skipping 13 matching lines...) Expand all
491 if (!object->IsCode()) return; 507 if (!object->IsCode()) return;
492 Handle<Code> code = Handle<Code>::cast(object); 508 Handle<Code> code = Handle<Code>::cast(object);
493 if (code->kind() == Code::KEYED_LOAD_IC || 509 if (code->kind() == Code::KEYED_LOAD_IC ||
494 code->kind() == Code::KEYED_STORE_IC) { 510 code->kind() == Code::KEYED_STORE_IC) {
495 AssertNoAllocation no_allocation; 511 AssertNoAllocation no_allocation;
496 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); 512 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
497 for (RelocIterator it(*code, mask); !it.done(); it.next()) { 513 for (RelocIterator it(*code, mask); !it.done(); it.next()) {
498 RelocInfo* info = it.rinfo(); 514 RelocInfo* info = it.rinfo();
499 Object* object = info->target_object(); 515 Object* object = info->target_object();
500 if (object->IsMap()) { 516 if (object->IsMap()) {
501 AddMapIfMissing(Handle<Map>(Map::cast(object)), types); 517 Map* map = Map::cast(object);
518 if (!CanRetainOtherContext(map, *global_context_)) {
519 AddMapIfMissing(Handle<Map>(map), types);
520 }
502 } 521 }
503 } 522 }
504 } 523 }
505 } 524 }
506 525
507 526
508 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) { 527 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) {
509 Handle<Object> object = GetInfo(ast_id); 528 Handle<Object> object = GetInfo(ast_id);
510 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; 529 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
511 } 530 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 USE(maybe_result); 644 USE(maybe_result);
626 #ifdef DEBUG 645 #ifdef DEBUG
627 Object* result = NULL; 646 Object* result = NULL;
628 // Dictionary has been allocated with sufficient size for all elements. 647 // Dictionary has been allocated with sufficient size for all elements.
629 ASSERT(maybe_result->ToObject(&result)); 648 ASSERT(maybe_result->ToObject(&result));
630 ASSERT(*dictionary_ == result); 649 ASSERT(*dictionary_ == result);
631 #endif 650 #endif
632 } 651 }
633 652
634 } } // namespace v8::internal 653 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/cctest/cctest.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698