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

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

Issue 8974013: Merge r10257 and r10277 to the 3.7 branch: Fix leak of global objects from optimized code. (Closed) Base URL: http://v8.googlecode.com/svn/branches/3.7/
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 | « src/type-info.h ('k') | src/version.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 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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { 425 isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) {
417 // TODO(fschneider): We could collect the maps and signal that 426 // TODO(fschneider): We could collect the maps and signal that
418 // we need a generic store (or load) here. 427 // we need a generic store (or load) here.
419 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); 428 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
420 } else if (object->IsMap()) { 429 } else if (object->IsMap()) {
421 types->Add(Handle<Map>::cast(object)); 430 types->Add(Handle<Map>::cast(object));
422 } else if (FLAG_collect_megamorphic_maps_from_stub_cache && 431 } else if (FLAG_collect_megamorphic_maps_from_stub_cache &&
423 Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { 432 Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
424 types->Reserve(4); 433 types->Reserve(4);
425 ASSERT(object->IsCode()); 434 ASSERT(object->IsCode());
426 isolate_->stub_cache()->CollectMatchingMaps(types, *name, flags); 435 isolate_->stub_cache()->CollectMatchingMaps(types,
436 *name,
437 flags,
438 global_context_);
427 } 439 }
428 } 440 }
429 441
430 442
443 // Check if a map originates from a given global context. We use this
444 // information to filter out maps from different context to avoid
445 // retaining objects from different tabs in Chrome via optimized code.
446 bool TypeFeedbackOracle::CanRetainOtherContext(Map* map,
447 Context* global_context) {
448 Object* constructor = NULL;
449 while (!map->prototype()->IsNull()) {
450 constructor = map->constructor();
451 if (!constructor->IsNull()) {
452 // If the constructor is not null or a JSFunction, we have to
453 // conservatively assume that it may retain a global context.
454 if (!constructor->IsJSFunction()) return true;
455 // Check if the constructor directly references a foreign context.
456 if (CanRetainOtherContext(JSFunction::cast(constructor),
457 global_context)) {
458 return true;
459 }
460 }
461 map = HeapObject::cast(map->prototype())->map();
462 }
463 constructor = map->constructor();
464 if (constructor->IsNull()) return false;
465 JSFunction* function = JSFunction::cast(constructor);
466 return CanRetainOtherContext(function, global_context);
467 }
468
469
470 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function,
471 Context* global_context) {
472 return function->context()->global() != global_context->global()
473 && function->context()->global() != global_context->builtins();
474 }
475
476
431 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list) { 477 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list) {
432 for (int i = 0; i < list->length(); ++i) { 478 for (int i = 0; i < list->length(); ++i) {
433 if (list->at(i).is_identical_to(map)) return; 479 if (list->at(i).is_identical_to(map)) return;
434 } 480 }
435 list->Add(map); 481 list->Add(map);
436 } 482 }
437 483
438 484
439 void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id, 485 void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id,
440 SmallMapList* types) { 486 SmallMapList* types) {
441 Handle<Object> object = GetInfo(ast_id); 487 Handle<Object> object = GetInfo(ast_id);
442 if (!object->IsCode()) return; 488 if (!object->IsCode()) return;
443 Handle<Code> code = Handle<Code>::cast(object); 489 Handle<Code> code = Handle<Code>::cast(object);
444 if (code->kind() == Code::KEYED_LOAD_IC || 490 if (code->kind() == Code::KEYED_LOAD_IC ||
445 code->kind() == Code::KEYED_STORE_IC) { 491 code->kind() == Code::KEYED_STORE_IC) {
446 AssertNoAllocation no_allocation; 492 AssertNoAllocation no_allocation;
447 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); 493 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
448 for (RelocIterator it(*code, mask); !it.done(); it.next()) { 494 for (RelocIterator it(*code, mask); !it.done(); it.next()) {
449 RelocInfo* info = it.rinfo(); 495 RelocInfo* info = it.rinfo();
450 Object* object = info->target_object(); 496 Object* object = info->target_object();
451 if (object->IsMap()) { 497 if (object->IsMap()) {
452 AddMapIfMissing(Handle<Map>(Map::cast(object)), types); 498 Map* map = Map::cast(object);
499 if (!CanRetainOtherContext(map, *global_context_)) {
500 AddMapIfMissing(Handle<Map>(map), types);
501 }
453 } 502 }
454 } 503 }
455 } 504 }
456 } 505 }
457 506
458 507
459 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) { 508 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) {
460 Handle<Object> object = GetInfo(ast_id); 509 Handle<Object> object = GetInfo(ast_id);
461 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; 510 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
462 } 511 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 case Code::LOAD_IC: 566 case Code::LOAD_IC:
518 case Code::STORE_IC: 567 case Code::STORE_IC:
519 case Code::CALL_IC: 568 case Code::CALL_IC:
520 case Code::KEYED_CALL_IC: 569 case Code::KEYED_CALL_IC:
521 if (target->ic_state() == MONOMORPHIC) { 570 if (target->ic_state() == MONOMORPHIC) {
522 if (target->kind() == Code::CALL_IC && 571 if (target->kind() == Code::CALL_IC &&
523 target->check_type() != RECEIVER_MAP_CHECK) { 572 target->check_type() != RECEIVER_MAP_CHECK) {
524 SetInfo(ast_id, Smi::FromInt(target->check_type())); 573 SetInfo(ast_id, Smi::FromInt(target->check_type()));
525 } else { 574 } else {
526 Object* map = target->FindFirstMap(); 575 Object* map = target->FindFirstMap();
527 SetInfo(ast_id, map == NULL ? static_cast<Object*>(target) : map); 576 if (map == NULL) {
577 SetInfo(ast_id, static_cast<Object*>(target));
578 } else if (!CanRetainOtherContext(Map::cast(map),
579 *global_context_)) {
580 SetInfo(ast_id, map);
581 }
528 } 582 }
529 } else if (target->ic_state() == MEGAMORPHIC) { 583 } else if (target->ic_state() == MEGAMORPHIC) {
530 SetInfo(ast_id, target); 584 SetInfo(ast_id, target);
531 } 585 }
532 break; 586 break;
533 587
534 case Code::KEYED_LOAD_IC: 588 case Code::KEYED_LOAD_IC:
535 case Code::KEYED_STORE_IC: 589 case Code::KEYED_STORE_IC:
536 if (target->ic_state() == MONOMORPHIC || 590 if (target->ic_state() == MONOMORPHIC ||
537 target->ic_state() == MEGAMORPHIC) { 591 target->ic_state() == MEGAMORPHIC) {
538 SetInfo(ast_id, target); 592 SetInfo(ast_id, target);
539 } 593 }
540 break; 594 break;
541 595
542 case Code::UNARY_OP_IC: 596 case Code::UNARY_OP_IC:
543 case Code::BINARY_OP_IC: 597 case Code::BINARY_OP_IC:
544 case Code::COMPARE_IC: 598 case Code::COMPARE_IC:
545 case Code::TO_BOOLEAN_IC: 599 case Code::TO_BOOLEAN_IC:
546 SetInfo(ast_id, target); 600 SetInfo(ast_id, target);
547 break; 601 break;
548 602
549 case Code::STUB: 603 case Code::STUB:
550 if (target->major_key() == CodeStub::CallFunction && 604 if (target->major_key() == CodeStub::CallFunction &&
551 target->has_function_cache()) { 605 target->has_function_cache()) {
552 Object* value = CallFunctionStub::GetCachedValue(reloc_entry.pc()); 606 Object* value = CallFunctionStub::GetCachedValue(reloc_entry.pc());
553 if (value->IsJSFunction()) { 607 if (value->IsJSFunction() &&
608 !CanRetainOtherContext(JSFunction::cast(value),
609 *global_context_)) {
554 SetInfo(ast_id, value); 610 SetInfo(ast_id, value);
555 } 611 }
556 } 612 }
557 break; 613 break;
558 614
559 default: 615 default:
560 break; 616 break;
561 } 617 }
562 } 618 }
563 } 619 }
564 620
565 621
566 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { 622 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) {
567 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound); 623 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound);
568 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); 624 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target);
569 USE(maybe_result); 625 USE(maybe_result);
570 #ifdef DEBUG 626 #ifdef DEBUG
571 Object* result = NULL; 627 Object* result = NULL;
572 // Dictionary has been allocated with sufficient size for all elements. 628 // Dictionary has been allocated with sufficient size for all elements.
573 ASSERT(maybe_result->ToObject(&result)); 629 ASSERT(maybe_result->ToObject(&result));
574 ASSERT(*dictionary_ == result); 630 ASSERT(*dictionary_ == result);
575 #endif 631 #endif
576 } 632 }
577 633
578 } } // namespace v8::internal 634 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | src/version.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698