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/assembler-inl.h" 11#include "src/debug/debug.h" 12#include "src/macro-assembler.h" 13#include "src/prototype.h" 14 15namespace v8 { 16namespace internal { 17 18 19Address IC::address() const { 20 // Get the address of the call. 21 return Assembler::target_address_from_return_address(pc()); 22} 23 24 25Address 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 34Address 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 43Code* 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 // The result can be an IC dispatcher (for vector-based ICs), an IC handler 50 // (for old-style patching ICs) or CEntryStub (for IC dispatchers inlined to 51 // bytecode handlers). 52 DCHECK(result->is_inline_cache_stub() || result->is_stub()); 53 return result; 54} 55 56 57void IC::SetTargetAtAddress(Address address, Code* target, 58 Address constant_pool) { 59 if (AddressIsDeoptimizedCode(target->GetIsolate(), address)) return; 60 61 // Only these three old-style ICs still do code patching. 62 DCHECK(target->is_binary_op_stub() || target->is_compare_ic_stub() || 63 target->is_to_boolean_ic_stub()); 64 65 Heap* heap = target->GetHeap(); 66 Code* old_target = GetTargetAtAddress(address, constant_pool); 67 68 Assembler::set_target_address_at(heap->isolate(), address, constant_pool, 69 target->instruction_start()); 70 if (heap->gc_state() == Heap::MARK_COMPACT) { 71 heap->mark_compact_collector()->RecordCodeTargetPatch(address, target); 72 } else { 73 heap->incremental_marking()->RecordCodeTargetPatch(address, target); 74 } 75 PostPatching(address, target, old_target); 76} 77 78 79void IC::set_target(Code* code) { 80 SetTargetAtAddress(address(), code, constant_pool()); 81} 82 83Code* IC::target() const { 84 return GetTargetAtAddress(address(), constant_pool()); 85} 86 87bool IC::IsHandler(Object* object) { 88 return (object->IsSmi() && (object != nullptr)) || object->IsTuple2() || 89 object->IsTuple3() || object->IsFixedArray() || 90 (object->IsCode() && Code::cast(object)->is_handler()); 91} 92 93Handle<Map> IC::GetHandlerCacheHolder(Handle<Map> receiver_map, 94 bool receiver_is_holder, Isolate* isolate, 95 CacheHolderFlag* flag) { 96 if (receiver_is_holder) { 97 *flag = kCacheOnReceiver; 98 return receiver_map; 99 } 100 Handle<JSFunction> builtin_ctor; 101 if (Map::GetConstructorFunction(receiver_map, isolate->native_context()) 102 .ToHandle(&builtin_ctor)) { 103 *flag = kCacheOnPrototypeReceiverIsPrimitive; 104 return handle(HeapObject::cast(builtin_ctor->instance_prototype())->map()); 105 } 106 *flag = receiver_map->is_dictionary_map() 107 ? kCacheOnPrototypeReceiverIsDictionary 108 : kCacheOnPrototype; 109 // Callers must ensure that the prototype is non-null. 110 return handle(JSObject::cast(receiver_map->prototype())->map()); 111} 112 113 114Handle<Map> IC::GetICCacheHolder(Handle<Map> map, Isolate* isolate, 115 CacheHolderFlag* flag) { 116 Handle<JSFunction> builtin_ctor; 117 if (Map::GetConstructorFunction(map, isolate->native_context()) 118 .ToHandle(&builtin_ctor)) { 119 *flag = kCacheOnPrototype; 120 return handle(builtin_ctor->initial_map()); 121 } 122 *flag = kCacheOnReceiver; 123 return map; 124} 125 126 127bool IC::AddressIsDeoptimizedCode() const { 128 return AddressIsDeoptimizedCode(isolate(), address()); 129} 130 131 132bool IC::AddressIsDeoptimizedCode(Isolate* isolate, Address address) { 133 Code* host = 134 isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 135 return (host->kind() == Code::OPTIMIZED_FUNCTION && 136 host->marked_for_deoptimization()); 137} 138} // namespace internal 139} // namespace v8 140 141#endif // V8_IC_INL_H_ 142