1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_IC_INL_H_ 6 #define V8_IC_INL_H_ 7 8 #include "src/ic/ic.h" 9 10 #include "src/compiler.h" 11 #include "src/debug/debug.h" 12 #include "src/macro-assembler.h" 13 #include "src/prototype.h" 14 15 namespace v8 { 16 namespace internal { 17 18 19 Address IC::address() const { 20 // Get the address of the call. 21 return Assembler::target_address_from_return_address(pc()); 22 } 23 24 25 Address IC::constant_pool() const { 26 if (FLAG_enable_embedded_constant_pool) { 27 return raw_constant_pool(); 28 } else { 29 return NULL; 30 } 31 } 32 33 34 Address IC::raw_constant_pool() const { 35 if (FLAG_enable_embedded_constant_pool) { 36 return *constant_pool_address_; 37 } else { 38 return NULL; 39 } 40 } 41 42 43 Code* IC::GetTargetAtAddress(Address address, Address constant_pool) { 44 // Get the target address of the IC. 45 Address target = Assembler::target_address_at(address, constant_pool); 46 // Convert target address to the code object. Code::GetCodeFromTargetAddress 47 // is safe for use during GC where the map might be marked. 48 Code* result = Code::GetCodeFromTargetAddress(target); 49 DCHECK(result->is_inline_cache_stub()); 50 return result; 51 } 52 53 54 void IC::SetTargetAtAddress(Address address, Code* target, 55 Address constant_pool) { 56 if (AddressIsDeoptimizedCode(target->GetIsolate(), address)) return; 57 58 DCHECK(target->is_inline_cache_stub() || target->is_compare_ic_stub()); 59 60 DCHECK(!target->is_inline_cache_stub() || 61 (target->kind() != Code::LOAD_IC && 62 target->kind() != Code::KEYED_LOAD_IC && 63 target->kind() != Code::CALL_IC && target->kind() != Code::STORE_IC && 64 target->kind() != Code::KEYED_STORE_IC)); 65 66 Heap* heap = target->GetHeap(); 67 Code* old_target = GetTargetAtAddress(address, constant_pool); 68 #ifdef DEBUG 69 // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark 70 // ICs as language mode. The language mode of the IC must be preserved. 71 if (old_target->kind() == Code::STORE_IC || 72 old_target->kind() == Code::KEYED_STORE_IC) { 73 DCHECK(StoreICState::GetLanguageMode(old_target->extra_ic_state()) == 74 StoreICState::GetLanguageMode(target->extra_ic_state())); 75 } 76 #endif 77 Assembler::set_target_address_at(heap->isolate(), address, constant_pool, 78 target->instruction_start()); 79 if (heap->gc_state() == Heap::MARK_COMPACT) { 80 heap->mark_compact_collector()->RecordCodeTargetPatch(address, target); 81 } else { 82 heap->incremental_marking()->RecordCodeTargetPatch(address, target); 83 } 84 PostPatching(address, target, old_target); 85 } 86 87 88 void IC::set_target(Code* code) { 89 SetTargetAtAddress(address(), code, constant_pool()); 90 target_set_ = true; 91 } 92 93 94 void LoadIC::set_target(Code* code) { 95 // The contextual mode must be preserved across IC patching. 96 DCHECK(LoadICState::GetTypeofMode(code->extra_ic_state()) == 97 LoadICState::GetTypeofMode(target()->extra_ic_state())); 98 // Strongness must be preserved across IC patching. 99 DCHECK(LoadICState::GetLanguageMode(code->extra_ic_state()) == 100 LoadICState::GetLanguageMode(target()->extra_ic_state())); 101 102 IC::set_target(code); 103 } 104 105 106 void StoreIC::set_target(Code* code) { 107 // Language mode must be preserved across IC patching. 108 DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) == 109 StoreICState::GetLanguageMode(target()->extra_ic_state())); 110 IC::set_target(code); 111 } 112 113 114 void KeyedStoreIC::set_target(Code* code) { 115 // Language mode must be preserved across IC patching. 116 DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) == 117 language_mode()); 118 IC::set_target(code); 119 } 120 121 122 Code* IC::raw_target() const { 123 return GetTargetAtAddress(address(), constant_pool()); 124 } 125 126 void IC::UpdateTarget() { target_ = handle(raw_target(), isolate_); } 127 128 129 Handle<Map> IC::GetHandlerCacheHolder(Handle<Map> receiver_map, 130 bool receiver_is_holder, Isolate* isolate, 131 CacheHolderFlag* flag) { 132 if (receiver_is_holder) { 133 *flag = kCacheOnReceiver; 134 return receiver_map; 135 } 136 Handle<JSFunction> builtin_ctor; 137 if (Map::GetConstructorFunction(receiver_map, isolate->native_context()) 138 .ToHandle(&builtin_ctor)) { 139 *flag = kCacheOnPrototypeReceiverIsPrimitive; 140 return handle(HeapObject::cast(builtin_ctor->instance_prototype())->map()); 141 } 142 *flag = receiver_map->is_dictionary_map() 143 ? kCacheOnPrototypeReceiverIsDictionary 144 : kCacheOnPrototype; 145 // Callers must ensure that the prototype is non-null. 146 return handle(JSObject::cast(receiver_map->prototype())->map()); 147 } 148 149 150 Handle<Map> IC::GetICCacheHolder(Handle<Map> map, Isolate* isolate, 151 CacheHolderFlag* flag) { 152 Handle<JSFunction> builtin_ctor; 153 if (Map::GetConstructorFunction(map, isolate->native_context()) 154 .ToHandle(&builtin_ctor)) { 155 *flag = kCacheOnPrototype; 156 return handle(builtin_ctor->initial_map()); 157 } 158 *flag = kCacheOnReceiver; 159 return map; 160 } 161 162 163 Code* IC::get_host() { 164 return isolate() 165 ->inner_pointer_to_code_cache() 166 ->GetCacheEntry(address()) 167 ->code; 168 } 169 170 171 bool IC::AddressIsDeoptimizedCode() const { 172 return AddressIsDeoptimizedCode(isolate(), address()); 173 } 174 175 176 bool IC::AddressIsDeoptimizedCode(Isolate* isolate, Address address) { 177 Code* host = 178 isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 179 return (host->kind() == Code::OPTIMIZED_FUNCTION && 180 host->marked_for_deoptimization()); 181 } 182 } // namespace internal 183 } // namespace v8 184 185 #endif // V8_IC_INL_H_ 186