Rewrite StoreIC handling using the LookupIterator. Continued from patch 494153002
[platform/upstream/v8.git] / src / ic-inl.h
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.h"
9
10 #include "src/compiler.h"
11 #include "src/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   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(Assembler::target_address_at(result,
31                                                        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
51 ConstantPoolArray* 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
75 ConstantPoolArray* 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
84 Code* 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
96 void IC::SetTargetAtAddress(Address address,
97                             Code* target,
98                             ConstantPoolArray* constant_pool) {
99   DCHECK(target->is_inline_cache_stub() || target->is_compare_ic_stub());
100   Heap* heap = target->GetHeap();
101   Code* old_target = GetTargetAtAddress(address, constant_pool);
102 #ifdef DEBUG
103   // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark
104   // ICs as strict mode. The strict-ness of the IC must be preserved.
105   if (old_target->kind() == Code::STORE_IC ||
106       old_target->kind() == Code::KEYED_STORE_IC) {
107     DCHECK(StoreIC::GetStrictMode(old_target->extra_ic_state()) ==
108            StoreIC::GetStrictMode(target->extra_ic_state()));
109   }
110 #endif
111   Assembler::set_target_address_at(
112       address, constant_pool, target->instruction_start());
113   if (heap->gc_state() == Heap::MARK_COMPACT) {
114     heap->mark_compact_collector()->RecordCodeTargetPatch(address, target);
115   } else {
116     heap->incremental_marking()->RecordCodeTargetPatch(address, target);
117   }
118   PostPatching(address, target, old_target);
119 }
120
121
122 template <class TypeClass>
123 JSFunction* IC::GetRootConstructor(TypeClass* type, Context* native_context) {
124   if (type->Is(TypeClass::Boolean())) {
125     return native_context->boolean_function();
126   } else if (type->Is(TypeClass::Number())) {
127     return native_context->number_function();
128   } else if (type->Is(TypeClass::String())) {
129     return native_context->string_function();
130   } else if (type->Is(TypeClass::Symbol())) {
131     return native_context->symbol_function();
132   } else {
133     return NULL;
134   }
135 }
136
137
138 Handle<Map> IC::GetHandlerCacheHolder(HeapType* type, bool receiver_is_holder,
139                                       Isolate* isolate, CacheHolderFlag* flag) {
140   Handle<Map> receiver_map = TypeToMap(type, isolate);
141   if (receiver_is_holder) {
142     *flag = kCacheOnReceiver;
143     return receiver_map;
144   }
145   Context* native_context = *isolate->native_context();
146   JSFunction* builtin_ctor = GetRootConstructor(type, native_context);
147   if (builtin_ctor != NULL) {
148     *flag = kCacheOnPrototypeReceiverIsPrimitive;
149     return handle(HeapObject::cast(builtin_ctor->instance_prototype())->map());
150   }
151   *flag = receiver_map->is_dictionary_map()
152               ? kCacheOnPrototypeReceiverIsDictionary
153               : kCacheOnPrototype;
154   // Callers must ensure that the prototype is non-null.
155   return handle(JSObject::cast(receiver_map->prototype())->map());
156 }
157
158
159 Handle<Map> IC::GetICCacheHolder(HeapType* type, Isolate* isolate,
160                                  CacheHolderFlag* flag) {
161   Context* native_context = *isolate->native_context();
162   JSFunction* builtin_ctor = GetRootConstructor(type, native_context);
163   if (builtin_ctor != NULL) {
164     *flag = kCacheOnPrototype;
165     return handle(builtin_ctor->initial_map());
166   }
167   *flag = kCacheOnReceiver;
168   return TypeToMap(type, isolate);
169 }
170
171
172 IC::State CallIC::FeedbackToState(Handle<FixedArray> vector,
173                                   Handle<Smi> slot) const {
174   IC::State state = UNINITIALIZED;
175   Object* feedback = vector->get(slot->value());
176
177   if (feedback == *TypeFeedbackInfo::MegamorphicSentinel(isolate())) {
178     state = GENERIC;
179   } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) {
180     state = MONOMORPHIC;
181   } else {
182     CHECK(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()));
183   }
184
185   return state;
186 }
187 } }  // namespace v8::internal
188
189 #endif  // V8_IC_INL_H_