Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 29 matching lines...) Expand all Loading... | |
| 40 | 40 |
| 41 namespace v8 { | 41 namespace v8 { |
| 42 namespace internal { | 42 namespace internal { |
| 43 | 43 |
| 44 | 44 |
| 45 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 45 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
| 46 Handle<Context> native_context, | 46 Handle<Context> native_context, |
| 47 Zone* zone) | 47 Zone* zone) |
| 48 : native_context_(native_context), | 48 : native_context_(native_context), |
| 49 zone_(zone) { | 49 zone_(zone) { |
| 50 Object* raw_info = code->type_feedback_info(); | |
| 51 if (raw_info->IsTypeFeedbackInfo()) { | |
| 52 feedback_vector_ = Handle<FixedArray>(TypeFeedbackInfo::cast(raw_info)-> | |
| 53 feedback_vector()); | |
| 54 } | |
| 55 | |
| 50 BuildDictionary(code); | 56 BuildDictionary(code); |
| 51 ASSERT(dictionary_->IsDictionary()); | 57 ASSERT(dictionary_->IsDictionary()); |
| 52 } | 58 } |
| 53 | 59 |
| 54 | 60 |
| 55 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 61 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
| 56 return static_cast<uint32_t>(ast_id.ToInt()); | 62 return static_cast<uint32_t>(ast_id.ToInt()); |
| 57 } | 63 } |
| 58 | 64 |
| 59 | 65 |
| 60 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 66 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
| 61 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 67 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
| 62 if (entry != UnseededNumberDictionary::kNotFound) { | 68 if (entry != UnseededNumberDictionary::kNotFound) { |
| 63 Object* value = dictionary_->ValueAt(entry); | 69 Object* value = dictionary_->ValueAt(entry); |
| 64 if (value->IsCell()) { | 70 if (value->IsCell()) { |
| 65 Cell* cell = Cell::cast(value); | 71 Cell* cell = Cell::cast(value); |
| 66 return Handle<Object>(cell->value(), isolate()); | 72 return Handle<Object>(cell->value(), isolate()); |
| 67 } else { | 73 } else { |
| 68 return Handle<Object>(value, isolate()); | 74 return Handle<Object>(value, isolate()); |
| 69 } | 75 } |
| 70 } | 76 } |
| 71 return Handle<Object>::cast(isolate()->factory()->undefined_value()); | 77 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
| 72 } | 78 } |
| 73 | 79 |
| 74 | 80 |
| 81 Handle<Object> TypeFeedbackOracle::GetInfo(int slot) { | |
| 82 ASSERT(slot >= 0 && slot < feedback_vector_->length()); | |
| 83 Object* obj = feedback_vector_->get(slot); | |
| 84 if (obj->IsSmi() || obj->IsAllocationSite() || | |
|
Benedikt Meurer
2014/02/04 08:53:50
Please remove this left over hacks, and use someth
mvstanton
2014/02/04 13:03:27
Thx, I removed the smi and allocationsite check. I
| |
| 85 (obj->IsJSFunction() && | |
| 86 !CanRetainOtherContext(JSFunction::cast(obj), *native_context_))) { | |
| 87 return Handle<Object>(obj, isolate()); | |
| 88 } | |
| 89 return Handle<Object>::cast(isolate()->factory()->undefined_value()); | |
| 90 } | |
| 91 | |
| 92 | |
| 75 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 93 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
| 76 Handle<Object> maybe_code = GetInfo(id); | 94 Handle<Object> maybe_code = GetInfo(id); |
| 77 if (maybe_code->IsCode()) { | 95 if (maybe_code->IsCode()) { |
| 78 Handle<Code> code = Handle<Code>::cast(maybe_code); | 96 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 79 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 97 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
| 80 } | 98 } |
| 81 return false; | 99 return false; |
| 82 } | 100 } |
| 83 | 101 |
| 84 | 102 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 114 Handle<Object> maybe_code = GetInfo(ast_id); | 132 Handle<Object> maybe_code = GetInfo(ast_id); |
| 115 if (maybe_code->IsCode()) { | 133 if (maybe_code->IsCode()) { |
| 116 Handle<Code> code = Handle<Code>::cast(maybe_code); | 134 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 117 return code->is_keyed_store_stub() && | 135 return code->is_keyed_store_stub() && |
| 118 code->ic_state() == POLYMORPHIC; | 136 code->ic_state() == POLYMORPHIC; |
| 119 } | 137 } |
| 120 return false; | 138 return false; |
| 121 } | 139 } |
| 122 | 140 |
| 123 | 141 |
| 142 bool TypeFeedbackOracle::CallIsMonomorphic(int slot) { | |
| 143 Handle<Object> value = GetInfo(slot); | |
| 144 return value->IsAllocationSite() || value->IsJSFunction(); | |
| 145 } | |
| 146 | |
| 147 | |
| 124 bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) { | 148 bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) { |
| 125 Handle<Object> value = GetInfo(id); | 149 Handle<Object> value = GetInfo(id); |
| 126 return value->IsAllocationSite() || value->IsJSFunction() || value->IsSmi() || | 150 return value->IsSmi() || |
| 127 (value->IsCode() && Handle<Code>::cast(value)->ic_state() == MONOMORPHIC); | 151 (value->IsCode() && Handle<Code>::cast(value)->ic_state() == MONOMORPHIC); |
| 128 } | 152 } |
| 129 | 153 |
| 130 | 154 |
| 131 bool TypeFeedbackOracle::KeyedArrayCallIsHoley(TypeFeedbackId id) { | 155 bool TypeFeedbackOracle::KeyedArrayCallIsHoley(TypeFeedbackId id) { |
| 132 Handle<Object> value = GetInfo(id); | 156 Handle<Object> value = GetInfo(id); |
| 133 Handle<Code> code = Handle<Code>::cast(value); | 157 Handle<Code> code = Handle<Code>::cast(value); |
| 134 return KeyedArrayCallStub::IsHoley(code); | 158 return KeyedArrayCallStub::IsHoley(code); |
| 135 } | 159 } |
| 136 | 160 |
| 137 | 161 |
| 138 bool TypeFeedbackOracle::CallNewIsMonomorphic(TypeFeedbackId id) { | 162 bool TypeFeedbackOracle::CallNewIsMonomorphic(int slot) { |
| 139 Handle<Object> info = GetInfo(id); | 163 Handle<Object> info = GetInfo(slot); |
| 140 return info->IsAllocationSite() || info->IsJSFunction(); | 164 return info->IsAllocationSite() || info->IsJSFunction(); |
| 141 } | 165 } |
| 142 | 166 |
| 143 | 167 |
| 144 byte TypeFeedbackOracle::ForInType(TypeFeedbackId id) { | 168 byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) { |
| 145 Handle<Object> value = GetInfo(id); | 169 Handle<Object> value = GetInfo(feedback_vector_slot); |
| 146 return value->IsSmi() && | 170 return value->IsSmi() && |
| 147 Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker | 171 Smi::cast(*value)->value() == TypeFeedbackInfo::kForInFastCaseMarker |
| 148 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; | 172 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; |
| 149 } | 173 } |
| 150 | 174 |
| 151 | 175 |
| 152 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( | 176 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( |
| 153 TypeFeedbackId ast_id) { | 177 TypeFeedbackId ast_id) { |
| 154 Handle<Object> maybe_code = GetInfo(ast_id); | 178 Handle<Object> maybe_code = GetInfo(ast_id); |
| 155 if (maybe_code->IsCode()) { | 179 if (maybe_code->IsCode()) { |
| 156 Handle<Code> code = Handle<Code>::cast(maybe_code); | 180 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 157 if (code->kind() == Code::KEYED_STORE_IC) { | 181 if (code->kind() == Code::KEYED_STORE_IC) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 174 | 198 |
| 175 CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) { | 199 CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) { |
| 176 Handle<Object> value = GetInfo(id); | 200 Handle<Object> value = GetInfo(id); |
| 177 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 201 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; |
| 178 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 202 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); |
| 179 ASSERT(check != RECEIVER_MAP_CHECK); | 203 ASSERT(check != RECEIVER_MAP_CHECK); |
| 180 return check; | 204 return check; |
| 181 } | 205 } |
| 182 | 206 |
| 183 | 207 |
| 184 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { | 208 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(int slot) { |
| 185 Handle<Object> info = GetInfo(id); | 209 Handle<Object> info = GetInfo(slot); |
| 186 if (info->IsAllocationSite()) { | 210 if (info->IsAllocationSite()) { |
| 187 return Handle<JSFunction>(isolate()->global_context()->array_function()); | 211 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 188 } else { | 212 } else { |
| 189 return Handle<JSFunction>::cast(info); | 213 return Handle<JSFunction>::cast(info); |
| 190 } | 214 } |
| 191 } | 215 } |
| 192 | 216 |
| 193 | 217 |
| 194 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { | 218 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(int slot) { |
| 195 Handle<Object> info = GetInfo(id); | 219 Handle<Object> info = GetInfo(slot); |
| 196 if (info->IsAllocationSite()) { | 220 if (info->IsAllocationSite()) { |
| 197 return Handle<JSFunction>(isolate()->global_context()->array_function()); | 221 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 198 } else { | 222 } else { |
| 199 return Handle<JSFunction>::cast(info); | 223 return Handle<JSFunction>::cast(info); |
| 200 } | 224 } |
| 201 } | 225 } |
| 202 | 226 |
| 203 | 227 |
| 204 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite( | 228 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(int slot) { |
| 205 TypeFeedbackId id) { | 229 Handle<Object> info = GetInfo(slot); |
| 206 Handle<Object> info = GetInfo(id); | |
| 207 if (info->IsAllocationSite()) { | 230 if (info->IsAllocationSite()) { |
| 208 return Handle<AllocationSite>::cast(info); | 231 return Handle<AllocationSite>::cast(info); |
| 209 } | 232 } |
| 210 return Handle<AllocationSite>::null(); | 233 return Handle<AllocationSite>::null(); |
| 211 } | 234 } |
| 212 | 235 |
| 213 | 236 |
| 214 bool TypeFeedbackOracle::LoadIsBuiltin( | 237 bool TypeFeedbackOracle::LoadIsBuiltin( |
| 215 TypeFeedbackId id, Builtins::Name builtin) { | 238 TypeFeedbackId id, Builtins::Name builtin) { |
| 216 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); | 239 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 449 // themselves are not GC-safe, so we first get all infos, then we create the | 472 // themselves are not GC-safe, so we first get all infos, then we create the |
| 450 // dictionary (possibly triggering GC), and finally we relocate the collected | 473 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 451 // infos before we process them. | 474 // infos before we process them. |
| 452 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 475 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 453 DisallowHeapAllocation no_allocation; | 476 DisallowHeapAllocation no_allocation; |
| 454 ZoneList<RelocInfo> infos(16, zone()); | 477 ZoneList<RelocInfo> infos(16, zone()); |
| 455 HandleScope scope(isolate()); | 478 HandleScope scope(isolate()); |
| 456 GetRelocInfos(code, &infos); | 479 GetRelocInfos(code, &infos); |
| 457 CreateDictionary(code, &infos); | 480 CreateDictionary(code, &infos); |
| 458 ProcessRelocInfos(&infos); | 481 ProcessRelocInfos(&infos); |
| 459 ProcessTypeFeedbackCells(code); | |
| 460 // Allocate handle in the parent scope. | 482 // Allocate handle in the parent scope. |
| 461 dictionary_ = scope.CloseAndEscape(dictionary_); | 483 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 462 } | 484 } |
| 463 | 485 |
| 464 | 486 |
| 465 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, | 487 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, |
| 466 ZoneList<RelocInfo>* infos) { | 488 ZoneList<RelocInfo>* infos) { |
| 467 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 489 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 468 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 490 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
| 469 infos->Add(*it.rinfo(), zone()); | 491 infos->Add(*it.rinfo(), zone()); |
| 470 } | 492 } |
| 471 } | 493 } |
| 472 | 494 |
| 473 | 495 |
| 474 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, | 496 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, |
| 475 ZoneList<RelocInfo>* infos) { | 497 ZoneList<RelocInfo>* infos) { |
| 476 AllowHeapAllocation allocation_allowed; | 498 AllowHeapAllocation allocation_allowed; |
| 477 int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo() | |
| 478 ? TypeFeedbackInfo::cast(code->type_feedback_info())-> | |
| 479 type_feedback_cells()->CellCount() | |
| 480 : 0; | |
| 481 int length = infos->length() + cell_count; | |
| 482 byte* old_start = code->instruction_start(); | 499 byte* old_start = code->instruction_start(); |
| 483 dictionary_ = isolate()->factory()->NewUnseededNumberDictionary(length); | 500 dictionary_ = |
| 501 isolate()->factory()->NewUnseededNumberDictionary(infos->length()); | |
| 484 byte* new_start = code->instruction_start(); | 502 byte* new_start = code->instruction_start(); |
| 485 RelocateRelocInfos(infos, old_start, new_start); | 503 RelocateRelocInfos(infos, old_start, new_start); |
| 486 } | 504 } |
| 487 | 505 |
| 488 | 506 |
| 489 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, | 507 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, |
| 490 byte* old_start, | 508 byte* old_start, |
| 491 byte* new_start) { | 509 byte* new_start) { |
| 492 for (int i = 0; i < infos->length(); i++) { | 510 for (int i = 0; i < infos->length(); i++) { |
| 493 RelocInfo* info = &(*infos)[i]; | 511 RelocInfo* info = &(*infos)[i]; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 522 SetInfo(ast_id, target); | 540 SetInfo(ast_id, target); |
| 523 break; | 541 break; |
| 524 | 542 |
| 525 default: | 543 default: |
| 526 break; | 544 break; |
| 527 } | 545 } |
| 528 } | 546 } |
| 529 } | 547 } |
| 530 | 548 |
| 531 | 549 |
| 532 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { | |
| 533 Object* raw_info = code->type_feedback_info(); | |
| 534 if (!raw_info->IsTypeFeedbackInfo()) return; | |
| 535 Handle<TypeFeedbackCells> cache( | |
| 536 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); | |
| 537 for (int i = 0; i < cache->CellCount(); i++) { | |
| 538 TypeFeedbackId ast_id = cache->AstId(i); | |
| 539 Cell* cell = cache->GetCell(i); | |
| 540 Object* value = cell->value(); | |
| 541 if (value->IsSmi() || | |
| 542 value->IsAllocationSite() || | |
| 543 (value->IsJSFunction() && | |
| 544 !CanRetainOtherContext(JSFunction::cast(value), | |
| 545 *native_context_))) { | |
| 546 SetInfo(ast_id, cell); | |
| 547 } | |
| 548 } | |
| 549 } | |
| 550 | |
| 551 | |
| 552 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { | 550 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { |
| 553 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == | 551 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == |
| 554 UnseededNumberDictionary::kNotFound); | 552 UnseededNumberDictionary::kNotFound); |
| 555 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); | 553 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); |
| 556 USE(maybe_result); | 554 USE(maybe_result); |
| 557 #ifdef DEBUG | 555 #ifdef DEBUG |
| 558 Object* result = NULL; | 556 Object* result = NULL; |
| 559 // Dictionary has been allocated with sufficient size for all elements. | 557 // Dictionary has been allocated with sufficient size for all elements. |
| 560 ASSERT(maybe_result->ToObject(&result)); | 558 ASSERT(maybe_result->ToObject(&result)); |
| 561 ASSERT(*dictionary_ == result); | 559 ASSERT(*dictionary_ == result); |
| 562 #endif | 560 #endif |
| 563 } | 561 } |
| 564 | 562 |
| 565 | 563 |
| 566 } } // namespace v8::internal | 564 } } // namespace v8::internal |
| OLD | NEW |