Changeset 36821 in webkit for trunk/JavaScriptCore/VM/CodeGenerator.cpp
- Timestamp:
- Sep 23, 2008, 5:27:18 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/VM/CodeGenerator.cpp
r36751 r36821 130 130 void CodeGenerator::generate() 131 131 { 132 m_codeBlock->numLocals = m_codeBlock->numVars + m_codeBlock->numParameters;133 132 m_codeBlock->thisRegister = m_thisRegister.index(); 133 134 134 if (m_shouldEmitDebugHooks) 135 135 m_codeBlock->needsFullScopeChain = true; … … 153 153 bool CodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0) 154 154 { 155 int index = m_nextVar; 155 int index = m_calleeRegisters.size(); 156 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); 157 pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry); 158 159 if (!result.second) { 160 r0 = ®isterFor(result.first->second.getIndex()); 161 return false; 162 } 163 164 ++m_codeBlock->numVars; 165 r0 = newRegister(); 166 return true; 167 } 168 169 bool CodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0) 170 { 171 int index = m_nextGlobal; 156 172 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); 157 173 pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry); … … 160 176 index = result.first->second.getIndex(); 161 177 else { 162 --m_nextVar; 163 ++m_codeBlock->numVars; 164 165 m_locals.append(index); 166 } 167 168 r0 = &m_locals[localsIndex(index)]; 178 --m_nextGlobal; 179 m_globals.append(index + m_globalVarStorageOffset); 180 } 181 182 r0 = ®isterFor(index); 169 183 return result.second; 170 184 } 171 185 172 bool CodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0) 173 { 174 int index = m_nextVar; 175 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); 176 pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry); 177 178 if (!result.second) 179 index = result.first->second.getIndex(); 180 else { 181 --m_nextVar; 182 m_locals.append(index + m_globalVarStorageOffset); 183 } 184 185 r0 = &m_locals[localsIndex(index)]; 186 return result.second; 186 void CodeGenerator::allocateConstants(size_t count) 187 { 188 m_codeBlock->numConstants = count; 189 if (!count) 190 return; 191 192 m_nextConstant = m_calleeRegisters.size(); 193 194 for (size_t i = 0; i < count; ++i) 195 newRegister(); 196 m_lastConstant = &m_calleeRegisters.last(); 187 197 } 188 198 … … 198 208 , m_codeType(GlobalCode) 199 209 , m_continueDepth(0) 200 , m_next Var(-1)210 , m_nextGlobal(-1) 201 211 , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) 202 212 , m_lastOpcodeID(op_end) 203 213 { 214 emitOpcode(op_init); 204 215 codeBlock->globalData = m_globalData; 205 216 206 217 // FIXME: Move code that modifies the global object to Machine::execute. 207 218 208 m_codeBlock->numConstants = programNode->neededConstants(); 209 m_codeBlock->numVars = 1; // Allocate space for "this" 219 m_codeBlock->numParameters = 1; // Allocate space for "this" 210 220 211 221 JSGlobalObject* globalObject = scopeChain.globalObject(); … … 214 224 215 225 // Shift register indexes in generated code to elide registers allocated by intermediate stack frames. 216 m_globalVarStorageOffset = - 1 - RegisterFile::CallFrameHeaderSize- registerFile->size();226 m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->numParameters - registerFile->size(); 217 227 218 228 // Add previously defined symbols to bookkeeping. 219 m_ locals.resize(symbolTable->size());229 m_globals.resize(symbolTable->size()); 220 230 SymbolTable::iterator end = symbolTable->end(); 221 231 for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it) 222 m_locals[localsIndex(it->second.getIndex())].setIndex(it->second.getIndex() + m_globalVarStorageOffset);232 registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset); 223 233 224 234 BatchedTransitionOptimizer optimizer(globalObject); … … 227 237 if (canOptimizeNewGlobals) { 228 238 // Shift new symbols so they get stored prior to existing symbols. 229 m_next Var-= symbolTable->size();239 m_nextGlobal -= symbolTable->size(); 230 240 231 241 for (size_t i = 0; i < functionStack.size(); ++i) { … … 235 245 } 236 246 237 for (size_t i = 0; i < varStack.size(); ++i) { 247 Vector<RegisterID*, 32> newVars; 248 for (size_t i = 0; i < varStack.size(); ++i) 238 249 if (!globalObject->hasProperty(exec, varStack[i].first)) 239 emitLoad(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant), jsUndefined()); 240 } 250 newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant)); 251 252 allocateConstants(programNode->neededConstants()); 253 254 for (size_t i = 0; i < newVars.size(); ++i) 255 emitLoad(newVars[i], jsUndefined()); 241 256 } else { 242 257 for (size_t i = 0; i < functionStack.size(); ++i) { … … 252 267 globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes); 253 268 } 269 270 allocateConstants(programNode->neededConstants()); 254 271 } 255 272 } … … 265 282 , m_codeType(FunctionCode) 266 283 , m_continueDepth(0) 267 , m_nextVar(-1)268 284 , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) 269 285 , m_lastOpcodeID(op_end) 270 286 { 271 emitOpcode(op_init ialise_locals);287 emitOpcode(op_init); 272 288 codeBlock->globalData = m_globalData; 273 274 m_codeBlock->numConstants = functionBody->neededConstants();275 289 276 290 const Node::FunctionStack& functionStack = functionBody->functionStack(); … … 292 306 293 307 Vector<Identifier>& parameters = functionBody->parameters(); 294 m_nextParameter = m_nextVar - parameters.size(); // parameters are allocated prior to vars295 m_ locals.resize(localsIndex(m_nextParameter) + 1); // localsIndex of 0 => m_locals size of 1308 m_nextParameter = -RegisterFile::CallFrameHeaderSize - parameters.size() - 1; 309 m_parameters.resize(1 + parameters.size()); // reserve space for "this" 296 310 297 311 // Add "this" as a parameter … … 302 316 for (size_t i = 0; i < parameters.size(); ++i) 303 317 addParameter(parameters[i]); 318 319 allocateConstants(functionBody->neededConstants()); 304 320 } 305 321 … … 318 334 , m_lastOpcodeID(op_end) 319 335 { 320 emitOpcode(op_init ialise_locals);336 emitOpcode(op_init); 321 337 codeBlock->globalData = m_globalData; 322 323 m_codeBlock->numConstants = evalNode->neededConstants(); 324 m_codeBlock->numVars = 1; // Allocate space for "this" 325 } 326 327 CodeGenerator::~CodeGenerator() 328 { 338 m_codeBlock->numParameters = 1; // Allocate space for "this" 339 340 allocateConstants(evalNode->neededConstants()); 329 341 } 330 342 331 343 RegisterID* CodeGenerator::addParameter(const Identifier& ident) 332 344 { 333 // Parameters overwrite var declarations, but not function declarations, 334 // in the symbol table. 345 // Parameters overwrite var declarations, but not function declarations. 335 346 RegisterID* result = 0; 336 347 UString::Rep* rep = ident.ustring().rep(); 337 348 if (!m_functions.contains(rep)) { 338 349 symbolTable().set(rep, m_nextParameter); 339 m_locals[localsIndex(m_nextParameter)].setIndex(m_nextParameter); 340 result = &(m_locals[localsIndex(m_nextParameter)]); 350 RegisterID& parameter = registerFor(m_nextParameter); 351 parameter.setIndex(m_nextParameter); 352 result = ¶meter; 341 353 } 342 354 … … 348 360 } 349 361 350 RegisterID* CodeGenerator::registerFor Local(const Identifier& ident)362 RegisterID* CodeGenerator::registerFor(const Identifier& ident) 351 363 { 352 364 if (m_codeType == FunctionCode && ident == propertyNames().arguments) … … 363 375 return 0; 364 376 365 return & m_locals[localsIndex(entry.getIndex())];366 } 367 368 RegisterID* CodeGenerator:: registerForLocalConstInit(const Identifier& ident)377 return ®isterFor(entry.getIndex()); 378 } 379 380 RegisterID* CodeGenerator::constRegisterFor(const Identifier& ident) 369 381 { 370 382 if (m_codeType == EvalCode) … … 374 386 ASSERT(!entry.isNull()); 375 387 376 return & m_locals[localsIndex(entry.getIndex())];388 return ®isterFor(entry.getIndex()); 377 389 } 378 390 … … 390 402 } 391 403 404 RegisterID* CodeGenerator::newRegister() 405 { 406 m_calleeRegisters.append(m_calleeRegisters.size()); 407 m_codeBlock->numCalleeRegisters = max<int>(m_codeBlock->numCalleeRegisters, m_calleeRegisters.size()); 408 return &m_calleeRegisters.last(); 409 } 410 392 411 RegisterID* CodeGenerator::newTemporary() 393 412 { 394 413 // Reclaim free register IDs. 395 while (m_temporaries.size() && !m_temporaries.last().refCount()) 396 m_temporaries.removeLast(); 397 398 // Allocate new register ID. 399 m_temporaries.append(m_temporaries.size() + m_codeBlock->numConstants); 400 m_codeBlock->numTemporaries = max<int>(m_codeBlock->numTemporaries, m_temporaries.size()); 401 return &m_temporaries.last(); 414 while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount()) 415 m_calleeRegisters.removeLast(); 416 417 RegisterID* result = newRegister(); 418 result->setTemporary(); 419 return result; 402 420 } 403 421 404 422 RegisterID* CodeGenerator::highestUsedRegister() 405 423 { 406 while (m_temporaries.size() < static_cast<unsigned>(m_codeBlock->numTemporaries)) 407 m_temporaries.append(m_temporaries.size()); 408 return &m_temporaries.last(); 424 size_t count = m_codeBlock->numCalleeRegisters; 425 while (m_calleeRegisters.size() < count) 426 newRegister(); 427 return &m_calleeRegisters.last(); 409 428 } 410 429 … … 580 599 RegisterID* CodeGenerator::addConstant(JSValue* v) 581 600 { 582 pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_ codeBlock->constantRegisters.size());601 pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_nextConstant); 583 602 if (result.second) { 584 m_constants.append(m_codeBlock->constantRegisters.size()); 585 m_constants.last().makeConstant(); 603 RegisterID& constant = m_calleeRegisters[m_nextConstant]; 604 605 ++m_nextConstant; 606 586 607 m_codeBlock->constantRegisters.append(v); 587 ASSERT(m_codeBlock->constantRegisters.size() <= (unsigned) m_codeBlock->numConstants); 588 return &m_constants.last(); 589 } 590 591 return &m_constants[result.first->second]; 608 return &constant; 609 } 610 611 return ®isterFor(result.first->second); 592 612 } 593 613 … … 1090 1110 { 1091 1111 ASSERT(opcodeID == op_call || opcodeID == op_call_eval); 1112 ASSERT(func->refCount()); 1113 ASSERT(!base || base->refCount()); 1092 1114 1093 // Ordinarily, we might ref "func" and "base", to avoid allocating new1094 // temporaries in the same registers. In this case, though, we actually1095 // want the call frame we allocate to overlap "func" and "base", if they're1096 // not otherwise referenced. op_call will read "func" and "base" before1097 // writing out the call frame, so this is safe.1098 1099 // Reserve space for call frame.1100 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;1101 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)1102 callFrame.append(newTemporary());1103 1104 1115 // Generate code for arguments. 1105 1116 Vector<RefPtr<RegisterID>, 16> argv; … … 1110 1121 } 1111 1122 1123 // Reserve space for call frame. 1124 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; 1125 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i) 1126 callFrame.append(newTemporary()); 1127 1112 1128 emitExpressionInfo(divot, startOffset, endOffset); 1113 1129 emitOpcode(opcodeID); … … 1117 1133 instructions().append(argv[0]->index()); // argv 1118 1134 instructions().append(argv.size()); // argc 1135 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset 1119 1136 return dst; 1120 1137 } … … 1131 1148 ASSERT(func->refCount()); 1132 1149 1133 // Reserve space for prototype 1150 // Load prototype. 1151 emitExpressionInfo(divot, startOffset, endOffset); 1134 1152 RefPtr<RegisterID> funcProto = newTemporary(); 1135 1136 // Reserve space for call frame. 1137 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; 1138 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i) 1139 callFrame.append(newTemporary()); 1153 emitGetById(funcProto.get(), func, globalExec()->propertyNames().prototype); 1140 1154 1141 1155 // Generate code for arguments. … … 1147 1161 } 1148 1162 1149 emitExpressionInfo(divot, startOffset, endOffset); 1150 emitGetById(funcProto.get(), func, globalExec()->propertyNames().prototype); 1163 // Reserve space for call frame. 1164 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; 1165 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i) 1166 callFrame.append(newTemporary()); 1151 1167 1152 1168 emitExpressionInfo(divot, startOffset, endOffset); … … 1157 1173 instructions().append(argv[0]->index()); // argv 1158 1174 instructions().append(argv.size()); // argc 1159 1175 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset 1176 1160 1177 emitOpcode(op_construct_verify); 1161 1178 instructions().append(dst->index());
Note:
See TracChangeset
for help on using the changeset viewer.