| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #ifndef V8_IC_INL_H_ |
| #define V8_IC_INL_H_ |
| |
| #include "ic.h" |
| |
| #include "compiler.h" |
| #include "debug.h" |
| #include "macro-assembler.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| |
| Address IC::address() const { |
| // Get the address of the call. |
| Address result = pc() - Assembler::kCallTargetAddressOffset; |
| |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| Debug* debug = Isolate::Current()->debug(); |
| // First check if any break points are active if not just return the address |
| // of the call. |
| if (!debug->has_break_points()) return result; |
| |
| // At least one break point is active perform additional test to ensure that |
| // break point locations are updated correctly. |
| if (debug->IsDebugBreak(Assembler::target_address_at(result))) { |
| // If the call site is a call to debug break then return the address in |
| // the original code instead of the address in the running code. This will |
| // cause the original code to be updated and keeps the breakpoint active in |
| // the running code. |
| return OriginalCodeAddress(); |
| } else { |
| // No break point here just return the address of the call. |
| return result; |
| } |
| #else |
| return result; |
| #endif |
| } |
| |
| |
| Code* IC::GetTargetAtAddress(Address address) { |
| // Get the target address of the IC. |
| Address target = Assembler::target_address_at(address); |
| // Convert target address to the code object. Code::GetCodeFromTargetAddress |
| // is safe for use during GC where the map might be marked. |
| Code* result = Code::GetCodeFromTargetAddress(target); |
| ASSERT(result->is_inline_cache_stub()); |
| return result; |
| } |
| |
| |
| void IC::SetTargetAtAddress(Address address, Code* target) { |
| ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub()); |
| Code* old_target = GetTargetAtAddress(address); |
| #ifdef DEBUG |
| // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark |
| // ICs as strict mode. The strict-ness of the IC must be preserved. |
| if (old_target->kind() == Code::STORE_IC || |
| old_target->kind() == Code::KEYED_STORE_IC) { |
| ASSERT(Code::GetStrictMode(old_target->extra_ic_state()) == |
| Code::GetStrictMode(target->extra_ic_state())); |
| } |
| #endif |
| Assembler::set_target_address_at(address, target->instruction_start()); |
| target->GetHeap()->incremental_marking()->RecordCodeTargetPatch(address, |
| target); |
| PostPatching(address, target, old_target); |
| } |
| |
| |
| InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object, |
| JSObject* holder) { |
| if (object->IsJSObject()) { |
| return GetCodeCacheForObject(JSObject::cast(object), holder); |
| } |
| // If the object is a value, we use the prototype map for the cache. |
| ASSERT(object->IsString() || object->IsNumber() || object->IsBoolean()); |
| return PROTOTYPE_MAP; |
| } |
| |
| |
| InlineCacheHolderFlag IC::GetCodeCacheForObject(JSObject* object, |
| JSObject* holder) { |
| // Fast-properties and global objects store stubs in their own maps. |
| // Slow properties objects use prototype's map (unless the property is its own |
| // when holder == object). It works because slow properties objects having |
| // the same prototype (or a prototype with the same map) and not having |
| // the property are interchangeable for such a stub. |
| if (holder != object && |
| !object->HasFastProperties() && |
| !object->IsJSGlobalProxy() && |
| !object->IsJSGlobalObject()) { |
| return PROTOTYPE_MAP; |
| } |
| return OWN_MAP; |
| } |
| |
| |
| JSObject* IC::GetCodeCacheHolder(Object* object, InlineCacheHolderFlag holder) { |
| Object* map_owner = (holder == OWN_MAP ? object : object->GetPrototype()); |
| ASSERT(map_owner->IsJSObject()); |
| return JSObject::cast(map_owner); |
| } |
| |
| |
| } } // namespace v8::internal |
| |
| #endif // V8_IC_INL_H_ |