blob: 58d7d4608f7b3ec8c2d3a5980e777b6b0ef4b684 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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.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 Address result = Assembler::target_address_from_return_address(pc());
22
23 Debug* debug = isolate()->debug();
24 // First check if any break points are active if not just return the address
25 // of the call.
26 if (!debug->has_break_points()) return result;
27
28 // At least one break point is active perform additional test to ensure that
29 // break point locations are updated correctly.
30 if (debug->IsDebugBreak(
31 Assembler::target_address_at(result, raw_constant_pool()))) {
32 // If the call site is a call to debug break then return the address in
33 // the original code instead of the address in the running code. This will
34 // cause the original code to be updated and keeps the breakpoint active in
35 // the running code.
36 Code* code = GetCode();
37 Code* original_code = GetOriginalCode();
38 intptr_t delta =
39 original_code->instruction_start() - code->instruction_start();
40 // Return the address in the original code. This is the place where
41 // the call which has been overwritten by the DebugBreakXXX resides
42 // and the place where the inline cache system should look.
43 return result + delta;
44 } else {
45 // No break point here just return the address of the call.
46 return result;
47 }
48}
49
50
51ConstantPoolArray* IC::constant_pool() const {
52 if (!FLAG_enable_ool_constant_pool) {
53 return NULL;
54 } else {
55 Handle<ConstantPoolArray> result = raw_constant_pool_;
56 Debug* debug = isolate()->debug();
57 // First check if any break points are active if not just return the
58 // original constant pool.
59 if (!debug->has_break_points()) return *result;
60
61 // At least one break point is active perform additional test to ensure that
62 // break point locations are updated correctly.
63 Address target = Assembler::target_address_from_return_address(pc());
64 if (debug->IsDebugBreak(
65 Assembler::target_address_at(target, raw_constant_pool()))) {
66 // If the call site is a call to debug break then we want to return the
67 // constant pool for the original code instead of the breakpointed code.
68 return GetOriginalCode()->constant_pool();
69 }
70 return *result;
71 }
72}
73
74
75ConstantPoolArray* IC::raw_constant_pool() const {
76 if (FLAG_enable_ool_constant_pool) {
77 return *raw_constant_pool_;
78 } else {
79 return NULL;
80 }
81}
82
83
84Code* IC::GetTargetAtAddress(Address address,
85 ConstantPoolArray* constant_pool) {
86 // Get the target address of the IC.
87 Address target = Assembler::target_address_at(address, constant_pool);
88 // Convert target address to the code object. Code::GetCodeFromTargetAddress
89 // is safe for use during GC where the map might be marked.
90 Code* result = Code::GetCodeFromTargetAddress(target);
91 DCHECK(result->is_inline_cache_stub());
92 return result;
93}
94
95
96void IC::SetTargetAtAddress(Address address, Code* target,
97 ConstantPoolArray* constant_pool) {
98 DCHECK(target->is_inline_cache_stub() || target->is_compare_ic_stub());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040099
100 // Don't use this for load_ics when --vector-ics is turned on.
101 DCHECK(!(FLAG_vector_ics && target->is_inline_cache_stub()) ||
102 (target->kind() != Code::LOAD_IC &&
103 target->kind() != Code::KEYED_LOAD_IC));
104
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 Heap* heap = target->GetHeap();
106 Code* old_target = GetTargetAtAddress(address, constant_pool);
107#ifdef DEBUG
108 // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark
109 // ICs as strict mode. The strict-ness of the IC must be preserved.
110 if (old_target->kind() == Code::STORE_IC ||
111 old_target->kind() == Code::KEYED_STORE_IC) {
112 DCHECK(StoreIC::GetStrictMode(old_target->extra_ic_state()) ==
113 StoreIC::GetStrictMode(target->extra_ic_state()));
114 }
115#endif
116 Assembler::set_target_address_at(address, constant_pool,
117 target->instruction_start());
118 if (heap->gc_state() == Heap::MARK_COMPACT) {
119 heap->mark_compact_collector()->RecordCodeTargetPatch(address, target);
120 } else {
121 heap->incremental_marking()->RecordCodeTargetPatch(address, target);
122 }
123 PostPatching(address, target, old_target);
124}
125
126
127void IC::set_target(Code* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 SetTargetAtAddress(address(), code, constant_pool());
129 target_set_ = true;
130}
131
132
133void LoadIC::set_target(Code* code) {
134 // The contextual mode must be preserved across IC patching.
135 DCHECK(LoadICState::GetContextualMode(code->extra_ic_state()) ==
136 LoadICState::GetContextualMode(target()->extra_ic_state()));
137
138 IC::set_target(code);
139}
140
141
142void StoreIC::set_target(Code* code) {
143 // Strict mode must be preserved across IC patching.
144 DCHECK(GetStrictMode(code->extra_ic_state()) ==
145 GetStrictMode(target()->extra_ic_state()));
146 IC::set_target(code);
147}
148
149
150void KeyedStoreIC::set_target(Code* code) {
151 // Strict mode must be preserved across IC patching.
152 DCHECK(GetStrictMode(code->extra_ic_state()) == strict_mode());
153 IC::set_target(code);
154}
155
156
157Code* IC::raw_target() const {
158 return GetTargetAtAddress(address(), constant_pool());
159}
160
161void IC::UpdateTarget() { target_ = handle(raw_target(), isolate_); }
162
163
164template <class TypeClass>
165JSFunction* IC::GetRootConstructor(TypeClass* type, Context* native_context) {
166 if (type->Is(TypeClass::Boolean())) {
167 return native_context->boolean_function();
168 } else if (type->Is(TypeClass::Number())) {
169 return native_context->number_function();
170 } else if (type->Is(TypeClass::String())) {
171 return native_context->string_function();
172 } else if (type->Is(TypeClass::Symbol())) {
173 return native_context->symbol_function();
174 } else {
175 return NULL;
176 }
177}
178
179
180Handle<Map> IC::GetHandlerCacheHolder(HeapType* type, bool receiver_is_holder,
181 Isolate* isolate, CacheHolderFlag* flag) {
182 Handle<Map> receiver_map = TypeToMap(type, isolate);
183 if (receiver_is_holder) {
184 *flag = kCacheOnReceiver;
185 return receiver_map;
186 }
187 Context* native_context = *isolate->native_context();
188 JSFunction* builtin_ctor = GetRootConstructor(type, native_context);
189 if (builtin_ctor != NULL) {
190 *flag = kCacheOnPrototypeReceiverIsPrimitive;
191 return handle(HeapObject::cast(builtin_ctor->instance_prototype())->map());
192 }
193 *flag = receiver_map->is_dictionary_map()
194 ? kCacheOnPrototypeReceiverIsDictionary
195 : kCacheOnPrototype;
196 // Callers must ensure that the prototype is non-null.
197 return handle(JSObject::cast(receiver_map->prototype())->map());
198}
199
200
201Handle<Map> IC::GetICCacheHolder(HeapType* type, Isolate* isolate,
202 CacheHolderFlag* flag) {
203 Context* native_context = *isolate->native_context();
204 JSFunction* builtin_ctor = GetRootConstructor(type, native_context);
205 if (builtin_ctor != NULL) {
206 *flag = kCacheOnPrototype;
207 return handle(builtin_ctor->initial_map());
208 }
209 *flag = kCacheOnReceiver;
210 return TypeToMap(type, isolate);
211}
212
213
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400214inline Code* IC::get_host() {
215 return isolate()
216 ->inner_pointer_to_code_cache()
217 ->GetCacheEntry(address())
218 ->code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219}
220}
221} // namespace v8::internal
222
223#endif // V8_IC_INL_H_