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