]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Lookup.h
JavaScriptCore-554.1.tar.gz
[apple/javascriptcore.git] / runtime / Lookup.h
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21#ifndef Lookup_h
22#define Lookup_h
23
24#include "CallFrame.h"
25#include "Identifier.h"
9dae56ea
A
26#include "JSGlobalObject.h"
27#include "JSObject.h"
28#include "PropertySlot.h"
29#include <stdio.h>
30#include <wtf/Assertions.h>
31
ba379fdc
A
32// Bug #26843: Work around Metrowerks compiler bug
33#if COMPILER(WINSCW)
34#define JSC_CONST_HASHTABLE
35#else
36#define JSC_CONST_HASHTABLE const
37#endif
9dae56ea
A
38
39namespace JSC {
40
41 // Hash table generated by the create_hash_table script.
42 struct HashTableValue {
43 const char* key; // property name
44 unsigned char attributes; // JSObject attributes
45 intptr_t value1;
46 intptr_t value2;
47 };
48
49 // FIXME: There is no reason this get function can't be simpler.
ba379fdc 50 // ie. typedef JSValue (*GetFunction)(ExecState*, JSObject* baseObject)
9dae56ea 51 typedef PropertySlot::GetValueFunc GetFunction;
ba379fdc 52 typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
9dae56ea
A
53
54 class HashEntry {
55 public:
56 void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
57 {
58 m_key = key;
59 m_attributes = attributes;
60 m_u.store.value1 = v1;
61 m_u.store.value2 = v2;
9dae56ea 62 m_next = 0;
9dae56ea
A
63 }
64
65 void setKey(UString::Rep* key) { m_key = key; }
66 UString::Rep* key() const { return m_key; }
67
68 unsigned char attributes() const { return m_attributes; }
69
70 NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
71 unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); }
72
73 GetFunction propertyGetter() const { ASSERT(!(m_attributes & Function)); return m_u.property.get; }
74 PutFunction propertyPutter() const { ASSERT(!(m_attributes & Function)); return m_u.property.put; }
75
76 intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; }
77
9dae56ea
A
78 void setNext(HashEntry *next) { m_next = next; }
79 HashEntry* next() const { return m_next; }
9dae56ea
A
80
81 private:
82 UString::Rep* m_key;
83 unsigned char m_attributes; // JSObject attributes
84
85 union {
86 struct {
87 intptr_t value1;
88 intptr_t value2;
89 } store;
90 struct {
91 NativeFunction functionValue;
92 intptr_t length; // number of arguments for function
93 } function;
94 struct {
95 GetFunction get;
96 PutFunction put;
97 } property;
98 struct {
99 intptr_t value;
100 intptr_t unused;
101 } lexer;
102 } m_u;
103
9dae56ea 104 HashEntry* m_next;
9dae56ea
A
105 };
106
107 struct HashTable {
ba379fdc 108
9dae56ea
A
109 int compactSize;
110 int compactHashSizeMask;
ba379fdc 111
9dae56ea
A
112 const HashTableValue* values; // Fixed values generated by script.
113 mutable const HashEntry* table; // Table allocated at runtime.
114
115 ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const
116 {
117 if (!table)
118 createTable(globalData);
119 }
120
121 ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const
122 {
123 if (!table)
124 createTable(&exec->globalData());
125 }
126
127 void deleteTable() const;
128
129 // Find an entry in the table, and return the entry.
130 ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
131 {
132 initializeIfNeeded(globalData);
133 return entry(identifier);
134 }
135
136 ALWAYS_INLINE const HashEntry* entry(ExecState* exec, const Identifier& identifier) const
137 {
138 initializeIfNeeded(exec);
139 return entry(identifier);
140 }
141
142 private:
143 ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
144 {
9dae56ea
A
145 ASSERT(table);
146
147 const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & compactHashSizeMask];
148
149 if (!entry->key())
150 return 0;
151
152 do {
153 if (entry->key() == identifier.ustring().rep())
154 return entry;
155 entry = entry->next();
156 } while (entry);
157
158 return 0;
9dae56ea
A
159 }
160
161 // Convert the hash table keys to identifiers.
162 void createTable(JSGlobalData*) const;
163 };
164
165 void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
166
167 /**
168 * This method does it all (looking in the hashtable, checking for function
169 * overrides, creating the function or retrieving from cache, calling
170 * getValueProperty in case of a non-function property, forwarding to parent if
171 * unknown property).
172 */
173 template <class ThisImp, class ParentImp>
174 inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
175 {
176 const HashEntry* entry = table->entry(exec, propertyName);
177
178 if (!entry) // not found, forward to parent
179 return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
180
181 if (entry->attributes() & Function)
182 setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
183 else
184 slot.setCustom(thisObj, entry->propertyGetter());
185
186 return true;
187 }
188
189 /**
190 * Simplified version of getStaticPropertySlot in case there are only functions.
191 * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
192 * a dummy getValueProperty.
193 */
194 template <class ParentImp>
195 inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
196 {
197 if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot))
198 return true;
199
200 const HashEntry* entry = table->entry(exec, propertyName);
201 if (!entry)
202 return false;
203
204 setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
205 return true;
206 }
207
208 /**
209 * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
210 * Using this instead of getStaticPropertySlot removes the need for a FuncImp class.
211 */
212 template <class ThisImp, class ParentImp>
213 inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
214 {
215 const HashEntry* entry = table->entry(exec, propertyName);
216
217 if (!entry) // not found, forward to parent
218 return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
219
220 ASSERT(!(entry->attributes() & Function));
221
222 slot.setCustom(thisObj, entry->propertyGetter());
223 return true;
224 }
225
226 /**
227 * This one is for "put".
228 * It looks up a hash entry for the property to be set. If an entry
229 * is found it sets the value and returns true, else it returns false.
230 */
231 template <class ThisImp>
ba379fdc 232 inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj)
9dae56ea
A
233 {
234 const HashEntry* entry = table->entry(exec, propertyName);
235
236 if (!entry)
237 return false;
238
ba379fdc
A
239 if (entry->attributes() & Function) { // function: put as override property
240 if (LIKELY(value.isCell()))
241 thisObj->putDirectFunction(propertyName, value.asCell());
242 else
243 thisObj->putDirect(propertyName, value);
244 } else if (!(entry->attributes() & ReadOnly))
9dae56ea
A
245 entry->propertyPutter()(exec, thisObj, value);
246
247 return true;
248 }
249
250 /**
251 * This one is for "put".
252 * It calls lookupPut<ThisImp>() to set the value. If that call
253 * returns false (meaning no entry in the hash table was found),
254 * then it calls put() on the ParentImp class.
255 */
256 template <class ThisImp, class ParentImp>
ba379fdc 257 inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot)
9dae56ea
A
258 {
259 if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj))
260 thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent
261 }
262
263} // namespace JSC
264
265#endif // Lookup_h