Changeset 28884 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp
- Timestamp:
- Dec 20, 2007, 1:32:06 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/nodes.cpp
r28855 r28884 3489 3489 inline void VarDeclNode::evaluateSingle(ExecState* exec) 3490 3490 { 3491 ASSERT(exec->variableObject()->hasOwnProperty(exec, ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations. 3491 3492 const ScopeChain& chain = exec->scopeChain(); 3492 3493 JSObject* variableObject = exec->variableObject(); … … 3496 3497 bool inGlobalScope = ++chain.begin() == chain.end(); 3497 3498 3498 if (inGlobalScope && (init || !variableObject->getDirect(ident))) { 3499 JSValue* val = init ? init->evaluate(exec) : jsUndefined(); 3500 int flags = Internal; 3501 if (exec->codeType() != EvalCode) 3502 flags |= DontDelete; 3503 if (varType == VarDeclNode::Constant) 3504 flags |= ReadOnly; 3505 variableObject->putDirect(ident, val, flags); 3506 } else if (init) { 3507 JSValue* val = init->evaluate(exec); 3508 KJS_CHECKEXCEPTIONVOID 3499 if (init) { 3500 if (inGlobalScope) { 3501 JSValue* val = init->evaluate(exec); 3502 int flags = Internal; 3503 if (exec->codeType() != EvalCode) 3504 flags |= DontDelete; 3505 if (varType == VarDeclNode::Constant) 3506 flags |= ReadOnly; 3507 variableObject->put(exec, ident, val, flags); 3508 } else { 3509 JSValue* val = init->evaluate(exec); 3510 KJS_CHECKEXCEPTIONVOID 3511 3512 // if the variable object is the top of the scope chain, then that must 3513 // be where this variable is declared, processVarDecls would have put 3514 // it there. Don't search the scope chain, to optimize this very common case. 3515 if (chain.top() != variableObject) 3516 return handleSlowCase(exec, chain, val); 3517 3518 unsigned flags = 0; 3519 variableObject->getPropertyAttributes(ident, flags); 3520 if (varType == VarDeclNode::Constant) 3521 flags |= ReadOnly; 3509 3522 3510 // if the variable object is the top of the scope chain, then that must 3511 // be where this variable is declared, processVarDecls would have put 3512 // it there. Don't search the scope chain, to optimize this very common case. 3513 if (chain.top() != variableObject) 3514 return handleSlowCase(exec, chain, val); 3515 3516 unsigned flags = 0; 3517 variableObject->getPropertyAttributes(ident, flags); 3518 if (varType == VarDeclNode::Constant) 3519 flags |= ReadOnly; 3520 3521 ASSERT(variableObject->hasProperty(exec, ident)); 3522 variableObject->put(exec, ident, val, flags); 3523 variableObject->put(exec, ident, val, flags); 3524 } 3523 3525 } 3524 3526 } … … 4275 4277 void FunctionBodyNode::initializeSymbolTable(ExecState* exec) 4276 4278 { 4277 size_t i, size; 4278 size_t count = 0; 4279 4280 // The order of additions here implicitly enforces the mutual exclusion described in ECMA 10.1.3. 4281 for (i = 0, size = m_varStack.size(); i < size; ++i) { 4282 if (m_varStack[i]->ident != exec->propertyNames().arguments) 4283 m_symbolTable.set(m_varStack[i]->ident.ustring().rep(), count); 4284 count++; 4285 } 4286 4287 for (i = 0, size = m_parameters.size(); i < size; ++i) 4288 m_symbolTable.set(m_parameters[i].ustring().rep(), count++); 4289 4290 for (i = 0, size = m_functionStack.size(); i < size; ++i) 4291 m_symbolTable.set(m_functionStack[i]->ident.ustring().rep(), count++); 4292 } 4293 4294 void FunctionBodyNode::optimizeVariableAccess() 4279 SymbolTable& symbolTable = exec->variableObject()->symbolTable(); 4280 ASSERT(!symbolTable.size()); 4281 4282 size_t localStorageIndex = 0; 4283 4284 for (size_t i = 0, size = m_parameters.size(); i < size; ++i, ++localStorageIndex) { 4285 UString::Rep* rep = m_parameters[i].ustring().rep(); 4286 symbolTable.set(rep, localStorageIndex); 4287 } 4288 4289 for (size_t i = 0, size = m_functionStack.size(); i < size; ++i, ++localStorageIndex) { 4290 UString::Rep* rep = m_functionStack[i]->ident.ustring().rep(); 4291 symbolTable.set(rep, localStorageIndex); 4292 } 4293 4294 for (size_t i = 0, size = m_varStack.size(); i < size; ++i, ++localStorageIndex) { 4295 Identifier& ident = m_varStack[i]->ident; 4296 if (ident == exec->propertyNames().arguments) 4297 continue; 4298 symbolTable.add(ident.ustring().rep(), localStorageIndex); 4299 } 4300 } 4301 4302 void ProgramNode::initializeSymbolTable(ExecState* exec) 4303 { 4304 // If a previous script defined a symbol with the same name as one of our 4305 // symbols, to avoid breaking previously optimized nodes, we need to reuse 4306 // the symbol's existing storage index. So, we can't be as efficient as 4307 // FunctionBodyNode::initializeSymbolTable, which knows that no bindings 4308 // have yet been made. 4309 4310 JSVariableObject* variableObject = exec->variableObject(); 4311 SymbolTable& symbolTable = variableObject->symbolTable(); 4312 4313 size_t localStorageIndex = symbolTable.size(); 4314 size_t size; 4315 4316 size = m_functionStack.size(); 4317 m_functionIndexes.resize(size); 4318 for (size_t i = 0; i < size; ++i) { 4319 UString::Rep* rep = m_functionStack[i]->ident.ustring().rep(); 4320 pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex); 4321 m_functionIndexes[i] = result.first->second; 4322 if (result.second) 4323 ++localStorageIndex; 4324 } 4325 4326 size = m_varStack.size(); 4327 m_varIndexes.resize(size); 4328 for (size_t i = 0; i < size; ++i) { 4329 const Identifier& ident = m_varStack[i]->ident; 4330 if (variableObject->getDirect(ident)) { 4331 m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration. 4332 continue; 4333 } 4334 4335 UString::Rep* rep = ident.ustring().rep(); 4336 pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex); 4337 if (!result.second) { 4338 m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration. 4339 continue; 4340 } 4341 m_varIndexes[i] = result.first->second; 4342 ++localStorageIndex; 4343 } 4344 } 4345 4346 void ScopeNode::optimizeVariableAccess(ExecState* exec) 4295 4347 { 4296 4348 DeclarationStacks::NodeStack nodeStack; … … 4299 4351 return; 4300 4352 4353 SymbolTable& symbolTable = exec->variableObject()->symbolTable(); 4301 4354 while (true) { 4302 node->optimizeVariableAccess( m_symbolTable, nodeStack);4355 node->optimizeVariableAccess(symbolTable, nodeStack); 4303 4356 4304 4357 size_t size = nodeStack.size(); … … 4315 4368 if (!m_initialized) { 4316 4369 initializeSymbolTable(exec); 4317 optimizeVariableAccess( );4370 optimizeVariableAccess(exec); 4318 4371 4319 4372 m_initialized = true; … … 4321 4374 4322 4375 LocalStorage& localStorage = exec->variableObject()->localStorage(); 4376 4377 // We can't just resize localStorage here because that would temporarily 4378 // leave uninitialized entries, which would crash GC during the mark phase. 4323 4379 localStorage.reserveCapacity(m_varStack.size() + m_parameters.size() + m_functionStack.size()); 4324 4380 4325 4381 int minAttributes = Internal | DontDelete; 4326 4382 4327 size_t i, size; 4328 4329 // NOTE: Must match the order of addition in initializeSymbolTable(). 4330 4331 for (i = 0, size = m_varStack.size(); i < size; ++i) { 4383 // In order for our localStorage indexes to be correct, we must match the 4384 // order of addition in initializeSymbolTable(). 4385 4386 const List& args = *exec->arguments(); 4387 for (size_t i = 0, size = m_parameters.size(); i < size; ++i) 4388 localStorage.uncheckedAppend(LocalStorageEntry(args[i], DontDelete)); 4389 4390 for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) { 4391 FuncDeclNode* node = m_functionStack[i]; 4392 localStorage.uncheckedAppend(LocalStorageEntry(node->makeFunction(exec), minAttributes)); 4393 } 4394 4395 for (size_t i = 0, size = m_varStack.size(); i < size; ++i) { 4332 4396 VarDeclNode* node = m_varStack[i]; 4333 4397 int attributes = minAttributes; 4334 4398 if (node->varType == VarDeclNode::Constant) 4335 4399 attributes |= ReadOnly; 4336 localStorage.append(LocalStorageEntry(jsUndefined(), attributes)); 4337 } 4338 4339 const List& args = *exec->arguments(); 4340 for (i = 0, size = m_parameters.size(); i < size; ++i) 4341 localStorage.append(LocalStorageEntry(args[i], DontDelete)); 4342 4343 for (i = 0, size = m_functionStack.size(); i < size; ++i) { 4400 localStorage.uncheckedAppend(LocalStorageEntry(jsUndefined(), attributes)); 4401 } 4402 } 4403 4404 static void gccIsCrazy() KJS_FAST_CALL; 4405 static void gccIsCrazy() 4406 { 4407 } 4408 4409 void ProgramNode::processDeclarations(ExecState* exec) 4410 { 4411 // If you remove this call, some SunSpider tests, including 4412 // bitops-nsieve-bits.js, will regress substantially on Mac, due to a ~40% 4413 // increase in L2 cache misses. FIXME: WTF? 4414 gccIsCrazy(); 4415 4416 initializeSymbolTable(exec); 4417 optimizeVariableAccess(exec); 4418 4419 LocalStorage& localStorage = exec->variableObject()->localStorage(); 4420 4421 // We can't just resize localStorage here because that would temporarily 4422 // leave uninitialized entries, which would crash GC during the mark phase. 4423 localStorage.reserveCapacity(localStorage.size() + m_varStack.size() + m_functionStack.size()); 4424 4425 int minAttributes = Internal | DontDelete; 4426 4427 // In order for our localStorage indexes to be correct, we must match the 4428 // order of addition in initializeSymbolTable(). 4429 4430 for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) { 4344 4431 FuncDeclNode* node = m_functionStack[i]; 4345 localStorage.append(LocalStorageEntry(node->makeFunction(exec), minAttributes)); 4346 } 4347 4348 exec->updateLocalStorage(); 4349 } 4350 4351 void ProgramNode::processDeclarations(ExecState* exec) 4352 { 4353 size_t i, size; 4354 4355 JSVariableObject* variableObject = exec->variableObject(); 4356 4357 int minAttributes = Internal | DontDelete; 4358 4359 for (i = 0, size = m_varStack.size(); i < size; ++i) { 4432 LocalStorageEntry entry = LocalStorageEntry(node->makeFunction(exec), minAttributes); 4433 size_t index = m_functionIndexes[i]; 4434 4435 if (index == localStorage.size()) 4436 localStorage.uncheckedAppend(entry); 4437 else { 4438 ASSERT(index < localStorage.size()); 4439 localStorage[index] = entry; 4440 } 4441 } 4442 4443 for (size_t i = 0, size = m_varStack.size(); i < size; ++i) { 4444 size_t index = m_varIndexes[i]; 4445 if (index == missingSymbolMarker()) 4446 continue; 4447 4360 4448 VarDeclNode* node = m_varStack[i]; 4361 if (variableObject->hasProperty(exec, node->ident))4362 continue;4363 4449 int attributes = minAttributes; 4364 4450 if (node->varType == VarDeclNode::Constant) 4365 4451 attributes |= ReadOnly; 4366 variableObject->put(exec, node->ident, jsUndefined(), attributes); 4367 } 4368 4369 for (i = 0, size = m_functionStack.size(); i < size; ++i) { 4370 FuncDeclNode* node = m_functionStack[i]; 4371 variableObject->put(exec, node->ident, node->makeFunction(exec), minAttributes); 4452 LocalStorageEntry entry = LocalStorageEntry(jsUndefined(), attributes); 4453 4454 ASSERT(index == localStorage.size()); 4455 localStorage.uncheckedAppend(entry); 4372 4456 } 4373 4457 } … … 4375 4459 void EvalNode::processDeclarations(ExecState* exec) 4376 4460 { 4461 // We could optimize access to pre-existing symbols here, but SunSpider 4462 // reports that to be a net loss. 4463 4377 4464 size_t i, size; 4378 4465 … … 4383 4470 for (i = 0, size = m_varStack.size(); i < size; ++i) { 4384 4471 VarDeclNode* node = m_varStack[i]; 4385 if (variableObject->has Property(exec, node->ident))4472 if (variableObject->hasOwnProperty(exec, node->ident)) 4386 4473 continue; 4387 4474 int attributes = minAttributes;
Note:
See TracChangeset
for help on using the changeset viewer.