De-virtualize JSVariableObject::isDynamicScope
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSVariableObject.h
1 /*
2  * Copyright (C) 2007, 2008 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  *
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  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #ifndef JSVariableObject_h
30 #define JSVariableObject_h
31
32 #include "JSObject.h"
33 #include "Register.h"
34 #include "SymbolTable.h"
35 #include "UnusedParam.h"
36 #include <wtf/OwnArrayPtr.h>
37 #include <wtf/UnusedParam.h>
38
39 namespace JSC {
40
41     class Register;
42
43     class JSVariableObject : public JSNonFinalObject {
44         friend class JIT;
45
46     public:
47         typedef JSNonFinalObject Base;
48
49         SymbolTable& symbolTable() const { return *m_symbolTable; }
50
51         virtual ~JSVariableObject();
52
53         static NO_RETURN_DUE_TO_ASSERT void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
54
55         static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
56         static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
57         
58         bool isDynamicScope(bool& requiresDynamicChecks) const;
59
60         WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
61
62         WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
63         static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); }
64
65         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
66         {
67             return Structure::create(globalData, globalObject, prototype, TypeInfo(VariableObjectType, StructureFlags), &s_info);
68         }
69         
70     protected:
71         static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags;
72
73         JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
74             : JSNonFinalObject(globalData, structure)
75             , m_symbolTable(symbolTable)
76             , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers))
77         {
78         }
79
80         void finishCreation(JSGlobalData& globalData)
81         {
82             Base::finishCreation(globalData);
83             ASSERT(m_symbolTable);
84             COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier);
85         }
86
87         PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts);
88         void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
89
90         bool symbolTableGet(const Identifier&, PropertySlot&);
91         bool symbolTableGet(const Identifier&, PropertyDescriptor&);
92         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
93         bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue);
94         bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
95
96         SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file.
97         WriteBarrier<Unknown>* m_registers; // "r" in the register file.
98         OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
99     };
100
101     inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
102     {
103         SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
104         if (!entry.isNull()) {
105             slot.setValue(registerAt(entry.getIndex()).get());
106             return true;
107         }
108         return false;
109     }
110
111     inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
112     {
113         SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
114         if (!entry.isNull()) {
115             slot.setValue(registerAt(entry.getIndex()).get());
116             slotIsWriteable = !entry.isReadOnly();
117             return true;
118         }
119         return false;
120     }
121
122     inline bool JSVariableObject::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
123     {
124         ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
125
126         SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
127         if (entry.isNull())
128             return false;
129         if (entry.isReadOnly())
130             return true;
131         registerAt(entry.getIndex()).set(globalData, this, value);
132         return true;
133     }
134
135     inline bool JSVariableObject::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
136     {
137         ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
138
139         SymbolTable::iterator iter = symbolTable().find(propertyName.impl());
140         if (iter == symbolTable().end())
141             return false;
142         SymbolTableEntry& entry = iter->second;
143         ASSERT(!entry.isNull());
144         entry.setAttributes(attributes);
145         registerAt(entry.getIndex()).set(globalData, this, value);
146         return true;
147     }
148
149     inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts)
150     {
151         OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[count]);
152         for (size_t i = 0; i < callframeStarts; i++)
153             registerArray[i].set(globalData, this, src[i].get());
154         for (size_t i = callframeStarts + RegisterFile::CallFrameHeaderSize; i < count; i++)
155             registerArray[i].set(globalData, this, src[i].get());
156
157         return registerArray.release();
158     }
159
160     inline void JSVariableObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray)
161     {
162         ASSERT(registerArray != m_registerArray);
163         m_registerArray = registerArray;
164         m_registers = registers;
165     }
166
167 } // namespace JSC
168
169 #endif // JSVariableObject_h