Changeset 128260 in webkit
- Timestamp:
- Sep 11, 2012 9:08:18 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r128259 r128260 1 2012-09-11 Geoffrey Garen <ggaren@apple.com> 2 3 JSActivation should inline allocate its registers, and eliminate 4 'arguments' registers in the common case 5 https://bugs.webkit.org/show_bug.cgi?id=96427 6 7 Reviewed by Filip Pizlo. 8 9 This cuts the size class for simple closures down to 64 bytes. 10 11 * bytecompiler/BytecodeGenerator.cpp: 12 (JSC::BytecodeGenerator::BytecodeGenerator): Set the usesNonStrictEval 13 flag, which is new. Use a more specific test for whether a function 14 uses 'arguments', so we can avoid allocating, initializing, and tearing 15 off those registers in the common case. Distinguish between capturing 16 arguments and not, so we can avoid allocating space for arguments in 17 the torn-off object. 18 19 We can make this even more general in the future, with some bytecode 20 generator refactoring. 21 22 (JSC::BytecodeGenerator::resolve): Updated for new interface. 23 24 * bytecompiler/BytecodeGenerator.h: 25 (BytecodeGenerator): 26 (JSC::BytecodeGenerator::symbolTable): Updated some types. 27 28 * heap/Heap.cpp: 29 (JSC::Heap::isValidAllocation): Allow large allocations, now that they 30 are both supported and used. 31 32 * heap/Heap.h: 33 (Heap): Added a new form of allocateCell that specifies the full size 34 of the allocation, to allow for extra space on the end. 35 36 * interpreter/CallFrame.h: 37 (JSC::ExecState::argumentOffset): 38 (JSC::ExecState::argumentOffsetIncludingThis): 39 * interpreter/Interpreter.cpp: 40 (JSC::Interpreter::unwindCallFrame): Refactored this code to be more 41 specific about tearing off 'arguments' vs activations. This is something 42 I forgot in my last patch, and it is required now that we can have 43 acitvations without 'arguments' registers. 44 45 * runtime/Arguments.h: 46 (JSC::Arguments::setRegisters): No need for setRegisters anymore because 47 the activation object's storage doesn't change. 48 49 * runtime/JSActivation.cpp: 50 (JSC::JSActivation::JSActivation): Initialize our storage manually because 51 it's not declared to the C++ compiler. 52 53 (JSC::JSActivation::visitChildren): No copyAndAppend because our storage 54 is not out-of-line anymore. 55 56 (JSC::JSActivation::symbolTableGet): 57 (JSC::JSActivation::symbolTablePut): 58 (JSC::JSActivation::getOwnPropertyNames): 59 (JSC::JSActivation::symbolTablePutWithAttributes): 60 (JSC::JSActivation::getOwnPropertySlot): 61 (JSC::JSActivation::getOwnPropertyDescriptor): 62 (JSC::JSActivation::argumentsGetter): Refactored isTornOff() testing to 63 avoid using a data member and to avoid hard-coding any offset assumptions. 64 65 * runtime/JSActivation.h: 66 (JSC): 67 (JSActivation): 68 (JSC::JSActivation::create): 69 (JSC::JSActivation::isDynamicScope): 70 (JSC::JSActivation::captureStart): 71 (JSC::JSActivation::storageSize): 72 (JSC::JSActivation::storageSizeInBytes): 73 (JSC::JSActivation::registerOffset): 74 (JSC::JSActivation::tearOff): 75 (JSC::JSActivation::isTornOff): 76 (JSC::JSActivation::storage): 77 (JSC::JSActivation::allocationSize): 78 (JSC::JSActivation::isValid): New helper functions for doing the math 79 on our inline storage. Note that in the "AllOfTheThings" tear-off case, 80 the number of things is not known at compile time, so we store the 81 number in the argument count register. We can't just copy the raw contents 82 of the register beacuse we need a value that is safe for precise marking, 83 and the value in the register file has an invalid tag. 84 85 * runtime/JSCell.h: 86 (JSC::allocateCell): New function for allocating with extra storage 87 on the end. 88 89 * runtime/JSSymbolTableObject.h: 90 (JSC::JSSymbolTableObject::JSSymbolTableObject): 91 (JSC::JSSymbolTableObject::finishCreation): 92 * runtime/JSVariableObject.h: 93 (JSC::JSVariableObject::JSVariableObject): 94 (JSVariableObject): Make it easier for subclasses to use their symbol 95 tables during construction, by passing the table as a constructor argument. 96 97 * runtime/SymbolTable.h: 98 (JSC::SharedSymbolTable::usesNonStrictEval): 99 (JSC::SharedSymbolTable::setUsesNonStrictEval): 100 (SharedSymbolTable): 101 (JSC::SharedSymbolTable::captureMode): 102 (JSC::SharedSymbolTable::setCaptureMode): 103 (JSC::SharedSymbolTable::captureStart): 104 (JSC::SharedSymbolTable::setCaptureStart): 105 (JSC::SharedSymbolTable::captureEnd): 106 (JSC::SharedSymbolTable::setCaptureEnd): 107 (JSC::SharedSymbolTable::parameterCountIncludingThis): 108 (JSC::SharedSymbolTable::setParameterCountIncludingThis): 109 (JSC::SharedSymbolTable::SharedSymbolTable): Added data members to more 110 precisely describe what kind of capture is in play, and to avoid having 111 data members in the activation. We expect N activations per symbol table, 112 so this can be a big savings in heavy closure usage. 113 1 114 2012-09-11 Ryuan Choi <ryuan.choi@samsung.com> 2 115 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r128096 r128260 261 261 } 262 262 263 BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, JSScope* scope, S ymbolTable* symbolTable, ProgramCodeBlock* codeBlock, CompilationKind compilationKind)263 BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, JSScope* scope, SharedSymbolTable* symbolTable, ProgramCodeBlock* codeBlock, CompilationKind compilationKind) 264 264 : m_shouldEmitDebugHooks(scope->globalObject()->debugger()) 265 265 , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject())) … … 296 296 m_codeBlock->setNeedsFullScopeChain(true); 297 297 298 codeBlock->setGlobalData(m_globalData); 299 symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode()); 300 m_codeBlock->setNumParameters(1); // Allocate space for "this" 301 298 302 prependComment("entering Program block"); 299 303 emitOpcode(op_enter); 300 codeBlock->setGlobalData(m_globalData);301 304 302 305 // FIXME: Move code that modifies the global object to Interpreter::execute. 303 306 304 m_codeBlock->setNumParameters(1); // Allocate space for "this"305 307 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 306 308 … … 343 345 } 344 346 345 BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* scope, S ymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind)347 BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* scope, SharedSymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind) 346 348 : m_shouldEmitDebugHooks(scope->globalObject()->debugger()) 347 349 , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject())) … … 379 381 380 382 codeBlock->setGlobalData(m_globalData); 381 383 symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode()); 384 symbolTable->setParameterCountIncludingThis(functionBody->parameters()->size() + 1); 385 382 386 prependComment("entering Function block"); 383 387 emitOpcode(op_enter); … … 389 393 } 390 394 391 if ( m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) {395 if (functionBody->usesArguments() || codeBlock->usesEval() || m_shouldEmitDebugHooks) { // May reify arguments object. 392 396 RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. 393 397 RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'. … … 418 422 instructions().append(argumentsRegister->index()); 419 423 } 424 } 425 426 bool capturesAnyArgument = codeBlock->usesArguments() || codeBlock->usesEval() || m_shouldEmitDebugHooks; // May reify arguments object. 427 if (!capturesAnyArgument && functionBody->hasCapturedVariables()) { 428 FunctionParameters& parameters = *functionBody->parameters(); 429 for (size_t i = 0; i < parameters.size(); ++i) { 430 if (!functionBody->captures(parameters[i])) 431 continue; 432 capturesAnyArgument = true; 433 break; 434 } 435 } 436 437 if (capturesAnyArgument) { 438 symbolTable->setCaptureMode(SharedSymbolTable::AllOfTheThings); 439 symbolTable->setCaptureStart(-CallFrame::offsetFor(symbolTable->parameterCountIncludingThis())); 440 } else { 441 symbolTable->setCaptureMode(SharedSymbolTable::SomeOfTheThings); 442 symbolTable->setCaptureStart(m_codeBlock->m_numVars); 420 443 } 421 444 … … 485 508 } 486 509 487 if (m_shouldEmitDebugHooks )510 if (m_shouldEmitDebugHooks || codeBlock->usesEval()) 488 511 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 512 513 symbolTable->setCaptureEnd(codeBlock->m_numCapturedVars); 489 514 490 515 FunctionParameters& parameters = *functionBody->parameters(); … … 515 540 } 516 541 517 BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, S ymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind)542 BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SharedSymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind) 518 543 : m_shouldEmitDebugHooks(scope->globalObject()->debugger()) 519 544 , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject())) … … 550 575 m_codeBlock->setNeedsFullScopeChain(true); 551 576 577 codeBlock->setGlobalData(m_globalData); 578 symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode()); 579 m_codeBlock->setNumParameters(1); 580 552 581 prependComment("entering Eval block"); 553 582 emitOpcode(op_enter); 554 codeBlock->setGlobalData(m_globalData);555 m_codeBlock->setNumParameters(1);556 583 557 584 const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack(); … … 1356 1383 #if !ASSERT_DISABLED 1357 1384 if (JSActivation* activation = jsDynamicCast<JSActivation*>(currentVariableObject)) 1358 ASSERT(activation->isValid ScopedLookup(entry.getIndex()));1385 ASSERT(activation->isValid(entry)); 1359 1386 #endif 1360 1387 return ResolveResult::lexicalResolve(entry.getIndex(), depth, flags); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r128096 r128260 262 262 static bool dumpsGeneratedCode(); 263 263 264 BytecodeGenerator(ProgramNode*, JSScope*, S ymbolTable*, ProgramCodeBlock*, CompilationKind);265 BytecodeGenerator(FunctionBodyNode*, JSScope*, S ymbolTable*, CodeBlock*, CompilationKind);266 BytecodeGenerator(EvalNode*, JSScope*, S ymbolTable*, EvalCodeBlock*, CompilationKind);264 BytecodeGenerator(ProgramNode*, JSScope*, SharedSymbolTable*, ProgramCodeBlock*, CompilationKind); 265 BytecodeGenerator(FunctionBodyNode*, JSScope*, SharedSymbolTable*, CodeBlock*, CompilationKind); 266 BytecodeGenerator(EvalNode*, JSScope*, SharedSymbolTable*, EvalCodeBlock*, CompilationKind); 267 267 268 268 ~BytecodeGenerator(); … … 655 655 Vector<Instruction>& instructions() { return m_instructions; } 656 656 657 S ymbolTable& symbolTable() { return *m_symbolTable; }657 SharedSymbolTable& symbolTable() { return *m_symbolTable; } 658 658 #if ENABLE(BYTECODE_COMMENTS) 659 659 Vector<Comment>& comments() { return m_comments; } … … 698 698 699 699 Strong<JSScope> m_scope; 700 S ymbolTable* m_symbolTable;700 SharedSymbolTable* m_symbolTable; 701 701 702 702 #if ENABLE(BYTECODE_COMMENTS) -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r127829 r128260 802 802 } 803 803 804 bool Heap::isValidAllocation(size_t bytes)804 bool Heap::isValidAllocation(size_t) 805 805 { 806 806 if (!isValidThreadState(m_globalData)) 807 return false;808 809 if (bytes > MarkedSpace::maxCellSize)810 807 return false; 811 808 -
trunk/Source/JavaScriptCore/heap/Heap.h
r128141 r128260 183 183 friend class SlotVisitor; 184 184 template<typename T> friend void* allocateCell(Heap&); 185 template<typename T> friend void* allocateCell(Heap&, size_t); 185 186 186 187 void* allocateWithDestructor(size_t); -
trunk/Source/JavaScriptCore/interpreter/CallFrame.h
r127211 r128260 191 191 size_t argumentCount() const { return argumentCountIncludingThis() - 1; } 192 192 size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].payload(); } 193 static int argumentOffset( size_t argument) { return s_firstArgumentOffset - argument; }194 static int argumentOffsetIncludingThis( size_t argument) { return s_thisArgumentOffset - argument; }193 static int argumentOffset(int argument) { return s_firstArgumentOffset - argument; } 194 static int argumentOffsetIncludingThis(int argument) { return s_thisArgumentOffset - argument; } 195 195 196 196 JSValue argument(size_t argument) -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r128111 r128260 464 464 } 465 465 466 // If this call frame created an activation or an 'arguments' object, tear it off. 467 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) { 468 if (!callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue()) { 469 oldCodeBlock->createActivation(callFrame); 470 scope = callFrame->scope(); 471 } 472 while (!scope->inherits(&JSActivation::s_info)) 473 scope = scope->next(); 474 475 callFrame->setScope(scope); 476 JSActivation* activation = asActivation(scope); 477 activation->tearOff(*scope->globalData()); 478 if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) 479 asArguments(arguments)->didTearOffActivation(callFrame->globalData(), activation); 480 } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) { 481 if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) 482 asArguments(arguments)->tearOff(callFrame); 466 JSValue activation; 467 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsActivation()) { 468 activation = callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue(); 469 if (activation) 470 jsCast<JSActivation*>(activation)->tearOff(*scope->globalData()); 471 } 472 473 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) { 474 if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) { 475 if (activation) 476 jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame->globalData(), jsCast<JSActivation*>(activation)); 477 else 478 jsCast<Arguments*>(arguments)->tearOff(callFrame); 479 } 483 480 } 484 481 -
trunk/Source/JavaScriptCore/runtime/Arguments.h
r126695 r128260 111 111 d->registers = &activation->registerAt(0); 112 112 } 113 void setRegisters(WriteBarrierBase<Unknown>* registers) { d->registers = registers; }114 113 115 114 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) -
trunk/Source/JavaScriptCore/runtime/JSActivation.cpp
r127363 r128260 42 42 const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSActivation) }; 43 43 44 JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)45 : Base(46 callFrame->globalData(),47 callFrame->lexicalGlobalObject()->activationStructure(),48 callFrame->registers(),49 callFrame->scope()50 )51 , m_registerArray(callFrame->globalData(), this, 0)52 , m_numCapturedArgs(max(callFrame->argumentCount(), functionExecutable->parameterCount()))53 , m_numCapturedVars(functionExecutable->capturedVariableCount())54 , m_isTornOff(false)55 , m_requiresDynamicChecks(functionExecutable->usesEval() && !functionExecutable->isStrictMode())56 , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())57 {58 }59 60 void JSActivation::finishCreation(CallFrame* callFrame, FunctionExecutable* functionExecutable)61 {62 Base::finishCreation(callFrame->globalData(), functionExecutable->symbolTable());63 ASSERT(inherits(&s_info));64 }65 66 44 void JSActivation::visitChildren(JSCell* cell, SlotVisitor& visitor) 67 45 { … … 73 51 74 52 // No need to mark our registers if they're still in the RegisterFile. 75 PropertyStorage registerArray = thisObject->m_registerArray.get(); 76 if (!registerArray) 53 if (!thisObject->isTornOff()) 77 54 return; 78 55 79 visitor.copyAndAppend(bitwise_cast<void**>(®isterArray), thisObject->registerArraySizeInBytes(), reinterpret_cast<JSValue*>(registerArray), thisObject->registerArraySize()); 80 thisObject->m_registerArray.set(registerArray, StorageBarrier::Unchecked); 81 thisObject->m_registers = registerArray + thisObject->registerOffset(); 82 83 // Update the arguments object, since it points at our buffer. 84 CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(thisObject->m_registers)); 85 if (JSValue v = callFrame->uncheckedR(unmodifiedArgumentsRegister(thisObject->m_argumentsRegister)).jsValue()) 86 jsCast<Arguments*>(v)->setRegisters(thisObject->m_registers); 56 for (size_t i = 0; i < thisObject->storageSize(); ++i) 57 visitor.append(&thisObject->storage()[i]); 87 58 } 88 59 … … 94 65 95 66 // Defend against the inspector asking for a var after it has been optimized out. 96 if ( m_isTornOff && entry.getIndex() >= m_numCapturedVars)67 if (isTornOff() && !isValid(entry)) 97 68 return false; 98 69 … … 108 79 109 80 // Defend against the inspector asking for a var after it has been optimized out. 110 if ( m_isTornOff && entry.getIndex() >= m_numCapturedVars)81 if (isTornOff() && !isValid(entry)) 111 82 return false; 112 83 … … 130 101 131 102 // Defend against the inspector asking for a var after it has been optimized out. 132 if ( m_isTornOff && entry.getIndex() >= m_numCapturedVars)103 if (isTornOff() && !isValid(entry)) 133 104 return false; 134 105 … … 141 112 JSActivation* thisObject = jsCast<JSActivation*>(object); 142 113 143 if (mode == IncludeDontEnumProperties )114 if (mode == IncludeDontEnumProperties && !thisObject->isTornOff()) 144 115 propertyNames.add(exec->propertyNames().arguments); 145 116 … … 148 119 if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties) 149 120 continue; 150 if ( it->second.getIndex() >= thisObject->m_numCapturedVars)121 if (!thisObject->isValid(it->second)) 151 122 continue; 152 123 propertyNames.add(Identifier(exec, it->first.get())); … … 165 136 SymbolTableEntry& entry = iter->second; 166 137 ASSERT(!entry.isNull()); 167 if ( entry.getIndex() >= m_numCapturedVars)138 if (!isValid(entry)) 168 139 return false; 169 140 … … 179 150 if (propertyName == exec->propertyNames().arguments) { 180 151 // Defend against the inspector asking for the arguments object after it has been optimized out. 181 if (!thisObject-> m_isTornOff) {152 if (!thisObject->isTornOff()) { 182 153 slot.setCustom(thisObject, thisObject->getArgumentsGetter()); 183 154 return true; … … 206 177 if (propertyName == exec->propertyNames().arguments) { 207 178 // Defend against the inspector asking for the arguments object after it has been optimized out. 208 if (!thisObject-> m_isTornOff) {179 if (!thisObject->isTornOff()) { 209 180 PropertySlot slot; 210 181 JSActivation::getOwnPropertySlot(thisObject, exec, propertyName, slot); … … 266 237 JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, PropertyName) 267 238 { 268 JSActivation* activation = asActivation(slotBase); 239 JSActivation* activation = jsCast<JSActivation*>(slotBase); 240 if (activation->isTornOff()) 241 return jsUndefined(); 242 269 243 CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->m_registers)); 270 int argumentsRegister = activation->m_argumentsRegister;244 int argumentsRegister = callFrame->codeBlock()->argumentsRegister(); 271 245 if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue()) 272 246 return arguments; -
trunk/Source/JavaScriptCore/runtime/JSActivation.h
r127376 r128260 38 38 namespace JSC { 39 39 40 class Arguments;41 40 class Register; 42 41 43 42 class JSActivation : public JSVariableObject { 44 43 private: 45 JSActivation( CallFrame*, FunctionExecutable*);44 JSActivation(JSGlobalData& globalData, CallFrame*, SharedSymbolTable*, size_t storageSize); 46 45 47 46 public: 48 47 typedef JSVariableObject Base; 49 48 50 static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, FunctionExecutable* func Exec)49 static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, FunctionExecutable* functionExecutable) 51 50 { 52 JSActivation* activation = new (NotNull, allocateCell<JSActivation>(globalData.heap)) JSActivation(callFrame, funcExec); 53 activation->finishCreation(callFrame, funcExec); 51 size_t storageSize = JSActivation::storageSize(callFrame, functionExecutable->symbolTable()); 52 JSActivation* activation = new ( 53 NotNull, 54 allocateCell<JSActivation>( 55 globalData.heap, 56 allocationSize(storageSize) 57 ) 58 ) JSActivation(globalData, callFrame, functionExecutable->symbolTable(), storageSize); 59 activation->finishCreation(globalData); 54 60 return activation; 55 61 } … … 76 82 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), &s_info); } 77 83 78 bool isValidScopedLookup(int index) { return index < m_numCapturedVars; } 84 bool isValid(const SymbolTableEntry&); 85 bool isTornOff(); 79 86 80 87 protected: 81 void finishCreation(CallFrame*, FunctionExecutable*);82 88 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags; 83 89 … … 92 98 NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); 93 99 94 size_t registerOffset(); 95 size_t registerArraySize(); 96 size_t registerArraySizeInBytes(); 97 98 StorageBarrier m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. 99 int m_numCapturedArgs; 100 int m_numCapturedVars : 30; 101 bool m_isTornOff : 1; 102 bool m_requiresDynamicChecks : 1; 103 int m_argumentsRegister; 100 static size_t allocationSize(size_t storageSize); 101 static size_t storageSize(CallFrame*, SharedSymbolTable*); 102 static int captureStart(CallFrame*, SharedSymbolTable*); 103 104 int registerOffset(); 105 size_t storageSize(); 106 WriteBarrier<Unknown>* storage(); // storageSize() number of registers. 104 107 }; 108 109 extern int activationCount; 110 extern int allTheThingsCount; 111 112 inline JSActivation::JSActivation(JSGlobalData& globalData, CallFrame* callFrame, SharedSymbolTable* symbolTable, size_t storageSize) 113 : Base( 114 globalData, 115 callFrame->lexicalGlobalObject()->activationStructure(), 116 callFrame->registers(), 117 callFrame->scope(), 118 symbolTable 119 ) 120 { 121 WriteBarrier<Unknown>* storage = this->storage(); 122 for (size_t i = 0; i < storageSize; ++i) 123 new(&storage[i]) WriteBarrier<Unknown>; 124 } 105 125 106 126 JSActivation* asActivation(JSValue); … … 119 139 inline bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const 120 140 { 121 requiresDynamicChecks = m_requiresDynamicChecks;141 requiresDynamicChecks = symbolTable()->usesNonStrictEval(); 122 142 return false; 123 143 } 124 144 125 inline size_t JSActivation::registerOffset() 126 { 127 if (!m_numCapturedArgs) 128 return 0; 129 130 size_t capturedArgumentCountIncludingThis = m_numCapturedArgs + 1; 131 return CallFrame::offsetFor(capturedArgumentCountIncludingThis); 132 } 133 134 inline size_t JSActivation::registerArraySize() 135 { 136 return registerOffset() + m_numCapturedVars; 137 } 138 139 inline size_t JSActivation::registerArraySizeInBytes() 140 { 141 return registerArraySize() * sizeof(WriteBarrierBase<Unknown>); 145 inline int JSActivation::captureStart(CallFrame* callFrame, SharedSymbolTable* symbolTable) 146 { 147 if (symbolTable->captureMode() == SharedSymbolTable::AllOfTheThings) 148 return -CallFrame::offsetFor(std::max<size_t>(callFrame->argumentCountIncludingThis(), symbolTable->parameterCountIncludingThis())); 149 return symbolTable->captureStart(); 150 } 151 152 inline size_t JSActivation::storageSize(CallFrame* callFrame, SharedSymbolTable* symbolTable) 153 { 154 return symbolTable->captureEnd() - captureStart(callFrame, symbolTable); 155 } 156 157 inline int JSActivation::registerOffset() 158 { 159 return -captureStart(CallFrame::create(reinterpret_cast<Register*>(m_registers)), symbolTable()); 160 } 161 162 inline size_t JSActivation::storageSize() 163 { 164 return storageSize(CallFrame::create(reinterpret_cast<Register*>(m_registers)), symbolTable()); 142 165 } 143 166 144 167 inline void JSActivation::tearOff(JSGlobalData& globalData) 145 168 { 146 ASSERT(!m_registerArray); 147 ASSERT(m_numCapturedVars + m_numCapturedArgs); 148 149 void* allocation = 0; 150 if (!globalData.heap.tryAllocateStorage(registerArraySizeInBytes(), &allocation)) 151 CRASH(); 152 PropertyStorage registerArray = static_cast<PropertyStorage>(allocation); 153 PropertyStorage registers = registerArray + registerOffset(); 154 155 // arguments 156 int from = CallFrame::argumentOffset(m_numCapturedArgs - 1); 157 int to = CallFrame::thisArgumentOffset(); // Skip 'this' because it's not lexically accessible. 158 for (int i = from; i < to; ++i) 159 registers[i].set(globalData, this, m_registers[i].get()); 160 161 // vars 162 from = 0; 163 to = m_numCapturedVars; 164 for (int i = from; i < to; ++i) 165 registers[i].set(globalData, this, m_registers[i].get()); 166 167 m_registerArray.set(globalData, this, registerArray); 168 m_registers = registers; 169 m_isTornOff = true; 169 ASSERT(!isTornOff()); 170 171 int registerOffset = this->registerOffset(); 172 WriteBarrierBase<Unknown>* dst = storage() + registerOffset; 173 WriteBarrierBase<Unknown>* src = m_registers; 174 175 if (symbolTable()->captureMode() == SharedSymbolTable::AllOfTheThings) { 176 int from = -registerOffset; 177 int to = CallFrame::thisArgumentOffset(); // Skip 'this' because it's not lexically accessible. 178 for (int i = from; i < to; ++i) 179 dst[i].set(globalData, this, src[i].get()); 180 181 dst[RegisterFile::ArgumentCount].set(globalData, this, JSValue( 182 CallFrame::create(reinterpret_cast<Register*>(src))->argumentCountIncludingThis())); 183 184 int captureEnd = symbolTable()->captureEnd(); 185 for (int i = 0; i < captureEnd; ++i) 186 dst[i].set(globalData, this, src[i].get()); 187 } else { 188 int captureEnd = symbolTable()->captureEnd(); 189 for (int i = symbolTable()->captureStart(); i < captureEnd; ++i) 190 dst[i].set(globalData, this, src[i].get()); 191 } 192 193 m_registers = dst; 194 ASSERT(isTornOff()); 195 } 196 197 inline bool JSActivation::isTornOff() 198 { 199 return m_registers == storage() + registerOffset(); 200 } 201 202 inline WriteBarrier<Unknown>* JSActivation::storage() 203 { 204 return reinterpret_cast<WriteBarrier<Unknown>*>( 205 reinterpret_cast<char*>(this) + 206 WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation)) 207 ); 208 } 209 210 inline size_t JSActivation::allocationSize(size_t storageSize) 211 { 212 size_t objectSizeInBytes = WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation)); 213 size_t storageSizeInBytes = storageSize * sizeof(WriteBarrier<Unknown>); 214 return objectSizeInBytes + storageSizeInBytes; 215 } 216 217 inline bool JSActivation::isValid(const SymbolTableEntry& entry) 218 { 219 if (entry.getIndex() < captureStart(CallFrame::create(reinterpret_cast<Register*>(m_registers)), symbolTable())) 220 return false; 221 if (entry.getIndex() >= symbolTable()->captureEnd()) 222 return false; 223 return true; 170 224 } 171 225 -
trunk/Source/JavaScriptCore/runtime/JSCell.h
r128146 r128260 65 65 friend class MarkedBlock; 66 66 template<typename T> friend void* allocateCell(Heap&); 67 template<typename T> friend void* allocateCell(Heap&, size_t); 67 68 68 69 public: … … 338 339 } 339 340 341 template<typename T> 342 void* allocateCell(Heap& heap, size_t size) 343 { 344 ASSERT(size >= sizeof(T)); 345 #if ENABLE(GC_VALIDATION) 346 ASSERT(!heap.globalData()->isInitializingObject()); 347 heap.globalData()->setInitializingObjectClass(&T::s_info); 348 #endif 349 JSCell* result = 0; 350 if (NeedsDestructor<T>::value) 351 result = static_cast<JSCell*>(heap.allocateWithDestructor(size)); 352 else { 353 ASSERT(T::s_info.methodTable.destroy == JSCell::destroy); 354 result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size)); 355 } 356 result->clearStructure(); 357 return result; 358 } 359 340 360 inline bool isZapped(const JSCell* cell) 341 361 { -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r127505 r128260 28 28 #include "CallFrame.h" 29 29 #include "Interpreter.h" 30 #include "JSFunction.h" 30 31 #include "JSGlobalObject.h" 31 32 #include "JSString.h" -
trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
r127363 r128260 50 50 static const unsigned StructureFlags = IsEnvironmentRecord | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags; 51 51 52 JSSymbolTableObject(JSGlobalData& globalData, Structure* structure, JSScope* scope )52 JSSymbolTableObject(JSGlobalData& globalData, Structure* structure, JSScope* scope, SharedSymbolTable* symbolTable = 0) 53 53 : Base(globalData, structure, scope) 54 54 { 55 if (symbolTable) 56 m_symbolTable.set(globalData, this, symbolTable); 55 57 } 56 58 57 void finishCreation(JSGlobalData& globalData , SharedSymbolTable* symbolTable = 0)59 void finishCreation(JSGlobalData& globalData) 58 60 { 59 61 Base::finishCreation(globalData); 60 if (!symbolTable) 61 symbolTable = SharedSymbolTable::create(globalData); 62 m_symbolTable.set(globalData, this, symbolTable); 62 if (!m_symbolTable) 63 m_symbolTable.set(globalData, this, SharedSymbolTable::create(globalData)); 63 64 } 64 65 -
trunk/Source/JavaScriptCore/runtime/JSVariableObject.h
r127363 r128260 61 61 Structure* structure, 62 62 Register* registers, 63 JSScope* scope 63 JSScope* scope, 64 SharedSymbolTable* symbolTable = 0 64 65 ) 65 : Base(globalData, structure, scope )66 : Base(globalData, structure, scope, symbolTable) 66 67 , m_registers(reinterpret_cast<WriteBarrierBase<Unknown>*>(registers)) 67 68 { 68 }69 70 void finishCreation(JSGlobalData& globalData, SharedSymbolTable* symbolTable = 0)71 {72 Base::finishCreation(globalData, symbolTable);73 COMPILE_ASSERT(sizeof(WriteBarrierBase<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrierBase);74 69 } 75 70 -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r127191 r128260 341 341 } 342 342 343 bool usesNonStrictEval() { return m_usesNonStrictEval; } 344 void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; } 345 346 enum CaptureMode { 347 SomeOfTheThings, 348 AllOfTheThings 349 }; 350 351 CaptureMode captureMode() { return m_captureMode; } 352 void setCaptureMode(CaptureMode captureMode) { m_captureMode = captureMode; } 353 354 int captureStart() { return m_captureStart; } 355 void setCaptureStart(int captureStart) { m_captureStart = captureStart; } 356 357 int captureEnd() { return m_captureEnd; } 358 void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; } 359 360 int parameterCountIncludingThis() { return m_parameterCountIncludingThis; } 361 void setParameterCountIncludingThis(int parameterCountIncludingThis) { m_parameterCountIncludingThis = parameterCountIncludingThis; } 362 343 363 static JS_EXPORTDATA const ClassInfo s_info; 344 364 … … 346 366 SharedSymbolTable(JSGlobalData& globalData) 347 367 : JSCell(globalData, globalData.sharedSymbolTableStructure.get()) 348 { 349 } 368 , m_parameterCountIncludingThis(0) 369 , m_usesNonStrictEval(false) 370 , m_captureMode(SomeOfTheThings) 371 , m_captureStart(0) 372 , m_captureEnd(0) 373 { 374 } 375 376 int m_parameterCountIncludingThis; 377 bool m_usesNonStrictEval; 378 379 CaptureMode m_captureMode; 380 int m_captureStart; 381 int m_captureEnd; 350 382 }; 351 383
Note: See TracChangeset
for help on using the changeset viewer.