/* * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. */ #include "config.h" #include "IntendedStructureChain.h" #include "CodeBlock.h" #include "Operations.h" #include "StructureChain.h" namespace JSC { IntendedStructureChain::IntendedStructureChain(JSGlobalObject* globalObject, Structure* head) : m_globalObject(globalObject) , m_head(head) { JSValue prototype = head->prototypeForLookup(globalObject); if (prototype.isNull()) return; for (Structure* current = asObject(prototype)->structure(); current; current = current->storedPrototypeStructure()) m_vector.append(current); } IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, Structure* prototypeStructure) : m_globalObject(codeBlock->globalObject()) , m_head(head) { m_vector.append(prototypeStructure); } IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain) : m_globalObject(codeBlock->globalObject()) , m_head(head) { for (unsigned i = 0; chain->head()[i]; ++i) m_vector.append(chain->head()[i].get()); } IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain, unsigned count) : m_globalObject(codeBlock->globalObject()) , m_head(head) { for (unsigned i = 0; i < count; ++i) m_vector.append(chain->head()[i].get()); } IntendedStructureChain::~IntendedStructureChain() { } bool IntendedStructureChain::isStillValid() const { JSValue currentPrototype = m_head->prototypeForLookup(m_globalObject); for (unsigned i = 0; i < m_vector.size(); ++i) { if (asObject(currentPrototype)->structure() != m_vector[i]) return false; currentPrototype = m_vector[i]->storedPrototype(); } return true; } bool IntendedStructureChain::matches(StructureChain* chain) const { for (unsigned i = 0; i < m_vector.size(); ++i) { if (m_vector[i] != chain->head()[i].get()) return false; } if (chain->head()[m_vector.size()]) return false; return true; } StructureChain* IntendedStructureChain::chain(VM& vm) const { ASSERT(isStillValid()); StructureChain* result = StructureChain::create(vm, m_head); ASSERT(matches(result)); return result; } bool IntendedStructureChain::mayInterceptStoreTo(VM& vm, StringImpl* uid) { for (unsigned i = 0; i < m_vector.size(); ++i) { unsigned attributes; JSCell* specificValue; PropertyOffset offset = m_vector[i]->getConcurrently(vm, uid, attributes, specificValue); if (!isValidOffset(offset)) continue; if (attributes & (ReadOnly | Accessor)) return true; return false; } return false; } bool IntendedStructureChain::isNormalized() { if (m_head->typeInfo().type() == ProxyType) return false; for (unsigned i = 0; i < m_vector.size(); ++i) { Structure* structure = m_vector[i]; if (structure->typeInfo().type() == ProxyType) return false; if (structure->isDictionary()) return false; } return true; } JSObject* IntendedStructureChain::terminalPrototype() const { ASSERT(!m_vector.isEmpty()); if (m_vector.size() == 1) return asObject(m_head->prototypeForLookup(m_globalObject)); return asObject(m_vector[m_vector.size() - 2]->storedPrototype()); } } // namespace JSC