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 } 91 92 Code* IC::target() const { 93 return GetTargetAtAddress(address(), constant_pool()); 94 } 95 96 Handle<Map> IC::GetHandlerCacheHolder(Handle<Map> receiver_map, 97 bool receiver_is_holder, Isolate* isolate, 98 CacheHolderFlag* flag) { 99 if (receiver_is_holder) { 100 *flag = kCacheOnReceiver; 101 return receiver_map; 102 } 103 Handle<JSFunction> builtin_ctor; 104 if (Map::GetConstructorFunction(receiver_map, isolate->native_context()) 105 .ToHandle(&builtin_ctor)) { 106 *flag = kCacheOnPrototypeReceiverIsPrimitive; 107 return handle(HeapObject::cast(builtin_ctor->instance_prototype())->map()); 108 } 109 *flag = receiver_map->is_dictionary_map() 110 ? kCacheOnPrototypeReceiverIsDictionary 111 : kCacheOnPrototype; 112 // Callers must ensure that the prototype is non-null. 113 return handle(JSObject::cast(receiver_map->prototype())->map()); 114 } 115 116 117 Handle<Map> IC::GetICCacheHolder(Handle<Map> map, Isolate* isolate, 118 CacheHolderFlag* flag) { 119 Handle<JSFunction> builtin_ctor; 120 if (Map::GetConstructorFunction(map, isolate->native_context()) 121 .ToHandle(&builtin_ctor)) { 122 *flag = kCacheOnPrototype; 123 return handle(builtin_ctor->initial_map()); 124 } 125 *flag = kCacheOnReceiver; 126 return map; 127 } 128 129 130 Code* IC::get_host() { 131 return isolate() 132 ->inner_pointer_to_code_cache() 133 ->GetCacheEntry(address()) 134 ->code; 135 } 136 137 138 bool IC::AddressIsDeoptimizedCode() const { 139 return AddressIsDeoptimizedCode(isolate(), address()); 140 } 141 142 143 bool IC::AddressIsDeoptimizedCode(Isolate* isolate, Address address) { 144 Code* host = 145 isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 146 return (host->kind() == Code::OPTIMIZED_FUNCTION && 147 host->marked_for_deoptimization()); 148 } 149 } // namespace internal 150 } // namespace v8 151 152 #endif // V8_IC_INL_H_ 153