ComplexGetStatus.h
1 /* 2 * Copyright (C) 2014, 2015 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 #pragma once 27 28 #include "ObjectPropertyConditionSet.h" 29 #include "PropertyOffset.h" 30 31 namespace JSC { 32 33 class CodeBlock; 34 class StructureChain; 35 36 // This class is useful for figuring out how to inline a cached get-like access. We 37 // say "get-like" because this is appropriate for loading the GetterSetter object in 38 // a put_by_id that hits a setter. Notably, this doesn't figure out how to call 39 // accessors, or even whether they should be called. What it gives us, is a way of 40 // determining how to load the value from the requested property (identified by a 41 // StringImpl* uid) from an object of the given structure in the given CodeBlock, 42 // assuming that such an access had already been cached by Repatch (and so Repatch had 43 // already done a bunch of safety checks). This doesn't reexecute any checks that 44 // Repatch would have executed, and for prototype chain accesses, it doesn't ask the 45 // objects in the prototype chain whether their getOwnPropertySlot would attempt to 46 // intercept the access - so this really is only appropriate if you already know that 47 // one of the JITOperations had OK'd this for caching and that Repatch concurred. 48 // 49 // The typical use pattern is something like: 50 // 51 // ComplexGetStatus status = ComplexGetStatus::computeFor(...); 52 // switch (status.kind()) { 53 // case ComplexGetStatus::ShouldSkip: 54 // // Handle the case where this kind of access is possibly safe but wouldn't 55 // // pass the required safety checks. For example, if an IC gives us a list of 56 // // accesses and one of them is ShouldSkip, then we should pretend as if it 57 // // wasn't even there. 58 // break; 59 // case ComplexGetStatus::TakesSlowPath: 60 // // This kind of access is not safe to inline. Bail out of any attempst to 61 // // inline. 62 // break; 63 // case ComplexGetStatus::Inlineable: 64 // // The good stuff goes here. If it's Inlineable then the other properties of 65 // // the 'status' object will tell you everything you need to know about how 66 // // to execute the get-like operation. 67 // break; 68 // } 69 70 class ComplexGetStatus final { 71 public: 72 enum Kind { 73 ShouldSkip, 74 TakesSlowPath, 75 Inlineable 76 }; 77 78 ComplexGetStatus() 79 : m_kind(ShouldSkip) 80 , m_offset(invalidOffset) 81 { 82 } 83 84 static ComplexGetStatus skip() 85 { 86 return ComplexGetStatus(); 87 } 88 89 static ComplexGetStatus takesSlowPath() 90 { 91 ComplexGetStatus result; 92 result.m_kind = TakesSlowPath; 93 return result; 94 } 95 96 static ComplexGetStatus computeFor( 97 Structure* headStructure, const ObjectPropertyConditionSet&, UniquedStringImpl* uid); 98 99 Kind kind() const { return m_kind; } 100 PropertyOffset offset() const { return m_offset; } 101 const ObjectPropertyConditionSet& conditionSet() const { return m_conditionSet; } 102 103 private: 104 Kind m_kind; 105 PropertyOffset m_offset; 106 ObjectPropertyConditionSet m_conditionSet; 107 }; 108 109 } // namespace JSC