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