source: webkit/trunk/JavaScriptCore/runtime/Lookup.h@ 45011

Last change on this file since 45011 was 44224, checked in by [email protected], 16 years ago

Revert 44221.

  • Property svn:eol-style set to native
File size: 9.0 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
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"
26#include "JSGlobalObject.h"
27#include "JSObject.h"
28#include "PropertySlot.h"
29#include <stdio.h>
30#include <wtf/Assertions.h>
31
32namespace JSC {
33
34 // Hash table generated by the create_hash_table script.
35 struct HashTableValue {
36 const char* key; // property name
37 unsigned char attributes; // JSObject attributes
38 intptr_t value1;
39 intptr_t value2;
40 };
41
42 // FIXME: There is no reason this get function can't be simpler.
43 // ie. typedef JSValue (*GetFunction)(ExecState*, JSObject* baseObject)
44 typedef PropertySlot::GetValueFunc GetFunction;
45 typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
46
47 class HashEntry {
48 public:
49 void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
50 {
51 m_key = key;
52 m_attributes = attributes;
53 m_u.store.value1 = v1;
54 m_u.store.value2 = v2;
55 m_next = 0;
56 }
57
58 void setKey(UString::Rep* key) { m_key = key; }
59 UString::Rep* key() const { return m_key; }
60
61 unsigned char attributes() const { return m_attributes; }
62
63 NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
64 unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); }
65
66 GetFunction propertyGetter() const { ASSERT(!(m_attributes & Function)); return m_u.property.get; }
67 PutFunction propertyPutter() const { ASSERT(!(m_attributes & Function)); return m_u.property.put; }
68
69 intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; }
70
71 void setNext(HashEntry *next) { m_next = next; }
72 HashEntry* next() const { return m_next; }
73
74 private:
75 UString::Rep* m_key;
76 unsigned char m_attributes; // JSObject attributes
77
78 union {
79 struct {
80 intptr_t value1;
81 intptr_t value2;
82 } store;
83 struct {
84 NativeFunction functionValue;
85 intptr_t length; // number of arguments for function
86 } function;
87 struct {
88 GetFunction get;
89 PutFunction put;
90 } property;
91 struct {
92 intptr_t value;
93 intptr_t unused;
94 } lexer;
95 } m_u;
96
97 HashEntry* m_next;
98 };
99
100 struct HashTable {
101
102 int compactSize;
103 int compactHashSizeMask;
104
105 const HashTableValue* values; // Fixed values generated by script.
106 mutable const HashEntry* table; // Table allocated at runtime.
107
108 ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const
109 {
110 if (!table)
111 createTable(globalData);
112 }
113
114 ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const
115 {
116 if (!table)
117 createTable(&exec->globalData());
118 }
119
120 void deleteTable() const;
121
122 // Find an entry in the table, and return the entry.
123 ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
124 {
125 initializeIfNeeded(globalData);
126 return entry(identifier);
127 }
128
129 ALWAYS_INLINE const HashEntry* entry(ExecState* exec, const Identifier& identifier) const
130 {
131 initializeIfNeeded(exec);
132 return entry(identifier);
133 }
134
135 private:
136 ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
137 {
138 ASSERT(table);
139
140 const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & compactHashSizeMask];
141
142 if (!entry->key())
143 return 0;
144
145 do {
146 if (entry->key() == identifier.ustring().rep())
147 return entry;
148 entry = entry->next();
149 } while (entry);
150
151 return 0;
152 }
153
154 // Convert the hash table keys to identifiers.
155 void createTable(JSGlobalData*) const;
156 };
157
158 void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
159
160 /**
161 * This method does it all (looking in the hashtable, checking for function
162 * overrides, creating the function or retrieving from cache, calling
163 * getValueProperty in case of a non-function property, forwarding to parent if
164 * unknown property).
165 */
166 template <class ThisImp, class ParentImp>
167 inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
168 {
169 const HashEntry* entry = table->entry(exec, propertyName);
170
171 if (!entry) // not found, forward to parent
172 return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
173
174 if (entry->attributes() & Function)
175 setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
176 else
177 slot.setCustom(thisObj, entry->propertyGetter());
178
179 return true;
180 }
181
182 /**
183 * Simplified version of getStaticPropertySlot in case there are only functions.
184 * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
185 * a dummy getValueProperty.
186 */
187 template <class ParentImp>
188 inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
189 {
190 if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot))
191 return true;
192
193 const HashEntry* entry = table->entry(exec, propertyName);
194 if (!entry)
195 return false;
196
197 setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
198 return true;
199 }
200
201 /**
202 * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
203 * Using this instead of getStaticPropertySlot removes the need for a FuncImp class.
204 */
205 template <class ThisImp, class ParentImp>
206 inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
207 {
208 const HashEntry* entry = table->entry(exec, propertyName);
209
210 if (!entry) // not found, forward to parent
211 return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
212
213 ASSERT(!(entry->attributes() & Function));
214
215 slot.setCustom(thisObj, entry->propertyGetter());
216 return true;
217 }
218
219 /**
220 * This one is for "put".
221 * It looks up a hash entry for the property to be set. If an entry
222 * is found it sets the value and returns true, else it returns false.
223 */
224 template <class ThisImp>
225 inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj)
226 {
227 const HashEntry* entry = table->entry(exec, propertyName);
228
229 if (!entry)
230 return false;
231
232 if (entry->attributes() & Function) { // function: put as override property
233 if (LIKELY(value.isCell()))
234 thisObj->putDirectFunction(propertyName, value.asCell());
235 else
236 thisObj->putDirect(propertyName, value);
237 } else if (!(entry->attributes() & ReadOnly))
238 entry->propertyPutter()(exec, thisObj, value);
239
240 return true;
241 }
242
243 /**
244 * This one is for "put".
245 * It calls lookupPut<ThisImp>() to set the value. If that call
246 * returns false (meaning no entry in the hash table was found),
247 * then it calls put() on the ParentImp class.
248 */
249 template <class ThisImp, class ParentImp>
250 inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot)
251 {
252 if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj))
253 thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent
254 }
255
256} // namespace JSC
257
258#endif // Lookup_h
Note: See TracBrowser for help on using the repository browser.