]>
Commit | Line | Data |
---|---|---|
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 <wtf/UnusedParam.h> | |
36 | #include <wtf/OwnArrayPtr.h> | |
37 | #include <wtf/UnusedParam.h> | |
38 | ||
39 | namespace JSC { | |
40 | ||
41 | class LLIntOffsetsExtractor; | |
42 | class Register; | |
43 | ||
44 | class JSVariableObject : public JSNonFinalObject { | |
45 | friend class JIT; | |
46 | friend class LLIntOffsetsExtractor; | |
47 | ||
48 | public: | |
49 | typedef JSNonFinalObject Base; | |
50 | ||
51 | SymbolTable& symbolTable() const { return *m_symbolTable; } | |
52 | ||
53 | JS_EXPORT_PRIVATE static void destroy(JSCell*); | |
54 | ||
55 | static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); | |
56 | ||
57 | JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier&); | |
58 | JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); | |
59 | ||
60 | bool isDynamicScope(bool& requiresDynamicChecks) const; | |
61 | ||
62 | WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; } | |
63 | ||
64 | WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; } | |
65 | static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); } | |
66 | ||
67 | static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) | |
68 | { | |
69 | return Structure::create(globalData, globalObject, prototype, TypeInfo(VariableObjectType, StructureFlags), &s_info); | |
70 | } | |
71 | ||
72 | protected: | |
73 | static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags; | |
74 | ||
75 | JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers) | |
76 | : JSNonFinalObject(globalData, structure) | |
77 | , m_symbolTable(symbolTable) | |
78 | , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers)) | |
79 | { | |
80 | } | |
81 | ||
82 | void finishCreation(JSGlobalData& globalData) | |
83 | { | |
84 | Base::finishCreation(globalData); | |
85 | ASSERT(m_symbolTable); | |
86 | COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier); | |
87 | } | |
88 | ||
89 | PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts); | |
90 | void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray); | |
91 | ||
92 | bool symbolTableGet(const Identifier&, PropertySlot&); | |
93 | JS_EXPORT_PRIVATE bool symbolTableGet(const Identifier&, PropertyDescriptor&); | |
94 | bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); | |
95 | bool symbolTablePut(ExecState*, const Identifier&, JSValue, bool shouldThrow); | |
96 | bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes); | |
97 | ||
98 | SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file. | |
99 | WriteBarrier<Unknown>* m_registers; // "r" in the register file. | |
100 | OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. | |
101 | }; | |
102 | ||
103 | inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) | |
104 | { | |
105 | SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); | |
106 | if (!entry.isNull()) { | |
107 | slot.setValue(registerAt(entry.getIndex()).get()); | |
108 | return true; | |
109 | } | |
110 | return false; | |
111 | } | |
112 | ||
113 | inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable) | |
114 | { | |
115 | SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); | |
116 | if (!entry.isNull()) { | |
117 | slot.setValue(registerAt(entry.getIndex()).get()); | |
118 | slotIsWriteable = !entry.isReadOnly(); | |
119 | return true; | |
120 | } | |
121 | return false; | |
122 | } | |
123 | ||
124 | inline bool JSVariableObject::symbolTablePut(ExecState* exec, const Identifier& propertyName, JSValue value, bool shouldThrow) | |
125 | { | |
126 | JSGlobalData& globalData = exec->globalData(); | |
127 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); | |
128 | ||
129 | SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); | |
130 | if (entry.isNull()) | |
131 | return false; | |
132 | if (entry.isReadOnly()) { | |
133 | if (shouldThrow) | |
134 | throwTypeError(exec, StrictModeReadonlyPropertyWriteError); | |
135 | return true; | |
136 | } | |
137 | registerAt(entry.getIndex()).set(globalData, this, value); | |
138 | return true; | |
139 | } | |
140 | ||
141 | inline bool JSVariableObject::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) | |
142 | { | |
143 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); | |
144 | ||
145 | SymbolTable::iterator iter = symbolTable().find(propertyName.impl()); | |
146 | if (iter == symbolTable().end()) | |
147 | return false; | |
148 | SymbolTableEntry& entry = iter->second; | |
149 | ASSERT(!entry.isNull()); | |
150 | entry.setAttributes(attributes); | |
151 | registerAt(entry.getIndex()).set(globalData, this, value); | |
152 | return true; | |
153 | } | |
154 | ||
155 | inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts) | |
156 | { | |
157 | OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[count]); | |
158 | for (size_t i = 0; i < callframeStarts; i++) | |
159 | registerArray[i].set(globalData, this, src[i].get()); | |
160 | for (size_t i = callframeStarts + RegisterFile::CallFrameHeaderSize; i < count; i++) | |
161 | registerArray[i].set(globalData, this, src[i].get()); | |
162 | ||
163 | return registerArray.release(); | |
164 | } | |
165 | ||
166 | inline void JSVariableObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray) | |
167 | { | |
168 | ASSERT(registerArray != m_registerArray); | |
169 | m_registerArray = registerArray; | |
170 | m_registers = registers; | |
171 | } | |
172 | ||
173 | } // namespace JSC | |
174 | ||
175 | #endif // JSVariableObject_h |