|  | /* | 
|  | * 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. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #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 final { | 
|  | 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 |