Changeset 27126 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Oct 26, 2007, 3:43:03 PM (18 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/function.cpp
r27100 r27126 391 391 const ClassInfo ActivationImp::info = {"Activation", 0, 0, 0}; 392 392 393 // ECMA 10.1.6394 393 ActivationImp::ActivationImp(FunctionImp* function, const List& arguments) 395 : _function(function), _arguments(arguments), _argumentsObject(0)396 { 397 // FIXME: Do we need to support enumerating the arguments property? 394 : d(new ActivationImpPrivate(function, arguments)) 395 , symbolTable(&function->body->symbolTable()) 396 { 398 397 } 399 398 … … 401 400 { 402 401 ActivationImp* thisObj = static_cast<ActivationImp*>(slot.slotBase()); 403 404 // default: return builtin arguments array405 if (! thisObj->_argumentsObject)402 ActivationImpPrivate* d = thisObj->d.get(); 403 404 if (!d->argumentsObject) 406 405 thisObj->createArgumentsObject(exec); 407 406 408 return thisObj->_argumentsObject;407 return d->argumentsObject; 409 408 } 410 409 … … 416 415 bool ActivationImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) 417 416 { 418 // do this first so property map arguments property wins over the below 419 // we don't call JSObject because we won't have getter/setter properties 420 // and we don't want to support __proto__ 417 // We don't call through to JSObject because there's no way to give an 418 // acitvation object getter/setter properties, and exposing __proto__ in 419 // the scope chain would be bizarre. 420 ASSERT(!_prop.hasGetterSetterProperties()); 421 422 size_t index; 423 if (symbolTable->get(propertyName, index)) { 424 slot.setValueSlot(this, &d->localStorage[index].value); 425 return true; 426 } 421 427 422 428 if (JSValue** location = getDirectLocation(propertyName)) { … … 425 431 } 426 432 433 // Only return the built-in arguments object if it wasn't overridden above. 427 434 if (propertyName == exec->propertyNames().arguments) { 428 435 slot.setCustom(this, getArgumentsGetter()); … … 437 444 if (propertyName == exec->propertyNames().arguments) 438 445 return false; 446 447 size_t index; 448 if (symbolTable->get(propertyName, index)) 449 return false; 450 439 451 return JSObject::deleteProperty(exec, propertyName); 440 452 } … … 442 454 void ActivationImp::put(ExecState*, const Identifier& propertyName, JSValue* value, int attr) 443 455 { 444 // There's no way that an activation object can have a prototype or getter/setter properties 456 // There's no way that an activation object can have a prototype or getter/setter properties. 445 457 ASSERT(!_prop.hasGetterSetterProperties()); 446 458 ASSERT(prototype() == jsNull()); 447 459 460 size_t index; 461 if (symbolTable->get(propertyName, index)) { 462 LocalStorageEntry& entry = d->localStorage[index]; 463 entry.value = value; 464 entry.attributes = attr; 465 return; 466 } 467 448 468 _prop.put(propertyName, value, attr, (attr == None || attr == DontDelete)); 449 469 } … … 451 471 void ActivationImp::mark() 452 472 { 453 if (_function && !_function->marked())454 _function->mark();455 if (_argumentsObject && !_argumentsObject->marked())456 _argumentsObject->mark();457 473 JSObject::mark(); 474 475 if (!d->function->marked()) 476 d->function->mark(); 477 478 size_t size = d->localStorage.size(); 479 for (size_t i = 0; i < size; ++i) { 480 JSValue* value = d->localStorage[i].value; 481 if (!value->marked()) 482 value->mark(); 483 } 484 485 if (d->argumentsObject && !d->argumentsObject->marked()) 486 d->argumentsObject->mark(); 458 487 } 459 488 460 489 void ActivationImp::createArgumentsObject(ExecState* exec) 461 490 { 462 _argumentsObject = new Arguments(exec, _function, _arguments, const_cast<ActivationImp*>(this)); 463 // The arguments list is only needed to create the arguments object, so discard it now 464 _arguments.reset(); 491 d->argumentsObject = new Arguments(exec, d->function, d->arguments, this); 492 493 // The arguments list is only needed to create the arguments object, so discard it now. 494 // This prevents lists of Lists from building up, waiting to be garbage collected. 495 d->arguments.reset(); 465 496 } 466 497 -
trunk/JavaScriptCore/kjs/function.h
r27097 r27126 25 25 #define KJS_FUNCTION_H 26 26 27 #include "SymbolTable.h" 27 28 #include "object.h" 28 29 #include <wtf/OwnPtr.h> … … 138 139 class ActivationImp : public JSObject { 139 140 public: 140 ActivationImp(FunctionImp* function, const List& arguments); 141 struct LocalStorageEntry { 142 LocalStorageEntry() 143 { 144 } 145 146 LocalStorageEntry(JSValue* v, int a) 147 : value(v) 148 , attributes(a) 149 { 150 } 151 152 JSValue* value; 153 int attributes; 154 }; 155 156 typedef Vector<LocalStorageEntry, 32> LocalStorage; 157 158 private: 159 struct ActivationImpPrivate { 160 ActivationImpPrivate(FunctionImp* f, const List& a) 161 : function(f) 162 , arguments(a) 163 , argumentsObject(0) 164 { 165 ASSERT(f); 166 } 167 168 FunctionImp* function; 169 LocalStorage localStorage; 170 171 List arguments; 172 Arguments* argumentsObject; 173 }; 174 175 public: 176 ActivationImp::ActivationImp(FunctionImp* function, const List& arguments); 141 177 142 178 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); … … 151 187 bool isActivation() { return true; } 152 188 153 void releaseArguments() { _arguments.reset(); } 189 void releaseArguments() { d->arguments.reset(); } 190 191 LocalStorage& localStorage() { return d->localStorage; }; 154 192 155 193 private: … … 157 195 static JSValue* argumentsGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot); 158 196 void createArgumentsObject(ExecState*); 159 160 FunctionImp* _function; 161 List _arguments; 162 mutable Arguments* _argumentsObject; 197 198 OwnPtr<ActivationImpPrivate> d; 199 SymbolTable* symbolTable; 163 200 }; 164 201 -
trunk/JavaScriptCore/kjs/nodes.cpp
r27100 r27126 1835 1835 flags |= ReadOnly; 1836 1836 1837 ASSERT(variableObject-> getDirect(ident) || ident == exec->propertyNames().arguments);1837 ASSERT(variableObject->hasProperty(exec, ident)); 1838 1838 variableObject->put(exec, ident, val, flags); 1839 1839 } … … 2579 2579 , m_sourceId(Parser::sid) 2580 2580 , m_initializedDeclarationStacks(false) 2581 , m_initializedSymbolTable(false) 2581 2582 { 2582 2583 setLoc(-1, -1); … … 2607 2608 } 2608 2609 2609 void FunctionBodyNode:: processDeclarationsFunctionCode(ExecState* exec)2610 void FunctionBodyNode::initializesymbolTable() 2610 2611 { 2611 2612 size_t i, size; 2612 2613 JSObject* variableObject = exec->variableObject(); 2614 2613 size_t count = 0; 2614 2615 // The order of additions here implicitly enforces the mutual exclusion described in ECMA 10.1.3. 2616 for (i = 0, size = m_varStack.size(); i < size; ++i) 2617 m_symbolTable.set(m_varStack[i]->ident, count++); 2618 2619 for (i = 0, size = m_parameters.size(); i < size; ++i) 2620 m_symbolTable.set(m_parameters[i], count++); 2621 2622 for (i = 0, size = m_functionStack.size(); i < size; ++i) 2623 m_symbolTable.set(m_functionStack[i]->ident, count++); 2624 2625 m_initializedSymbolTable = true; 2626 } 2627 2628 void FunctionBodyNode::processDeclarations(ExecState* exec) 2629 { 2630 if (!m_initializedDeclarationStacks) 2631 initializeDeclarationStacks(exec); 2632 2633 if (exec->codeType() == FunctionCode) 2634 processDeclarationsForFunctionCode(exec); 2635 else 2636 processDeclarationsForProgramCode(exec); 2637 } 2638 2639 void FunctionBodyNode::processDeclarationsForFunctionCode(ExecState* exec) 2640 { 2641 if (!m_initializedSymbolTable) 2642 initializesymbolTable(); 2643 2644 ASSERT(exec->variableObject()->isActivation()); 2645 ActivationImp::LocalStorage& localStorage = static_cast<ActivationImp*>(exec->variableObject())->localStorage(); 2646 localStorage.reserveCapacity(m_varStack.size() + m_parameters.size() + m_functionStack.size()); 2647 2615 2648 int minAttributes = Internal | DontDelete; 2616 2617 // The order of additions to the variable object here implicitly enforces the mutual exclusion described in ECMA 10.1.3. 2649 2650 size_t i, size; 2651 2652 // NOTE: Must match the order of addition in initializesymbolTable(). 2653 2618 2654 for (i = 0, size = m_varStack.size(); i < size; ++i) { 2619 2655 VarDeclNode* node = m_varStack[i]; … … 2621 2657 if (node->varType == VarDeclNode::Constant) 2622 2658 attributes |= ReadOnly; 2623 variableObject->put(exec, node->ident, jsUndefined(), attributes);2659 localStorage.append(ActivationImp::LocalStorageEntry(jsUndefined(), attributes)); 2624 2660 } 2625 2661 2626 2662 const List& args = *exec->arguments(); 2627 2663 for (i = 0, size = m_parameters.size(); i < size; ++i) 2628 variableObject->put(exec, m_parameters[i], args[i], DontDelete);2664 localStorage.append(ActivationImp::LocalStorageEntry(args[i], DontDelete)); 2629 2665 2630 2666 for (i = 0, size = m_functionStack.size(); i < size; ++i) { 2631 2667 FuncDeclNode* node = m_functionStack[i]; 2632 variableObject->put(exec, node->ident, node->makeFunction(exec), minAttributes);2668 localStorage.append(ActivationImp::LocalStorageEntry(node->makeFunction(exec), minAttributes)); 2633 2669 } 2634 2670 } 2635 2671 2636 void FunctionBodyNode::processDeclarations ProgramCode(ExecState* exec)2672 void FunctionBodyNode::processDeclarationsForProgramCode(ExecState* exec) 2637 2673 { 2638 2674 size_t i, size; … … 2678 2714 } 2679 2715 2680 void FunctionBodyNode::processDeclarations(ExecState* exec)2681 {2682 if (!m_initializedDeclarationStacks)2683 initializeDeclarationStacks(exec);2684 2685 if (exec->codeType() == FunctionCode)2686 processDeclarationsFunctionCode(exec);2687 else2688 processDeclarationsProgramCode(exec);2689 }2690 2691 2716 Completion FunctionBodyNode::execute(ExecState* exec) 2692 2717 { -
trunk/JavaScriptCore/kjs/nodes.h
r27028 r27126 1235 1235 1236 1236 virtual Completion execute(ExecState*) KJS_FAST_CALL; 1237 1238 SymbolTable& symbolTable() { return m_symbolTable; } 1237 1239 1238 1240 void addParam(const Identifier& ident) KJS_FAST_CALL; … … 1242 1244 Vector<Identifier>& parameters() KJS_FAST_CALL { return m_parameters; } 1243 1245 ALWAYS_INLINE void processDeclarations(ExecState*); 1244 ALWAYS_INLINE void processDeclarationsF unctionCode(ExecState*);1245 ALWAYS_INLINE void processDeclarations ProgramCode(ExecState*);1246 ALWAYS_INLINE void processDeclarationsForFunctionCode(ExecState*); 1247 ALWAYS_INLINE void processDeclarationsForProgramCode(ExecState*); 1246 1248 private: 1247 1249 UString m_sourceURL; … … 1251 1253 bool m_initializedDeclarationStacks; 1252 1254 1253 // Properties that will go into the ActivationImp's symbol table. (Used for initializing the ActivationImp.) 1254 DeclarationStacks::VarStack m_varStack; 1255 DeclarationStacks::FunctionStack m_functionStack; 1256 Vector<Identifier> m_parameters; 1255 void initializesymbolTable(); 1256 bool m_initializedSymbolTable; 1257 1258 // Properties that will go into the ActivationImp's local storage. (Used for initializing the ActivationImp.) 1259 DeclarationStacks::VarStack m_varStack; 1260 DeclarationStacks::FunctionStack m_functionStack; 1261 Vector<Identifier> m_parameters; 1262 1263 // Mapping from property name -> local storage index. (Used once to transform the AST, and subsequently for residual slow case lookups.) 1264 SymbolTable m_symbolTable; 1257 1265 }; 1258 1266
Note:
See TracChangeset
for help on using the changeset viewer.