| 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->IsJSFunction() || |
| 85 !CanRetainOtherContext(JSFunction::cast(obj), *native_context_)) { |
| 86 return Handle<Object>(obj, isolate()); |
| 87 } |
| 88 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
| 89 } |
| 90 |
| 91 |
| 75 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 92 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
| 76 Handle<Object> maybe_code = GetInfo(id); | 93 Handle<Object> maybe_code = GetInfo(id); |
| 77 if (maybe_code->IsCode()) { | 94 if (maybe_code->IsCode()) { |
| 78 Handle<Code> code = Handle<Code>::cast(maybe_code); | 95 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 79 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 96 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
| 80 } | 97 } |
| 81 return false; | 98 return false; |
| 82 } | 99 } |
| 83 | 100 |
| 84 | 101 |
| 85 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { | 102 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { |
| 86 Handle<Object> maybe_code = GetInfo(ast_id); | 103 Handle<Object> maybe_code = GetInfo(ast_id); |
| 87 if (!maybe_code->IsCode()) return false; | 104 if (!maybe_code->IsCode()) return false; |
| 88 Handle<Code> code = Handle<Code>::cast(maybe_code); | 105 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 89 return code->ic_state() == UNINITIALIZED; | 106 return code->ic_state() == UNINITIALIZED; |
| 90 } | 107 } |
| 91 | 108 |
| 92 | 109 |
| 93 bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) { | 110 bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) { |
| 94 Handle<Object> maybe_code = GetInfo(ast_id); | 111 Handle<Object> maybe_code = GetInfo(ast_id); |
| 95 if (maybe_code->IsCode()) { | 112 if (maybe_code->IsCode()) { |
| 96 Handle<Code> code = Handle<Code>::cast(maybe_code); | 113 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 97 return code->is_keyed_store_stub() && | 114 return code->is_keyed_store_stub() && |
| 98 code->ic_state() == POLYMORPHIC; | 115 code->ic_state() == POLYMORPHIC; |
| 99 } | 116 } |
| 100 return false; | 117 return false; |
| 101 } | 118 } |
| 102 | 119 |
| 103 | 120 |
| 104 bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) { | 121 bool TypeFeedbackOracle::CallIsMonomorphic(int slot) { |
| 105 Handle<Object> value = GetInfo(id); | 122 Handle<Object> value = GetInfo(slot); |
| 106 return value->IsAllocationSite() || value->IsJSFunction(); | 123 return value->IsAllocationSite() || value->IsJSFunction(); |
| 107 } | 124 } |
| 108 | 125 |
| 109 | 126 |
| 110 bool TypeFeedbackOracle::CallNewIsMonomorphic(TypeFeedbackId id) { | 127 bool TypeFeedbackOracle::CallNewIsMonomorphic(int slot) { |
| 111 Handle<Object> info = GetInfo(id); | 128 Handle<Object> info = GetInfo(slot); |
| 112 return info->IsAllocationSite() || info->IsJSFunction(); | 129 return info->IsAllocationSite() || info->IsJSFunction(); |
| 113 } | 130 } |
| 114 | 131 |
| 115 | 132 |
| 116 byte TypeFeedbackOracle::ForInType(TypeFeedbackId id) { | 133 byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) { |
| 117 Handle<Object> value = GetInfo(id); | 134 Handle<Object> value = GetInfo(feedback_vector_slot); |
| 118 return value->IsSmi() && | 135 return value->IsSmi() && |
| 119 Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker | 136 Smi::cast(*value)->value() == TypeFeedbackInfo::kForInFastCaseMarker |
| 120 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; | 137 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; |
| 121 } | 138 } |
| 122 | 139 |
| 123 | 140 |
| 124 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( | 141 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( |
| 125 TypeFeedbackId ast_id) { | 142 TypeFeedbackId ast_id) { |
| 126 Handle<Object> maybe_code = GetInfo(ast_id); | 143 Handle<Object> maybe_code = GetInfo(ast_id); |
| 127 if (maybe_code->IsCode()) { | 144 if (maybe_code->IsCode()) { |
| 128 Handle<Code> code = Handle<Code>::cast(maybe_code); | 145 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 129 if (code->kind() == Code::KEYED_STORE_IC) { | 146 if (code->kind() == Code::KEYED_STORE_IC) { |
| 130 return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()); | 147 return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()); |
| 131 } | 148 } |
| 132 } | 149 } |
| 133 return STANDARD_STORE; | 150 return STANDARD_STORE; |
| 134 } | 151 } |
| 135 | 152 |
| 136 | 153 |
| 137 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { | 154 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(int slot) { |
| 138 Handle<Object> info = GetInfo(id); | 155 Handle<Object> info = GetInfo(slot); |
| 139 if (info->IsAllocationSite()) { | 156 if (info->IsAllocationSite()) { |
| 140 return Handle<JSFunction>(isolate()->global_context()->array_function()); | 157 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 141 } else { | 158 } else { |
| 142 return Handle<JSFunction>::cast(info); | 159 return Handle<JSFunction>::cast(info); |
| 143 } | 160 } |
| 144 } | 161 } |
| 145 | 162 |
| 146 | 163 |
| 147 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { | 164 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(int slot) { |
| 148 Handle<Object> info = GetInfo(id); | 165 Handle<Object> info = GetInfo(slot); |
| 149 if (info->IsAllocationSite()) { | 166 if (info->IsAllocationSite()) { |
| 150 return Handle<JSFunction>(isolate()->global_context()->array_function()); | 167 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 151 } else { | 168 } else { |
| 152 return Handle<JSFunction>::cast(info); | 169 return Handle<JSFunction>::cast(info); |
| 153 } | 170 } |
| 154 } | 171 } |
| 155 | 172 |
| 156 | 173 |
| 157 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite( | 174 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(int slot) { |
| 158 TypeFeedbackId id) { | 175 Handle<Object> info = GetInfo(slot); |
| 159 Handle<Object> info = GetInfo(id); | |
| 160 if (info->IsAllocationSite()) { | 176 if (info->IsAllocationSite()) { |
| 161 return Handle<AllocationSite>::cast(info); | 177 return Handle<AllocationSite>::cast(info); |
| 162 } | 178 } |
| 163 return Handle<AllocationSite>::null(); | 179 return Handle<AllocationSite>::null(); |
| 164 } | 180 } |
| 165 | 181 |
| 166 | 182 |
| 167 bool TypeFeedbackOracle::LoadIsBuiltin( | 183 bool TypeFeedbackOracle::LoadIsBuiltin( |
| 168 TypeFeedbackId id, Builtins::Name builtin) { | 184 TypeFeedbackId id, Builtins::Name builtin) { |
| 169 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); | 185 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 // themselves are not GC-safe, so we first get all infos, then we create the | 418 // themselves are not GC-safe, so we first get all infos, then we create the |
| 403 // dictionary (possibly triggering GC), and finally we relocate the collected | 419 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 404 // infos before we process them. | 420 // infos before we process them. |
| 405 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 421 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 406 DisallowHeapAllocation no_allocation; | 422 DisallowHeapAllocation no_allocation; |
| 407 ZoneList<RelocInfo> infos(16, zone()); | 423 ZoneList<RelocInfo> infos(16, zone()); |
| 408 HandleScope scope(isolate()); | 424 HandleScope scope(isolate()); |
| 409 GetRelocInfos(code, &infos); | 425 GetRelocInfos(code, &infos); |
| 410 CreateDictionary(code, &infos); | 426 CreateDictionary(code, &infos); |
| 411 ProcessRelocInfos(&infos); | 427 ProcessRelocInfos(&infos); |
| 412 ProcessTypeFeedbackCells(code); | |
| 413 // Allocate handle in the parent scope. | 428 // Allocate handle in the parent scope. |
| 414 dictionary_ = scope.CloseAndEscape(dictionary_); | 429 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 415 } | 430 } |
| 416 | 431 |
| 417 | 432 |
| 418 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, | 433 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, |
| 419 ZoneList<RelocInfo>* infos) { | 434 ZoneList<RelocInfo>* infos) { |
| 420 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 435 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 421 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 436 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
| 422 infos->Add(*it.rinfo(), zone()); | 437 infos->Add(*it.rinfo(), zone()); |
| 423 } | 438 } |
| 424 } | 439 } |
| 425 | 440 |
| 426 | 441 |
| 427 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, | 442 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, |
| 428 ZoneList<RelocInfo>* infos) { | 443 ZoneList<RelocInfo>* infos) { |
| 429 AllowHeapAllocation allocation_allowed; | 444 AllowHeapAllocation allocation_allowed; |
| 430 int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo() | |
| 431 ? TypeFeedbackInfo::cast(code->type_feedback_info())-> | |
| 432 type_feedback_cells()->CellCount() | |
| 433 : 0; | |
| 434 int length = infos->length() + cell_count; | |
| 435 byte* old_start = code->instruction_start(); | 445 byte* old_start = code->instruction_start(); |
| 436 dictionary_ = isolate()->factory()->NewUnseededNumberDictionary(length); | 446 dictionary_ = |
| 447 isolate()->factory()->NewUnseededNumberDictionary(infos->length()); |
| 437 byte* new_start = code->instruction_start(); | 448 byte* new_start = code->instruction_start(); |
| 438 RelocateRelocInfos(infos, old_start, new_start); | 449 RelocateRelocInfos(infos, old_start, new_start); |
| 439 } | 450 } |
| 440 | 451 |
| 441 | 452 |
| 442 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, | 453 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, |
| 443 byte* old_start, | 454 byte* old_start, |
| 444 byte* new_start) { | 455 byte* new_start) { |
| 445 for (int i = 0; i < infos->length(); i++) { | 456 for (int i = 0; i < infos->length(); i++) { |
| 446 RelocInfo* info = &(*infos)[i]; | 457 RelocInfo* info = &(*infos)[i]; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 468 SetInfo(ast_id, target); | 479 SetInfo(ast_id, target); |
| 469 break; | 480 break; |
| 470 | 481 |
| 471 default: | 482 default: |
| 472 break; | 483 break; |
| 473 } | 484 } |
| 474 } | 485 } |
| 475 } | 486 } |
| 476 | 487 |
| 477 | 488 |
| 478 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { | |
| 479 Object* raw_info = code->type_feedback_info(); | |
| 480 if (!raw_info->IsTypeFeedbackInfo()) return; | |
| 481 Handle<TypeFeedbackCells> cache( | |
| 482 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); | |
| 483 for (int i = 0; i < cache->CellCount(); i++) { | |
| 484 TypeFeedbackId ast_id = cache->AstId(i); | |
| 485 Cell* cell = cache->GetCell(i); | |
| 486 Object* value = cell->value(); | |
| 487 if (value->IsSmi() || | |
| 488 value->IsAllocationSite() || | |
| 489 (value->IsJSFunction() && | |
| 490 !CanRetainOtherContext(JSFunction::cast(value), | |
| 491 *native_context_))) { | |
| 492 SetInfo(ast_id, cell); | |
| 493 } | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 | |
| 498 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { | 489 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { |
| 499 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == | 490 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == |
| 500 UnseededNumberDictionary::kNotFound); | 491 UnseededNumberDictionary::kNotFound); |
| 501 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); | 492 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); |
| 502 USE(maybe_result); | 493 USE(maybe_result); |
| 503 #ifdef DEBUG | 494 #ifdef DEBUG |
| 504 Object* result = NULL; | 495 Object* result = NULL; |
| 505 // Dictionary has been allocated with sufficient size for all elements. | 496 // Dictionary has been allocated with sufficient size for all elements. |
| 506 ASSERT(maybe_result->ToObject(&result)); | 497 ASSERT(maybe_result->ToObject(&result)); |
| 507 ASSERT(*dictionary_ == result); | 498 ASSERT(*dictionary_ == result); |
| 508 #endif | 499 #endif |
| 509 } | 500 } |
| 510 | 501 |
| 511 | 502 |
| 512 } } // namespace v8::internal | 503 } } // namespace v8::internal |
| OLD | NEW |