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
15 namespace v8 {
16 namespace internal {
17
18
address()19 Address IC::address() const {
20 // Get the address of the call.
21 return Assembler::target_address_from_return_address(pc());
22 }
23
24
constant_pool()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
raw_constant_pool()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
GetTargetAtAddress(Address address,Address constant_pool)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 // 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
SetTargetAtAddress(Address address,Code * target,Address constant_pool)57 void 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
set_target(Code * code)79 void IC::set_target(Code* code) {
80 SetTargetAtAddress(address(), code, constant_pool());
81 }
82
target()83 Code* IC::target() const {
84 return GetTargetAtAddress(address(), constant_pool());
85 }
86
IsHandler(Object * object)87 bool 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
GetHandlerCacheHolder(Handle<Map> receiver_map,bool receiver_is_holder,Isolate * isolate,CacheHolderFlag * flag)93 Handle<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
GetICCacheHolder(Handle<Map> map,Isolate * isolate,CacheHolderFlag * flag)114 Handle<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
AddressIsDeoptimizedCode()127 bool IC::AddressIsDeoptimizedCode() const {
128 return AddressIsDeoptimizedCode(isolate(), address());
129 }
130
131
AddressIsDeoptimizedCode(Isolate * isolate,Address address)132 bool 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