1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2008, 2015 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29// This file would be called TypeInfo.h, but that conflicts with <typeinfo.h>
30// in the STL on systems without case-sensitive file systems.
31
32#include "JSType.h"
33
34namespace JSC {
35
36class LLIntOffsetsExtractor;
37
38// Inline flags.
39
40static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all undetectable.
41static const unsigned ImplementsDefaultHasInstance = 1 << 1;
42static const unsigned OverridesGetCallData = 1 << 2; // Need this flag if you implement [[Callable]] interface, which means overriding getCallData. The object may not be callable since getCallData can say it is not callable.
43static const unsigned OverridesGetOwnPropertySlot = 1 << 3;
44static const unsigned OverridesToThis = 1 << 4; // If this is false then this returns something other than 'this'. Non-object cells that are visible to JS have this set as do some exotic objects.
45static const unsigned HasStaticPropertyTable = 1 << 5;
46static const unsigned TypeInfoPerCellBit = 1 << 7; // Unlike other inline flags, this will only be set on the cell itself and will not be set on the Structure.
47
48// Out of line flags.
49
50static const unsigned ImplementsHasInstance = 1 << 8;
51static const unsigned OverridesGetPropertyNames = 1 << 9;
52static const unsigned ProhibitsPropertyCaching = 1 << 10;
53static const unsigned GetOwnPropertySlotIsImpure = 1 << 11;
54static const unsigned NewImpurePropertyFiresWatchpoints = 1 << 12;
55static const unsigned IsImmutablePrototypeExoticObject = 1 << 13;
56static const unsigned GetOwnPropertySlotIsImpureForPropertyAbsence = 1 << 14;
57static const unsigned InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero = 1 << 15;
58static const unsigned StructureIsImmortal = 1 << 16;
59
60class TypeInfo {
61public:
62 typedef uint8_t InlineTypeFlags;
63 typedef uint16_t OutOfLineTypeFlags;
64
65 TypeInfo(JSType type, unsigned flags = 0)
66 : TypeInfo(type, flags & 0xff, flags >> 8)
67 {
68 ASSERT(!(flags >> 24));
69 }
70
71 TypeInfo(JSType type, InlineTypeFlags inlineTypeFlags, OutOfLineTypeFlags outOfLineTypeFlags)
72 : m_type(type)
73 , m_flags(inlineTypeFlags)
74 , m_flags2(outOfLineTypeFlags)
75 {
76 }
77
78 JSType type() const { return static_cast<JSType>(m_type); }
79 bool isObject() const { return isObject(type()); }
80 static bool isObject(JSType type) { return type >= ObjectType; }
81 bool isFinalObject() const { return type() == FinalObjectType; }
82 bool isNumberObject() const { return type() == NumberObjectType; }
83
84 unsigned flags() const { return (static_cast<unsigned>(m_flags2) << 8) | static_cast<unsigned>(m_flags); }
85 bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); }
86 bool implementsHasInstance() const { return isSetOnFlags2(ImplementsHasInstance); }
87 bool implementsDefaultHasInstance() const { return isSetOnFlags1(ImplementsDefaultHasInstance); }
88 bool overridesGetCallData() const { return isSetOnFlags1(OverridesGetCallData); }
89 bool overridesGetOwnPropertySlot() const { return overridesGetOwnPropertySlot(inlineTypeFlags()); }
90 static bool overridesGetOwnPropertySlot(InlineTypeFlags flags) { return flags & OverridesGetOwnPropertySlot; }
91 static bool hasStaticPropertyTable(InlineTypeFlags flags) { return flags & HasStaticPropertyTable; }
92 static bool perCellBit(InlineTypeFlags flags) { return flags & TypeInfoPerCellBit; }
93 bool overridesToThis() const { return isSetOnFlags1(OverridesToThis); }
94 bool structureIsImmortal() const { return isSetOnFlags2(StructureIsImmortal); }
95 bool overridesGetPropertyNames() const { return isSetOnFlags2(OverridesGetPropertyNames); }
96 bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); }
97 bool getOwnPropertySlotIsImpure() const { return isSetOnFlags2(GetOwnPropertySlotIsImpure); }
98 bool getOwnPropertySlotIsImpureForPropertyAbsence() const { return isSetOnFlags2(GetOwnPropertySlotIsImpureForPropertyAbsence); }
99 bool newImpurePropertyFiresWatchpoints() const { return isSetOnFlags2(NewImpurePropertyFiresWatchpoints); }
100 bool isImmutablePrototypeExoticObject() const { return isSetOnFlags2(IsImmutablePrototypeExoticObject); }
101 bool interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero() const { return isSetOnFlags2(InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero); }
102
103 static bool isArgumentsType(JSType type)
104 {
105 return type == DirectArgumentsType
106 || type == ScopedArgumentsType
107 || type == ClonedArgumentsType;
108 }
109
110 static ptrdiff_t flagsOffset()
111 {
112 return OBJECT_OFFSETOF(TypeInfo, m_flags);
113 }
114
115 static ptrdiff_t typeOffset()
116 {
117 return OBJECT_OFFSETOF(TypeInfo, m_type);
118 }
119
120 // Since the Structure doesn't track TypeInfoPerCellBit, we need to make sure we copy it.
121 static InlineTypeFlags mergeInlineTypeFlags(InlineTypeFlags structureFlags, InlineTypeFlags oldCellFlags)
122 {
123 return structureFlags | (oldCellFlags & static_cast<InlineTypeFlags>(TypeInfoPerCellBit));
124 }
125
126 InlineTypeFlags inlineTypeFlags() const { return m_flags; }
127 OutOfLineTypeFlags outOfLineTypeFlags() const { return m_flags2; }
128
129private:
130 friend class LLIntOffsetsExtractor;
131
132 bool isSetOnFlags1(unsigned flag) const { ASSERT(flag <= (1 << 7)); return m_flags & flag; }
133 bool isSetOnFlags2(unsigned flag) const { ASSERT(flag >= (1 << 8)); return m_flags2 & (flag >> 8); }
134
135 uint8_t m_type;
136 uint8_t m_flags;
137 uint16_t m_flags2;
138};
139
140} // namespace JSC
141