| OLD | NEW | 
|---|
|  | (Empty) | 
| 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_ |  | 
| OLD | NEW | 
|---|