Changeset 29425 in webkit
- Timestamp:
- Jan 11, 2008, 6:08:50 PM (17 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r29402 r29425 1 2008-01-11 Cameron Zwarich <cwzwarich@uwaterloo.ca> 2 3 Reviewed by Maciej. 4 5 Optimized ActivationImp allocation, so that activation records are now 6 first allocated on an explicitly managed stack and only heap allocated 7 when necessary. Roughly a 5% improvement on SunSpider, and a larger 8 improvement on benchmarks that use more function calls. 9 10 * JavaScriptCore.xcodeproj/project.pbxproj: 11 * kjs/Activation.h: Added. 12 (KJS::ActivationImp::ActivationData::ActivationData): 13 (KJS::ActivationImp::ActivationImp): 14 (KJS::ActivationImp::classInfo): 15 (KJS::ActivationImp::isActivationObject): 16 (KJS::ActivationImp::isOnStack): 17 (KJS::ActivationImp::d): 18 (KJS::StackActivation::StackActivation): 19 * kjs/ExecState.cpp: 20 (KJS::ExecState::ExecState): 21 (KJS::ExecState::~ExecState): 22 * kjs/ExecState.h: 23 (KJS::ExecState::replaceScopeChainTop): 24 (KJS::ExecState::setActivationObject): 25 (KJS::ExecState::setLocalStorage): 26 * kjs/JSGlobalObject.cpp: 27 (KJS::JSGlobalObject::reset): 28 (KJS::JSGlobalObject::pushActivation): 29 (KJS::JSGlobalObject::checkActivationCount): 30 (KJS::JSGlobalObject::popActivationHelper): 31 (KJS::JSGlobalObject::popActivation): 32 (KJS::JSGlobalObject::tearOffActivation): 33 * kjs/JSGlobalObject.h: 34 * kjs/JSVariableObject.h: 35 (KJS::JSVariableObject::JSVariableObjectData::JSVariableObjectData): 36 (KJS::JSVariableObject::JSVariableObject): 37 * kjs/function.cpp: 38 (KJS::FunctionImp::argumentsGetter): 39 (KJS::ActivationImp::ActivationImp): 40 (KJS::ActivationImp::~ActivationImp): 41 (KJS::ActivationImp::init): 42 (KJS::ActivationImp::getOwnPropertySlot): 43 (KJS::ActivationImp::markHelper): 44 (KJS::ActivationImp::mark): 45 (KJS::ActivationImp::ActivationData::ActivationData): 46 (KJS::GlobalFuncImp::callAsFunction): 47 * kjs/function.h: 48 * kjs/nodes.cpp: 49 (KJS::PostIncResolveNode::evaluate): 50 (KJS::PostDecResolveNode::evaluate): 51 (KJS::PreIncResolveNode::evaluate): 52 (KJS::PreDecResolveNode::evaluate): 53 (KJS::ReadModifyResolveNode::evaluate): 54 (KJS::AssignResolveNode::evaluate): 55 (KJS::WithNode::execute): 56 (KJS::TryNode::execute): 57 (KJS::FunctionBodyNode::processDeclarations): 58 (KJS::FuncExprNode::evaluate): 59 * kjs/object.h: 60 * kjs/scope_chain.h: 61 (KJS::ScopeChain::replace): 62 * kjs/scope_chain_mark.h: Added. 63 (KJS::ScopeChain::mark): 64 1 65 2008-01-11 Simon Hausmann <hausmann@webkit.org> 2 66 -
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r29381 r29425 532 532 70B16A260569A10900DB756D /* runtime_object.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = runtime_object.cpp; path = bindings/runtime_object.cpp; sourceTree = "<group>"; tabWidth = 8; }; 533 533 70B16A270569A10900DB756D /* runtime_object.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = runtime_object.h; path = bindings/runtime_object.h; sourceTree = "<group>"; tabWidth = 8; }; 534 7E2C6C950D31C6AB002D44E2 /* Activation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Activation.h; path = kjs/Activation.h; sourceTree = "<group>"; }; 535 7E2C6C980D31C6B6002D44E2 /* scope_chain_mark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scope_chain_mark.h; path = kjs/scope_chain_mark.h; sourceTree = "<group>"; }; 534 536 84ABF1DE070B628C00A3AC05 /* npruntime_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = npruntime_impl.h; path = bindings/npruntime_impl.h; sourceTree = "<group>"; tabWidth = 8; }; 535 537 9303F567099118FA00AD71B8 /* OwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtr.h; sourceTree = "<group>"; }; … … 689 691 isa = PBXGroup; 690 692 children = ( 693 7E2C6C980D31C6B6002D44E2 /* scope_chain_mark.h */, 694 7E2C6C950D31C6AB002D44E2 /* Activation.h */, 691 695 937B63CC09E766D200A671DD /* DerivedSources.make */, 692 696 14B8ECA60A5653980062BE54 /* JavaScriptCore.exp */, -
trunk/JavaScriptCore/kjs/ExecState.cpp
r29067 r29425 26 26 #include "ExecState.h" 27 27 28 #include "Activation.h" 28 29 #include "JSGlobalObject.h" 29 30 #include "function.h" 30 31 #include "internal.h" 32 #include "scope_chain_mark.h" 31 33 32 34 namespace KJS { … … 106 108 , m_codeType(FunctionCode) 107 109 { 108 ActivationImp* activation = new ActivationImp(this);110 ActivationImp* activation = globalObject->pushActivation(this); 109 111 m_activation = activation; 110 112 m_localStorage = &activation->localStorage(); … … 116 118 ExecState::~ExecState() 117 119 { 120 if (m_codeType == FunctionCode && m_activation->needsPop()) 121 m_globalObject->popActivation(); 122 118 123 m_globalObject->setCurrentExec(m_savedExec); 119 124 } -
trunk/JavaScriptCore/kjs/ExecState.h
r29067 r29425 78 78 79 79 const ScopeChain& scopeChain() const { return m_scopeChain; } 80 void replaceScopeChainTop(JSObject* o) { m_scopeChain.replaceTop(o); } 80 81 81 82 JSVariableObject* variableObject() const { return m_variableObject; } … … 88 89 89 90 ActivationImp* activationObject() { return m_activation; } 91 void setActivationObject(ActivationImp* a) { m_activation = a; } 90 92 CodeType codeType() { return m_codeType; } 91 93 ScopeNode* scopeNode() { return m_scopeNode; } … … 113 115 114 116 LocalStorage& localStorage() { return *m_localStorage; } 117 void setLocalStorage(LocalStorage* s) { m_localStorage = s; } 115 118 116 119 // These are only valid right after calling execute(). -
trunk/JavaScriptCore/kjs/JSGlobalObject.cpp
r29091 r29425 1 1 /* 2 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca) 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 30 31 #include "JSGlobalObject.h" 31 32 32 #include " SavedBuiltins.h"33 #include "Activation.h" 33 34 #include "array_object.h" 34 35 #include "bool_object.h" … … 41 42 #include "object_object.h" 42 43 #include "regexp_object.h" 44 #include "SavedBuiltins.h" 43 45 #include "string_object.h" 44 46 … … 201 203 ExecState* exec = &d()->globalExec; 202 204 205 d()->activations = new ActivationStackNode; 206 d()->activationCount = 0; 207 203 208 // Prototypes 204 209 d()->functionPrototype = new FunctionPrototype(exec); … … 495 500 } 496 501 502 ActivationImp* JSGlobalObject::pushActivation(ExecState* exec) 503 { 504 if (d()->activationCount == activationStackNodeSize) { 505 ActivationStackNode* newNode = new ActivationStackNode; 506 newNode->prev = d()->activations; 507 d()->activations = newNode; 508 d()->activationCount = 0; 509 } 510 511 StackActivation* stackEntry = &d()->activations->data[d()->activationCount++]; 512 stackEntry->activationStorage.init(exec); 513 514 return &(stackEntry->activationStorage); 515 } 516 517 inline void JSGlobalObject::checkActivationCount() 518 { 519 if (!d()->activationCount) { 520 ActivationStackNode* prev = d()->activations->prev; 521 delete d()->activations; 522 d()->activations = prev; 523 d()->activationCount = activationStackNodeSize; 524 } 525 } 526 527 void JSGlobalObject::popActivation() 528 { 529 checkActivationCount(); 530 d()->activations->data[--d()->activationCount].activationDataStorage.localStorage.shrink(0); 531 } 532 533 void JSGlobalObject::tearOffActivation(ExecState* exec, bool leaveRelic) 534 { 535 if (exec->codeType() == FunctionCode && static_cast<ActivationImp*>(exec->activationObject())->isOnStack()) { 536 ActivationImp* oldActivation = static_cast<ActivationImp*>(exec->activationObject()); 537 ActivationImp* newActivation = new ActivationImp(*oldActivation->d(), leaveRelic); 538 539 if (!leaveRelic) { 540 checkActivationCount(); 541 d()->activationCount--; 542 } 543 544 oldActivation->d()->localStorage.shrink(0); 545 546 exec->setActivationObject(newActivation); 547 exec->setVariableObject(newActivation); 548 exec->setLocalStorage(&(newActivation->localStorage())); 549 exec->replaceScopeChainTop(newActivation); 550 } 551 } 552 497 553 } // namespace KJS -
trunk/JavaScriptCore/kjs/JSGlobalObject.h
r28884 r29425 28 28 namespace KJS { 29 29 30 class ActivationImp; 31 class ActivationStackNode; 30 32 class ArrayObjectImp; 31 33 class ArrayPrototype; … … 129 131 130 132 SymbolTable inlineSymbolTable; 133 134 ActivationStackNode* activations; 135 size_t activationCount; 131 136 }; 132 137 … … 228 233 virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; } 229 234 235 ActivationImp* pushActivation(ExecState*); 236 void popActivation(); 237 void tearOffActivation(ExecState*, bool markAsRelic = false); 238 230 239 private: 231 240 void init(); … … 236 245 void resetTimeoutCheck(); 237 246 247 void checkActivationCount(); 248 238 249 static JSGlobalObject* s_head; 239 250 }; -
trunk/JavaScriptCore/kjs/JSVariableObject.h
r28884 r29425 57 57 // size of a JSCell). 58 58 struct JSVariableObjectData { 59 JSVariableObjectData() { } 60 59 61 JSVariableObjectData(SymbolTable* s) 60 62 : symbolTable(s) // Subclass owns this pointer. … … 66 68 67 69 }; 70 71 JSVariableObject() { } 68 72 69 73 JSVariableObject(JSVariableObjectData* data) -
trunk/JavaScriptCore/kjs/function.cpp
r29067 r29425 27 27 #include "function.h" 28 28 29 #include "Activation.h" 29 30 #include "ExecState.h" 30 31 #include "JSGlobalObject.h" … … 85 86 { 86 87 FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase()); 87 ExecState* e = exec; 88 while (e) { 89 if (e->function() == thisObj) 88 89 for (ExecState* e = exec; e; e = e->callingExecState()) 90 if (e->function() == thisObj) { 91 e->dynamicGlobalObject()->tearOffActivation(e, e == exec); 90 92 return e->activationObject()->get(exec, propertyName); 91 e = e->callingExecState();92 }93 } 94 93 95 return jsNull(); 94 96 } … … 341 343 const ClassInfo ActivationImp::info = { "Activation", 0, 0 }; 342 344 345 ActivationImp::ActivationImp(const ActivationData& oldData, bool leaveRelic) 346 { 347 JSVariableObject::d = new ActivationData(oldData); 348 d()->leftRelic = leaveRelic; 349 } 350 351 ActivationImp::~ActivationImp() 352 { 353 if (!d()->isOnStack) 354 delete d(); 355 } 356 357 void ActivationImp::init(ExecState* exec) 358 { 359 d()->symbolTable = &exec->function()->body->symbolTable(); 360 d()->exec = exec; 361 d()->function = exec->function(); 362 d()->argumentsObject = 0; 363 } 364 343 365 JSValue* ActivationImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot) 344 366 { … … 368 390 // Only return the built-in arguments object if it wasn't overridden above. 369 391 if (propertyName == exec->propertyNames().arguments) { 392 for (ExecState* e = exec; e; e = e->callingExecState()) 393 if (e->function() == d()->function) { 394 e->dynamicGlobalObject()->tearOffActivation(e, e == exec); 395 ActivationImp* newActivation = e->activationObject(); 396 slot.setCustom(newActivation, newActivation->getArgumentsGetter()); 397 return true; 398 } 399 370 400 slot.setCustom(this, getArgumentsGetter()); 371 401 return true; … … 399 429 } 400 430 401 void ActivationImp::mark() 402 { 403 JSVariableObject::mark(); 431 void ActivationImp::markChildren() 432 { 433 LocalStorage& localStorage = d()->localStorage; 434 size_t size = localStorage.size(); 435 436 for (size_t i = 0; i < size; ++i) { 437 JSValue* value = localStorage[i].value; 438 439 if (!value->marked()) 440 value->mark(); 441 } 404 442 405 443 if (!d()->function->marked()) 406 444 d()->function->mark(); 407 445 408 446 if (d()->argumentsObject && !d()->argumentsObject->marked()) 409 d()->argumentsObject->mark(); 447 d()->argumentsObject->mark(); 448 } 449 450 void ActivationImp::mark() 451 { 452 JSObject::mark(); 453 markChildren(); 410 454 } 411 455 … … 416 460 // call instead of storing the list ourselves. 417 461 d()->argumentsObject = new Arguments(exec, d()->exec->function(), *d()->exec->arguments(), this); 462 } 463 464 ActivationImp::ActivationData::ActivationData(const ActivationData& old) 465 : JSVariableObjectData(old) 466 , exec(old.exec) 467 , function(old.function) 468 , argumentsObject(old.argumentsObject) 469 , isOnStack(false) 470 { 418 471 } 419 472 … … 697 750 698 751 // enter a new execution context 752 if (!switchGlobal) 753 exec->dynamicGlobalObject()->tearOffActivation(exec); 754 699 755 JSGlobalObject* globalObject = switchGlobal ? static_cast<JSGlobalObject*>(thisObj) : exec->dynamicGlobalObject(); 700 756 ExecState newExec(globalObject, evalNode.get(), exec); -
trunk/JavaScriptCore/kjs/function.h
r28907 r29425 37 37 class FunctionBodyNode; 38 38 class FunctionPrototype; 39 class JSGlobalObject; 39 40 40 41 class InternalFunctionImp : public JSObject { … … 138 139 }; 139 140 140 class ActivationImp : public JSVariableObject {141 private:142 using JSVariableObject::JSVariableObjectData;143 144 struct ActivationImpData : public JSVariableObjectData {145 ActivationImpData(ExecState* e)146 : JSVariableObjectData(&e->function()->body->symbolTable())147 , exec(e)148 , function(e->function()) // Store this pointer for marking, to keep our symbol table / scope alive after exec has gone out of scope.149 , argumentsObject(0)150 {151 }152 153 ExecState* exec;154 FunctionImp* function;155 Arguments* argumentsObject;156 };157 158 public:159 ActivationImp(ExecState* exec)160 : JSVariableObject(new ActivationImpData(exec))161 {162 }163 164 virtual ~ActivationImp()165 {166 delete d();167 }168 169 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);170 virtual void put(ExecState*, const Identifier& propertyName, JSValue* value, int attr = None);171 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);172 173 virtual const ClassInfo* classInfo() const { return &info; }174 static const ClassInfo info;175 176 virtual void mark();177 178 virtual bool isActivationObject() { return true; }179 180 private:181 static PropertySlot::GetValueFunc getArgumentsGetter();182 static JSValue* argumentsGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot);183 void createArgumentsObject(ExecState*);184 ActivationImpData* d() { return static_cast<ActivationImpData*>(JSVariableObject::d); }185 };186 187 141 class GlobalFuncImp : public InternalFunctionImp { 188 142 public: -
trunk/JavaScriptCore/kjs/nodes.cpp
r29109 r29425 1282 1282 1283 1283 PropertySlot slot; 1284 JSObject *base;1285 1284 do { 1286 base = *iter; 1287 if (base->getPropertySlot(exec, m_ident, slot)) { 1285 if ((*iter)->getPropertySlot(exec, m_ident, slot)) { 1286 // See the comment in PostIncResolveNode::evaluate(). 1287 1288 JSObject* base = *iter; 1288 1289 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec); 1289 1290 base->put(exec, m_ident, jsNumber(v->toNumber(exec) + 1)); … … 1339 1340 1340 1341 PropertySlot slot; 1341 JSObject *base;1342 1342 do { 1343 base = *iter; 1344 if (base->getPropertySlot(exec, m_ident, slot)) { 1343 if ((*iter)->getPropertySlot(exec, m_ident, slot)) { 1344 // See the comment in PostIncResolveNode::evaluate(). 1345 1346 JSObject* base = *iter; 1345 1347 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec); 1346 1348 base->put(exec, m_ident, jsNumber(v->toNumber(exec) - 1)); … … 1752 1754 1753 1755 PropertySlot slot; 1754 JSObject *base;1755 1756 do { 1756 base = *iter; 1757 if (base->getPropertySlot(exec, m_ident, slot)) { 1757 if ((*iter)->getPropertySlot(exec, m_ident, slot)) { 1758 // See the comment in PostIncResolveNode::evaluate(). 1759 1760 JSObject* base = *iter; 1758 1761 JSValue *v = slot.getValue(exec, base, m_ident); 1759 1762 … … 1799 1802 1800 1803 PropertySlot slot; 1801 JSObject *base;1802 1804 do { 1803 base = *iter; 1804 if (base->getPropertySlot(exec, m_ident, slot)) { 1805 if ((*iter)->getPropertySlot(exec, m_ident, slot)) { 1806 // See the comment in PostIncResolveNode::evaluate(). 1807 1808 JSObject* base = *iter; 1805 1809 JSValue *v = slot.getValue(exec, base, m_ident); 1806 1810 … … 3229 3233 do { 3230 3234 base = *iter; 3231 if (base->getPropertySlot(exec, m_ident, slot)) 3235 if (base->getPropertySlot(exec, m_ident, slot)) { 3236 // See the comment in PostIncResolveNode::evaluate(). 3237 3238 base = *iter; 3232 3239 goto found; 3240 } 3233 3241 3234 3242 ++iter; … … 3266 3274 do { 3267 3275 base = *iter; 3268 if (base->getPropertySlot(exec, m_ident, slot)) 3276 if (base->getPropertySlot(exec, m_ident, slot)) { 3277 // See the comment in PostIncResolveNode::evaluate(). 3278 3279 base = *iter; 3269 3280 goto found; 3281 } 3270 3282 3271 3283 ++iter; … … 3998 4010 JSObject *o = v->toObject(exec); 3999 4011 KJS_CHECKEXCEPTION 4012 exec->dynamicGlobalObject()->tearOffActivation(exec); 4000 4013 exec->pushScope(o); 4001 4014 JSValue* value = statement->execute(exec); … … 4196 4209 JSObject* obj = new JSObject; 4197 4210 obj->put(exec, exceptionIdent, result, DontDelete); 4211 exec->dynamicGlobalObject()->tearOffActivation(exec); 4198 4212 exec->pushScope(obj); 4199 4213 result = catchBlock->execute(exec); … … 4358 4372 } 4359 4373 4374 if (m_functionStack.size() != 0) 4375 exec->dynamicGlobalObject()->tearOffActivation(exec); 4376 4360 4377 LocalStorage& localStorage = exec->variableObject()->localStorage(); 4361 4378 … … 4570 4587 JSValue *FuncExprNode::evaluate(ExecState *exec) 4571 4588 { 4589 exec->dynamicGlobalObject()->tearOffActivation(exec); 4590 4572 4591 bool named = !ident.isNull(); 4573 4592 JSObject *functionScopeObject = 0; -
trunk/JavaScriptCore/kjs/object.h
r29068 r29425 581 581 } 582 582 583 584 // FIXME: Put this function in a separate file named something like scope_chain_mark.h -- can't put it in scope_chain.h since it depends on JSObject.585 586 inline void ScopeChain::mark()587 {588 for (ScopeChainNode *n = _node; n; n = n->next) {589 JSObject *o = n->object;590 if (!o->marked())591 o->mark();592 }593 }594 595 583 inline void ScopeChain::release() 596 584 { -
trunk/JavaScriptCore/kjs/scope_chain.h
r29068 r29425 81 81 void push(JSObject *); 82 82 void push(const ScopeChain &); 83 void replaceTop(JSObject*); 83 84 void pop(); 84 85 … … 130 131 } 131 132 133 inline void ScopeChain::replaceTop(JSObject* o) 134 { 135 ASSERT(o); 136 _node->object = o; 137 } 138 132 139 inline void ScopeChain::pop() 133 140 { -
trunk/LayoutTests/ChangeLog
r29424 r29425 1 2008-01-11 Cameron Zwarich <cwzwarich@uwaterloo.ca> 2 3 Reviewed by Maciej. 4 5 Added a test case that came up when developing the ActivationImp tear-off. 6 7 * fast/js/resources/vardecl-preserve-arguments.js: 8 * fast/js/vardecl-preserve-arguments-expected.txt: 9 1 10 2008-01-11 Justin Garcia <justin.garcia@apple.com> 2 11 -
trunk/LayoutTests/fast/js/resources/vardecl-preserve-arguments.js
r24287 r29425 112 112 } 113 113 114 function argumentsTearOff1() 115 { 116 return argumentsTearOff2(2); 117 } 118 119 function argumentsTearOff2(b) 120 { 121 var v = b; 122 var w = argumentsTearOff1.arguments; 123 argumentsTearOff3(3); 124 return v; 125 } 126 127 function argumentsTearOff3(c) 128 { 129 var v = c; 130 } 131 114 132 shouldBe("argumentsLength()", "0"); 115 133 shouldBe("argumentsLength(1)", "1"); … … 143 161 shouldBe("argumentsLengthOverrideInnerBlock3('a','b')", "2"); 144 162 163 shouldBe("argumentsTearOff1()", "2"); 164 145 165 // this tests that behaviour should persists for 146 166 // the program source elements also -
trunk/LayoutTests/fast/js/vardecl-preserve-arguments-expected.txt
r24287 r29425 60 60 PASS 7 is 7 61 61 PASS argumentsLengthOverrideInnerBlock3('a','b') is 2 62 PASS argumentsTearOff1() is 2 62 63 PASS typeof undefined is 'undefined' 63 64 PASS 'undefined' is 'undefined' -
trunk/WebCore/ChangeLog
r29423 r29425 1 2008-01-11 Cameron Zwarich <cwzwarich@uwaterloo.ca> 2 3 Reviewed by Maciej. 4 5 Added a new forwarding header, because Activation.h has been separated 6 from function.h 7 8 * ForwardingHeaders/kjs/Activation.h: Added. 9 1 10 2008-01-11 Luca Bruno <lethalman88@gmail.com> 2 11
Note:
See TracChangeset
for help on using the changeset viewer.