/* * Copyright (C) 2014, 2015 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 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 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. */ #ifndef ComplexGetStatus_h #define ComplexGetStatus_h #include "JSCJSValue.h" #include "ObjectPropertyConditionSet.h" #include "PropertyOffset.h" namespace JSC { class CodeBlock; class StructureChain; // This class is useful for figuring out how to inline a cached get-like access. We // say "get-like" because this is appropriate for loading the GetterSetter object in // a put_by_id that hits a setter. Notably, this doesn't figure out how to call // accessors, or even whether they should be called. What it gives us, is a way of // determining how to load the value from the requested property (identified by a // StringImpl* uid) from an object of the given structure in the given CodeBlock, // assuming that such an access had already been cached by Repatch (and so Repatch had // already done a bunch of safety checks). This doesn't reexecute any checks that // Repatch would have executed, and for prototype chain accesses, it doesn't ask the // objects in the prototype chain whether their getOwnPropertySlot would attempt to // intercept the access - so this really is only appropriate if you already know that // one of the JITOperations had OK'd this for caching and that Repatch concurred. // // The typical use pattern is something like: // // ComplexGetStatus status = ComplexGetStatus::computeFor(...); // switch (status.kind()) { // case ComplexGetStatus::ShouldSkip: // // Handle the case where this kind of access is possibly safe but wouldn't // // pass the required safety checks. For example, if an IC gives us a list of // // accesses and one of them is ShouldSkip, then we should pretend as if it // // wasn't even there. // break; // case ComplexGetStatus::TakesSlowPath: // // This kind of access is not safe to inline. Bail out of any attempst to // // inline. // break; // case ComplexGetStatus::Inlineable: // // The good stuff goes here. If it's Inlineable then the other properties of // // the 'status' object will tell you everything you need to know about how // // to execute the get-like operation. // break; // } class ComplexGetStatus { public: enum Kind { ShouldSkip, TakesSlowPath, Inlineable }; ComplexGetStatus() : m_kind(ShouldSkip) , m_offset(invalidOffset) { } static ComplexGetStatus skip() { return ComplexGetStatus(); } static ComplexGetStatus takesSlowPath() { ComplexGetStatus result; result.m_kind = TakesSlowPath; return result; } static ComplexGetStatus computeFor( Structure* headStructure, const ObjectPropertyConditionSet&, UniquedStringImpl* uid); Kind kind() const { return m_kind; } PropertyOffset offset() const { return m_offset; } const ObjectPropertyConditionSet& conditionSet() const { return m_conditionSet; } private: Kind m_kind; PropertyOffset m_offset; ObjectPropertyConditionSet m_conditionSet; }; } // namespace JSC #endif // ComplexGetStatus_h