1/* 2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "IntendedStructureChain.h" 28 29#include "CodeBlock.h" 30#include "JSCInlines.h" 31#include "StructureChain.h" 32#include <wtf/CommaPrinter.h> 33 34namespace JSC { 35 36IntendedStructureChain::IntendedStructureChain(JSGlobalObject* globalObject, Structure* head) 37 : m_globalObject(globalObject) 38 , m_head(head) 39{ 40 JSValue prototype = head->prototypeForLookup(globalObject); 41 if (prototype.isNull()) 42 return; 43 for (Structure* current = asObject(prototype)->structure(); current; current = current->storedPrototypeStructure()) 44 m_vector.append(current); 45} 46 47IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, Structure* prototypeStructure) 48 : m_globalObject(codeBlock->globalObject()) 49 , m_head(head) 50{ 51 m_vector.append(prototypeStructure); 52} 53 54IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain) 55 : m_globalObject(codeBlock->globalObject()) 56 , m_head(head) 57{ 58 for (unsigned i = 0; chain->head()[i]; ++i) 59 m_vector.append(chain->head()[i].get()); 60} 61 62IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain, unsigned count) 63 : m_globalObject(codeBlock->globalObject()) 64 , m_head(head) 65{ 66 for (unsigned i = 0; i < count; ++i) 67 m_vector.append(chain->head()[i].get()); 68} 69 70IntendedStructureChain::~IntendedStructureChain() 71{ 72} 73 74bool IntendedStructureChain::isStillValid() const 75{ 76 JSValue currentPrototype = m_head->prototypeForLookup(m_globalObject); 77 for (unsigned i = 0; i < m_vector.size(); ++i) { 78 if (asObject(currentPrototype)->structure() != m_vector[i]) 79 return false; 80 currentPrototype = m_vector[i]->storedPrototype(); 81 } 82 return true; 83} 84 85bool IntendedStructureChain::matches(StructureChain* chain) const 86{ 87 for (unsigned i = 0; i < m_vector.size(); ++i) { 88 if (m_vector[i] != chain->head()[i].get()) 89 return false; 90 } 91 if (chain->head()[m_vector.size()]) 92 return false; 93 return true; 94} 95 96StructureChain* IntendedStructureChain::chain(VM& vm) const 97{ 98 ASSERT(isStillValid()); 99 StructureChain* result = StructureChain::create(vm, m_head); 100 ASSERT(matches(result)); 101 return result; 102} 103 104bool IntendedStructureChain::mayInterceptStoreTo(VM& vm, StringImpl* uid) 105{ 106 for (unsigned i = 0; i < m_vector.size(); ++i) { 107 unsigned attributes; 108 JSCell* specificValue; 109 PropertyOffset offset = m_vector[i]->getConcurrently(vm, uid, attributes, specificValue); 110 if (!isValidOffset(offset)) 111 continue; 112 if (attributes & (ReadOnly | Accessor)) 113 return true; 114 return false; 115 } 116 return false; 117} 118 119bool IntendedStructureChain::isNormalized() 120{ 121 if (m_head->isProxy()) 122 return false; 123 for (unsigned i = 0; i < m_vector.size(); ++i) { 124 Structure* structure = m_vector[i]; 125 if (structure->isProxy()) 126 return false; 127 if (structure->isDictionary()) 128 return false; 129 } 130 return true; 131} 132 133JSObject* IntendedStructureChain::terminalPrototype() const 134{ 135 ASSERT(!m_vector.isEmpty()); 136 if (m_vector.size() == 1) 137 return asObject(m_head->prototypeForLookup(m_globalObject)); 138 return asObject(m_vector[m_vector.size() - 2]->storedPrototype()); 139} 140 141void IntendedStructureChain::visitChildren(SlotVisitor& visitor) 142{ 143 visitor.appendUnbarrieredPointer(&m_globalObject); 144 visitor.appendUnbarrieredPointer(&m_head); 145 for (unsigned i = m_vector.size(); i--;) 146 visitor.appendUnbarrieredPointer(&m_vector[i]); 147} 148 149void IntendedStructureChain::dump(PrintStream& out) const 150{ 151 dumpInContext(out, 0); 152} 153 154void IntendedStructureChain::dumpInContext(PrintStream& out, DumpContext* context) const 155{ 156 out.print( 157 "(global = ", RawPointer(m_globalObject), ", head = ", 158 pointerDumpInContext(m_head, context), ", vector = ["); 159 CommaPrinter comma; 160 for (unsigned i = 0; i < m_vector.size(); ++i) 161 out.print(comma, pointerDumpInContext(m_vector[i], context)); 162 out.print("])"); 163} 164 165} // namespace JSC 166 167