Home | History | Annotate | Download | only in src
      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 
     14 namespace v8 {
     15 namespace internal {
     16 
     17 
     18 Address IC::address() const {
     19   // Get the address of the call.
     20   Address result = Assembler::target_address_from_return_address(pc());
     21 
     22   Debug* debug = isolate()->debug();
     23   // First check if any break points are active if not just return the address
     24   // of the call.
     25   if (!debug->has_break_points()) return result;
     26 
     27   // At least one break point is active perform additional test to ensure that
     28   // break point locations are updated correctly.
     29   if (debug->IsDebugBreak(Assembler::target_address_at(result,
     30                                                        raw_constant_pool()))) {
     31     // If the call site is a call to debug break then return the address in
     32     // the original code instead of the address in the running code. This will
     33     // cause the original code to be updated and keeps the breakpoint active in
     34     // the running code.
     35     Code* code = GetCode();
     36     Code* original_code = GetOriginalCode();
     37     intptr_t delta =
     38         original_code->instruction_start() - code->instruction_start();
     39     // Return the address in the original code. This is the place where
     40     // the call which has been overwritten by the DebugBreakXXX resides
     41     // and the place where the inline cache system should look.
     42     return result + delta;
     43   } else {
     44     // No break point here just return the address of the call.
     45     return result;
     46   }
     47 }
     48 
     49 
     50 ConstantPoolArray* IC::constant_pool() const {
     51   if (!FLAG_enable_ool_constant_pool) {
     52     return NULL;
     53   } else {
     54     Handle<ConstantPoolArray> result = raw_constant_pool_;
     55     Debug* debug = isolate()->debug();
     56     // First check if any break points are active if not just return the
     57     // original constant pool.
     58     if (!debug->has_break_points()) return *result;
     59 
     60     // At least one break point is active perform additional test to ensure that
     61     // break point locations are updated correctly.
     62     Address target = Assembler::target_address_from_return_address(pc());
     63     if (debug->IsDebugBreak(
     64             Assembler::target_address_at(target, raw_constant_pool()))) {
     65       // If the call site is a call to debug break then we want to return the
     66       // constant pool for the original code instead of the breakpointed code.
     67       return GetOriginalCode()->constant_pool();
     68     }
     69     return *result;
     70   }
     71 }
     72 
     73 
     74 ConstantPoolArray* IC::raw_constant_pool() const {
     75   if (FLAG_enable_ool_constant_pool) {
     76     return *raw_constant_pool_;
     77   } else {
     78     return NULL;
     79   }
     80 }
     81 
     82 
     83 Code* IC::GetTargetAtAddress(Address address,
     84                              ConstantPoolArray* constant_pool) {
     85   // Get the target address of the IC.
     86   Address target = Assembler::target_address_at(address, constant_pool);
     87   // Convert target address to the code object. Code::GetCodeFromTargetAddress
     88   // is safe for use during GC where the map might be marked.
     89   Code* result = Code::GetCodeFromTargetAddress(target);
     90   ASSERT(result->is_inline_cache_stub());
     91   return result;
     92 }
     93 
     94 
     95 void IC::SetTargetAtAddress(Address address,
     96                             Code* target,
     97                             ConstantPoolArray* constant_pool) {
     98   ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub());
     99   Heap* heap = target->GetHeap();
    100   Code* old_target = GetTargetAtAddress(address, constant_pool);
    101 #ifdef DEBUG
    102   // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark
    103   // ICs as strict mode. The strict-ness of the IC must be preserved.
    104   if (old_target->kind() == Code::STORE_IC ||
    105       old_target->kind() == Code::KEYED_STORE_IC) {
    106     ASSERT(StoreIC::GetStrictMode(old_target->extra_ic_state()) ==
    107            StoreIC::GetStrictMode(target->extra_ic_state()));
    108   }
    109 #endif
    110   Assembler::set_target_address_at(
    111       address, constant_pool, target->instruction_start());
    112   if (heap->gc_state() == Heap::MARK_COMPACT) {
    113     heap->mark_compact_collector()->RecordCodeTargetPatch(address, target);
    114   } else {
    115     heap->incremental_marking()->RecordCodeTargetPatch(address, target);
    116   }
    117   PostPatching(address, target, old_target);
    118 }
    119 
    120 
    121 InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object) {
    122   if (object->IsJSObject()) return OWN_MAP;
    123 
    124   // If the object is a value, we use the prototype map for the cache.
    125   ASSERT(object->IsString() || object->IsSymbol() ||
    126          object->IsNumber() || object->IsBoolean());
    127   return PROTOTYPE_MAP;
    128 }
    129 
    130 
    131 HeapObject* IC::GetCodeCacheHolder(Isolate* isolate,
    132                                    Object* object,
    133                                    InlineCacheHolderFlag holder) {
    134   if (object->IsSmi()) holder = PROTOTYPE_MAP;
    135   Object* map_owner = holder == OWN_MAP
    136       ? object : object->GetPrototype(isolate);
    137   return HeapObject::cast(map_owner);
    138 }
    139 
    140 
    141 InlineCacheHolderFlag IC::GetCodeCacheFlag(HeapType* type) {
    142   if (type->Is(HeapType::Boolean()) ||
    143       type->Is(HeapType::Number()) ||
    144       type->Is(HeapType::String()) ||
    145       type->Is(HeapType::Symbol())) {
    146     return PROTOTYPE_MAP;
    147   }
    148   return OWN_MAP;
    149 }
    150 
    151 
    152 Handle<Map> IC::GetCodeCacheHolder(InlineCacheHolderFlag flag,
    153                                    HeapType* type,
    154                                    Isolate* isolate) {
    155   if (flag == PROTOTYPE_MAP) {
    156     Context* context = isolate->context()->native_context();
    157     JSFunction* constructor;
    158     if (type->Is(HeapType::Boolean())) {
    159       constructor = context->boolean_function();
    160     } else if (type->Is(HeapType::Number())) {
    161       constructor = context->number_function();
    162     } else if (type->Is(HeapType::String())) {
    163       constructor = context->string_function();
    164     } else {
    165       ASSERT(type->Is(HeapType::Symbol()));
    166       constructor = context->symbol_function();
    167     }
    168     return handle(JSObject::cast(constructor->instance_prototype())->map());
    169   }
    170   return TypeToMap(type, isolate);
    171 }
    172 
    173 
    174 } }  // namespace v8::internal
    175 
    176 #endif  // V8_IC_INL_H_
    177