Changeset 31147 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Mar 18, 2008, 9:23:21 PM (17 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/create_hash_table
r27608 r31147 45 45 my @params = (); 46 46 my @hashes = (); 47 my @table = ();48 my @links = ();49 47 50 48 my $inside = 0; 51 49 my $name; 52 50 my $size; 53 my $hashSizeMask;54 51 my $banner = 0; 55 sub calc Table();52 sub calcSize(); 56 53 sub output(); 57 54 sub hashValue($); 58 55 59 56 while (<IN>) { 60 chop; 61 s/^\s*//g; 62 if (/^\#|^$/) { 63 # comment. do nothing 64 } elsif (/^\@begin/ && !$inside) { 65 if (/^\@begin\s*([:_\w]+)\s*\d*\s*$/) { 66 $inside = 1; 67 $name = $1; 68 } else { 69 printf STDERR "WARNING: \@begin without table name and hashsize, skipping $_\n"; 70 } 57 chomp; 58 s/^\s+//; 59 next if /^\#|^$/; # Comment or blank line. Do nothing. 60 if (/^\@begin/ && !$inside) { 61 if (/^\@begin\s*([:_\w]+)\s*\d*\s*$/) { 62 $inside = 1; 63 $name = $1; 64 } else { 65 print STDERR "WARNING: \@begin without table name, skipping $_\n"; 66 } 71 67 } elsif (/^\@end\s*$/ && $inside) { 72 73 calcTable(); 74 75 output(); 76 @keys = (); 77 @values = (); 78 @attrs = (); 79 @params = (); 80 @table = (); 81 @links = (); 82 @hashes = (); 83 $inside = 0; 68 calcSize(); 69 output(); 70 71 @keys = (); 72 @values = (); 73 @attrs = (); 74 @params = (); 75 @hashes = (); 76 77 $inside = 0; 84 78 } elsif (/^(\S+)\s*(\S+)\s*([\w\|]*)\s*(\w*)\s*$/ && $inside) { 85 my $key = $1; 86 my $val = $2; 87 my $att = $3; 88 my $param = $4; 89 push(@keys, $key); 90 push(@values, $val); 91 push(@hashes, hashValue($key)); 92 printf STDERR "WARNING: Number of arguments missing for $key/$val\n" 93 if ( $att =~ m/Function/ && length($param) == 0); 94 push(@attrs, length($att) > 0 ? $att : "0"); 95 push(@params, length($param) > 0 ? $param : "0"); 79 my $key = $1; 80 my $val = $2; 81 my $att = $3; 82 my $param = $4; 83 push(@keys, $key); 84 push(@values, $val); 85 push(@hashes, hashValue($key)); 86 printf STDERR "WARNING: Number of arguments missing for $key/$val\n" if ($att =~ m/Function/ && length($param) == 0); 87 push(@attrs, length($att) > 0 ? $att : "0"); 88 push(@params, length($param) > 0 ? $param : "0"); 96 89 } elsif ($inside) { 97 die "invalid data {" . $_ . "}";90 die "invalid data {" . $_ . "}"; 98 91 } 99 92 } … … 113 106 } 114 107 115 sub calcTable() { 116 my $hashsize = ceilingToPowerOf2(2 * @keys); 117 $hashSizeMask = $hashsize - 1; 118 $size = $hashsize; 119 my $collisions = 0; 120 my $maxdepth = 0; 121 my $i = 0; 122 foreach my $key (@keys) { 123 my $depth = 0; 124 my $h = hashValue($key) % $hashsize; 125 while (defined($table[$h])) { 126 if (defined($links[$h])) { 127 $h = $links[$h]; 128 $depth++; 129 } else { 130 $collisions++; 131 $links[$h] = $size; 132 $h = $size; 133 $size++; 134 } 135 } 136 $table[$h] = $i; 137 $i++; 138 $maxdepth = $depth if ( $depth > $maxdepth); 139 } 140 141 # Ensure table is big enough (in case of undef entries at the end) 142 if ( $#table+1 < $size ) { 143 $#table = $size-1; 144 } 108 sub calcSize() 109 { 110 tableSizeLoop: 111 for ($size = ceilingToPowerOf2(scalar @keys); ; $size += $size) { 112 my @table = (); 113 foreach my $key (@keys) { 114 my $h = hashValue($key) % $size; 115 next tableSizeLoop if $table[$h]; 116 $table[$h] = 1; 117 } 118 last; 119 } 145 120 } 146 121 … … 204 179 205 180 sub output() { 206 if (!$banner) { 207 $banner = 1; 208 print "/* Automatically generated from $file using $0. DO NOT EDIT ! */\n"; 209 } 210 211 my $nameEntries = "${name}Entries"; 212 $nameEntries =~ s/:/_/g; 213 214 print "\n#include \"lookup.h\"\n" if ($includelookup); 215 if ($useNameSpace) { 216 print "\nnamespace ${useNameSpace}\n{\n"; 217 print "\nusing namespace KJS;"; 218 } else { 219 print "\nnamespace KJS {\n"; 220 } 221 print "\nstatic const struct HashEntry ".$nameEntries."[] = {\n"; 222 my $i = 0; 223 224 foreach my $entry (@table) { 225 if (defined($entry)) { 226 my $key = $keys[$entry]; 227 print " \{ \"" . $key . "\""; 228 print ", { (intptr_t)" . $values[$entry] . " }"; 229 print ", " . $attrs[$entry]; 230 print ", " . $params[$entry]; 231 print ", "; 232 if (defined($links[$i])) { 233 print "&" . $nameEntries . "[" . $links[$i] . "]" . " \}"; 234 } else { 235 print "0 \}" 236 } 237 print "/* " . $hashes[$entry] . " */ "; 238 } else { 239 print " { 0, { 0 }, 0, 0, 0 }"; 240 } 241 print "," unless ($i == $size - 1); 242 print "\n"; 243 $i++; 244 } 245 246 print "};\n\n"; 247 print "const struct HashTable $name = "; 248 print "\{ 3, $size, $nameEntries, $hashSizeMask \};\n\n"; 249 print "} // namespace\n"; 250 } 181 if (!$banner) { 182 $banner = 1; 183 print "// Automatically generated from $file using $0. DO NOT EDIT!\n"; 184 } 185 186 my $nameEntries = "${name}Values"; 187 $nameEntries =~ s/:/_/g; 188 189 print "\n#include \"lookup.h\"\n" if ($includelookup); 190 if ($useNameSpace) { 191 print "\nnamespace ${useNameSpace}\n{\n"; 192 print "\nusing namespace KJS;"; 193 } else { 194 print "\nnamespace KJS {\n"; 195 } 196 my $count = scalar @keys + 1; 197 print "\nstatic const struct HashTableValue ${nameEntries}[$count] = {\n"; 198 my $i = 0; 199 foreach my $key (@keys) { 200 print " { \"$key\", (intptr_t)$values[$i], $attrs[$i], $params[$i] },\n"; 201 $i++; 202 } 203 print " { 0, 0, 0, 0 }\n"; 204 print "};\n\n"; 205 print "const struct HashTable $name = "; 206 print "\{ ", $size - 1, ", $nameEntries, 0 \};\n\n"; 207 print "} // namespace\n"; 208 } -
trunk/JavaScriptCore/kjs/identifier.h
r27206 r31147 62 62 friend bool operator==(const Identifier&, const char*); 63 63 64 static void remove(UString::Rep* 64 static void remove(UString::Rep*); 65 65 66 66 static bool equal(const UString::Rep*, const char*); 67 67 static bool equal(const UString::Rep*, const UChar*, int length); 68 68 static bool equal(const UString::Rep*, const UString::Rep*); 69 70 static PassRefPtr<UString::Rep> add(const char*); 69 71 70 72 private: … … 76 78 { return equal(a._ustring.rep(), b); } 77 79 78 static PassRefPtr<UString::Rep> add(const char*);79 80 static PassRefPtr<UString::Rep> add(const UChar*, int length); 80 81 static PassRefPtr<UString::Rep> add(UString::Rep* r) -
trunk/JavaScriptCore/kjs/lexer.cpp
r30942 r31147 524 524 #endif 525 525 526 if (state != Identifier && eatNextIdentifier)526 if (state != Identifier) 527 527 eatNextIdentifier = false; 528 528 … … 537 537 break; 538 538 case Other: 539 if (token == '}' || token == ';') {539 if (token == '}' || token == ';') 540 540 delimited = true; 541 break; 542 case Identifier: 543 // Apply anonymous-function hack below (eat the identifier). 544 if (eatNextIdentifier) { 545 eatNextIdentifier = false; 546 token = lex(); 547 break; 541 548 } 549 kjsyylval.ident = makeIdentifier(m_buffer16); 550 token = IDENT; 542 551 break; 543 552 case IdentifierOrKeyword: 544 if ((token = Lookup::find(&mainTable, m_buffer16.data(), m_buffer16.size())) < 0) { 545 case Identifier: 546 // Lookup for keyword failed, means this is an identifier 547 // Apply anonymous-function hack below (eat the identifier) 548 if (eatNextIdentifier) { 549 eatNextIdentifier = false; 550 token = lex(); 551 break; 552 } 553 kjsyylval.ident = makeIdentifier(m_buffer16); 553 kjsyylval.ident = makeIdentifier(m_buffer16); 554 if ((token = mainTable.value(*kjsyylval.ident)) < 0) { 555 // Lookup for keyword failed, means this is an identifier. 554 556 token = IDENT; 555 557 break; 556 558 } 557 558 eatNextIdentifier = false; 559 // Hack for "f = function somename() { ... }", too hard to get into the grammar 560 if (token == FUNCTION && lastToken == '=' ) 561 eatNextIdentifier = true; 562 563 if (token == CONTINUE || token == BREAK || 564 token == RETURN || token == THROW) 559 // Hack for "f = function somename() { ... }"; too hard to get into the grammar. 560 eatNextIdentifier = token == FUNCTION && lastToken == '='; 561 if (token == CONTINUE || token == BREAK || token == RETURN || token == THROW) 565 562 restrKeyword = true; 566 563 break; -
trunk/JavaScriptCore/kjs/lookup.cpp
r30942 r31147 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 4 * Copyright (C) 2003, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 5 3 * 6 4 * This library is free software; you can redistribute it and/or … … 23 21 #include "lookup.h" 24 22 25 #include <wtf/Assertions.h>26 27 23 namespace KJS { 28 24 29 static inline bool keysMatch(const UChar* c, unsigned len, const char* s) 25 void HashTable::createTable() const 30 26 { 31 // FIXME: This can run off the end of |s| if |c| has a U+0000 character in it. 32 const char* end = s + len; 33 for (; s != end; c++, s++) 34 if (*c != *s) 35 return false; 36 return *s == 0; 37 } 38 39 static inline const HashEntry* findEntry(const struct HashTable* table, unsigned int hash, 40 const UChar* c, unsigned int len) 41 { 42 ASSERT(table->type == 3); 43 44 const HashEntry* e = &table->entries[hash & table->hashSizeMask]; 45 46 if (!e->s) 47 return 0; 48 49 do { 50 // compare strings 51 if (keysMatch(c, len, e->s)) 52 return e; 53 54 // try next bucket 55 e = e->next; 56 } while (e); 57 return 0; 58 } 59 60 const HashEntry* Lookup::findEntry(const struct HashTable* table, const Identifier& s) 61 { 62 return KJS::findEntry(table, s.ustring().rep()->computedHash(), s.data(), s.size()); 63 } 64 65 int Lookup::find(const struct HashTable *table, const UChar *c, unsigned int len) 66 { 67 const HashEntry *entry = KJS::findEntry(table, UString::Rep::computeHash(c, len), c, len); 68 if (entry) 69 return entry->value.intValue; 70 return -1; 71 } 72 73 int Lookup::find(const struct HashTable* table, const Identifier& s) 74 { 75 const HashEntry* entry = KJS::findEntry(table, s.ustring().rep()->computedHash(), s.data(), s.size()); 76 if (entry) 77 return entry->value.intValue; 78 return -1; 27 ASSERT(!table); 28 HashEntry* entries = new HashEntry[hashSizeMask + 1]; 29 for (int i = 0; i <= hashSizeMask; ++i) 30 entries[i].key = 0; 31 for (int i = 0; values[i].key; ++i) { 32 UString::Rep* identifier = Identifier::add(values[i].key).releaseRef(); 33 int hashIndex = identifier->computedHash() & hashSizeMask; 34 ASSERT(!entries[hashIndex].key); 35 entries[hashIndex].key = identifier; 36 entries[hashIndex].integerValue = values[i].value; 37 entries[hashIndex].attributes = values[i].attributes; 38 entries[hashIndex].length = values[i].length; 39 } 40 table = entries; 79 41 } 80 42 -
trunk/JavaScriptCore/kjs/lookup.h
r30534 r31147 2 2 /* 3 3 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 4 * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 33 33 namespace KJS { 34 34 35 /** 36 * An entry in a hash table. 37 */ 38 struct HashEntry { 39 /** 40 * s is the key (e.g. a property name) 41 */ 42 const char* s; 43 44 /** 45 * value is the result value (enum value for properties and a function pointer to a constructor factory for functions) 46 */ 47 union { 48 intptr_t intValue; 49 PrototypeFunction::JSMemberFunction functionValue; 50 } value; 51 52 /** 53 * attr is a set for flags (e.g. the property flags, see object.h) 54 */ 55 unsigned char attr; 56 /** 57 * params is another number. For property hashtables, it is used to 58 * denote the number of argument of the function 59 */ 60 short int params; 61 /** 62 * next is the pointer to the next entry for the same hash value 63 */ 64 const HashEntry* next; 65 }; 66 67 /** 68 * A hash table 69 * Usually the hashtable is generated by the create_hash_table script, from a .table file. 70 * 71 * The implementation uses an array of entries, "size" is the total size of that array. 72 * The entries between 0 and hashSize-1 are the entry points 73 * for each hash value, and the entries between hashSize and size-1 74 * are the overflow entries for the hash values that need one. 75 * The "next" pointer of the entry links entry points to overflow entries, 76 * and links overflow entries between them. 77 */ 78 struct HashTable { 79 /** 80 * type is a version number. Currently always 2 81 */ 82 int type; 83 /** 84 * size is the total number of entries in the hashtable, including the null entries, 85 * i.e. the size of the "entries" array. 86 * Used to iterate over all entries in the table 87 */ 88 int size; 89 /** 90 * pointer to the array of entries 91 * Mind that some entries in the array are null (0,0,0,0). 92 */ 93 const HashEntry* entries; 94 /** 95 * the maximum value for the hash minus 1. Always smaller than size. 96 */ 97 int hashSizeMask; 98 }; 99 100 /** 101 * @short Fast keyword lookup. 102 */ 103 class Lookup { 104 public: 105 /** 106 * Find an entry in the table, and return its value (i.e. the value field of HashEntry) 107 */ 108 static int find(const struct HashTable*, const Identifier&); 109 static int find(const struct HashTable*, const UChar*, unsigned int len); 110 111 /** 112 * Find an entry in the table, and return the entry 113 * This variant gives access to the other attributes of the entry, 114 * especially the attr field. 115 */ 116 static const HashEntry* findEntry(const struct HashTable*, const Identifier&); 117 118 }; 119 120 class ExecState; 121 class UString; 35 // Hash table generated by the create_hash_table script. 36 37 struct HashTableValue { 38 const char* key; // property name 39 intptr_t value; // integer or function 40 unsigned char attributes; // JSObject attributes 41 unsigned char length; // number of arguments for function 42 }; 43 44 struct HashEntry { 45 UString::Rep* key; 46 union { 47 intptr_t integerValue; 48 PrototypeFunction::JSMemberFunction functionValue; 49 }; 50 unsigned char attributes; // JSObject attributes 51 unsigned char length; // number of arguments for function 52 }; 53 54 struct HashTable { 55 int hashSizeMask; // Precomputed size for the hash table (minus 1). 56 const HashTableValue* values; // Fixed values generated by script. 57 mutable const HashEntry* table; // Table allocated at runtime. 58 59 // Find an entry in the table, and return the entry. 60 ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const 61 { 62 if (!table) 63 createTable(); 64 ASSERT(table); 65 const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & hashSizeMask]; 66 if (entry->key != identifier.ustring().rep()) 67 return 0; 68 return entry; 69 } 70 71 // Find an entry in the table, and return the value. 72 int value(const Identifier& identifier) const 73 { 74 const HashEntry* entry = this->entry(identifier); 75 return entry ? entry->integerValue : -1; 76 } 77 78 // Convert the hash table keys to identifiers. 79 void createTable() const; 80 }; 81 122 82 /** 123 83 * @internal … … 133 93 134 94 const HashEntry* entry = slot.staticEntry(); 135 JSValue* val = new PrototypeFunction(exec, entry-> params, propertyName, entry->value.functionValue);136 thisObj->putDirect(propertyName, val, entry->attr );95 JSValue* val = new PrototypeFunction(exec, entry->length, propertyName, entry->functionValue); 96 thisObj->putDirect(propertyName, val, entry->attributes); 137 97 return val; 138 98 } … … 147 107 ThisImp* thisObj = static_cast<ThisImp*>(slot.slotBase()); 148 108 const HashEntry* entry = slot.staticEntry(); 149 return thisObj->getValueProperty(exec, entry-> value.intValue);109 return thisObj->getValueProperty(exec, entry->integerValue); 150 110 } 151 111 … … 171 131 */ 172 132 template <class ThisImp, class ParentImp> 173 inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, 174 ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) 175 { 176 const HashEntry* entry = Lookup::findEntry(table, propertyName); 133 inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) 134 { 135 const HashEntry* entry = table->entry(propertyName); 177 136 178 137 if (!entry) // not found, forward to parent 179 138 return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot); 180 139 181 if (entry->attr & Function)140 if (entry->attributes & Function) 182 141 slot.setStaticEntry(thisObj, entry, staticFunctionGetter); 183 142 else … … 193 152 */ 194 153 template <class ParentImp> 195 inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, 196 JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot) 197 { 198 const HashEntry* entry = Lookup::findEntry(table, propertyName); 154 inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot) 155 { 156 const HashEntry* entry = table->entry(propertyName); 199 157 200 158 if (!entry) // not found, forward to parent 201 159 return static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot); 202 160 203 ASSERT(entry->attr & Function);161 ASSERT(entry->attributes & Function); 204 162 205 163 slot.setStaticEntry(thisObj, entry, staticFunctionGetter); … … 212 170 */ 213 171 template <class ThisImp, class ParentImp> 214 inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, 215 ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) 216 { 217 const HashEntry* entry = Lookup::findEntry(table, propertyName); 172 inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) 173 { 174 const HashEntry* entry = table->entry(propertyName); 218 175 219 176 if (!entry) // not found, forward to parent 220 177 return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot); 221 178 222 ASSERT(!(entry->attr & Function));179 ASSERT(!(entry->attributes & Function)); 223 180 224 181 slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>); … … 232 189 */ 233 190 template <class ThisImp> 234 inline bool lookupPut(ExecState* exec, const Identifier& propertyName, 235 JSValue* value, const HashTable* table, ThisImp* thisObj) 236 { 237 const HashEntry* entry = Lookup::findEntry(table, propertyName); 191 inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue* value, const HashTable* table, ThisImp* thisObj) 192 { 193 const HashEntry* entry = table->entry(propertyName); 238 194 239 195 if (!entry) 240 196 return false; 241 197 242 if (entry->attr & Function) // function: put as override property198 if (entry->attributes & Function) // function: put as override property 243 199 thisObj->putDirect(propertyName, value); 244 else if (!(entry->attr & ReadOnly))245 thisObj->putValueProperty(exec, entry-> value.intValue, value);200 else if (!(entry->attributes & ReadOnly)) 201 thisObj->putValueProperty(exec, entry->integerValue, value); 246 202 247 203 return true; … … 255 211 */ 256 212 template <class ThisImp, class ParentImp> 257 inline void lookupPut(ExecState* exec, const Identifier& propertyName, 258 JSValue* value, const HashTable* table, ThisImp* thisObj) 213 inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue* value, const HashTable* table, ThisImp* thisObj) 259 214 { 260 215 if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj)) -
trunk/JavaScriptCore/kjs/object.cpp
r31145 r31147 315 315 // Look in the static hashtable of properties 316 316 const HashEntry* entry = findPropertyHashEntry(propertyName); 317 if (entry && entry->attr & DontDelete)317 if (entry && entry->attributes & DontDelete) 318 318 return false; // this builtin property can't be deleted 319 // FIXME: Should the code here actually do some deletion? 319 320 return true; 320 321 } … … 378 379 const HashEntry* JSObject::findPropertyHashEntry(const Identifier& propertyName) const 379 380 { 380 for (const ClassInfo *info = classInfo(); info; info = info->parentClass) {381 if (const HashTable *propHashTable = info->propHashTable) {382 if (const HashEntry *e = Lookup::findEntry(propHashTable,propertyName))383 return e;384 }385 }386 return 0;381 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) { 382 if (const HashTable* propHashTable = info->propHashTable) { 383 if (const HashEntry* e = propHashTable->entry(propertyName)) 384 return e; 385 } 386 } 387 return 0; 387 388 } 388 389 … … 488 489 const HashEntry* e = findPropertyHashEntry(propertyName); 489 490 if (e) { 490 attributes = e->attr ;491 attributes = e->attributes; 491 492 return true; 492 493 } … … 497 498 void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) 498 499 { 499 _prop.getEnumerablePropertyNames(propertyNames); 500 501 // Add properties from the static hashtable of properties 502 const ClassInfo *info = classInfo(); 503 while (info) { 504 if (info->propHashTable) { 505 int size = info->propHashTable->size; 506 const HashEntry *e = info->propHashTable->entries; 507 for (int i = 0; i < size; ++i, ++e) { 508 if (e->s && !(e->attr & DontEnum)) 509 propertyNames.add(e->s); 510 } 511 } 512 info = info->parentClass; 513 } 514 if (_proto->isObject()) 515 static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames); 500 _prop.getEnumerablePropertyNames(propertyNames); 501 502 // Add properties from the static hashtables of properties 503 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) { 504 const HashTable* table = info->propHashTable; 505 if (!table) 506 continue; 507 if (!table->table) 508 table->createTable(); 509 ASSERT(table->table); 510 int hashSizeMask = table->hashSizeMask; 511 const HashEntry* e = table->table; 512 for (int i = 0; i <= hashSizeMask; ++i, ++e) { 513 if (e->key && !(e->attributes & DontEnum)) 514 propertyNames.add(Identifier(e->key)); 515 } 516 } 517 518 if (_proto->isObject()) 519 static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames); 516 520 } 517 521
Note:
See TracChangeset
for help on using the changeset viewer.