Changeset 171660 in webkit for trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
- Timestamp:
- Jul 27, 2014, 4:14:40 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r171648 r171660 133 133 } 134 134 135 case PutStructure: { 136 if (m_state.forNode(node->child1()).m_structure.onlyStructure() != node->transition()->next) 137 break; 138 139 node->convertToPhantom(); 140 eliminated = true; 141 break; 142 } 143 135 144 case CheckFunction: { 136 145 if (m_state.forNode(node->child1()).value() != node->function()->value()) … … 155 164 156 165 case MultiGetByOffset: { 157 Edge childEdge = node->child1();158 Node* child = childEdge.node();166 Edge baseEdge = node->child1(); 167 Node* base = baseEdge.node(); 159 168 MultiGetByOffsetData& data = node->multiGetByOffsetData(); 160 169 161 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 162 if (!structure) 163 break; 164 165 for (unsigned i = data.variants.size(); i--;) { 166 const GetByIdVariant& variant = data.variants[i]; 167 if (!variant.structureSet().contains(structure)) 170 // First prune the variants, then check if the MultiGetByOffset can be 171 // strength-reduced to a GetByOffset. 172 173 AbstractValue baseValue = m_state.forNode(base); 174 175 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 176 eliminated = true; // Don't allow the default constant folder to do things to this. 177 178 for (unsigned i = 0; i < data.variants.size(); ++i) { 179 GetByIdVariant& variant = data.variants[i]; 180 variant.structureSet().filter(baseValue); 181 if (variant.structureSet().isEmpty()) { 182 data.variants[i--] = data.variants.last(); 183 data.variants.removeLast(); 184 } 185 } 186 187 if (data.variants.size() != 1) 188 break; 189 190 emitGetByOffset( 191 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber); 192 break; 193 } 194 195 case MultiPutByOffset: { 196 Edge baseEdge = node->child1(); 197 Node* base = baseEdge.node(); 198 MultiPutByOffsetData& data = node->multiPutByOffsetData(); 199 200 AbstractValue baseValue = m_state.forNode(base); 201 202 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 203 eliminated = true; // Don't allow the default constant folder to do things to this. 204 205 206 for (unsigned i = 0; i < data.variants.size(); ++i) { 207 PutByIdVariant& variant = data.variants[i]; 208 variant.oldStructure().filter(baseValue); 209 210 if (variant.oldStructure().isEmpty()) { 211 data.variants[i--] = data.variants.last(); 212 data.variants.removeLast(); 168 213 continue; 214 } 169 215 170 if (variant.alternateBase()) 171 break; 172 173 emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 174 eliminated = true; 175 break; 176 } 177 break; 178 } 179 180 case MultiPutByOffset: { 181 Edge childEdge = node->child1(); 182 Node* child = childEdge.node(); 183 MultiPutByOffsetData& data = node->multiPutByOffsetData(); 184 185 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 186 if (!structure) 187 break; 188 189 for (unsigned i = data.variants.size(); i--;) { 190 const PutByIdVariant& variant = data.variants[i]; 191 if (variant.oldStructure() != structure) 192 continue; 193 194 emitPutByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 195 eliminated = true; 196 break; 197 } 216 if (variant.kind() == PutByIdVariant::Transition 217 && variant.oldStructure().onlyStructure() == variant.newStructure()) { 218 variant = PutByIdVariant::replace( 219 variant.oldStructure(), 220 variant.offset()); 221 } 222 } 223 224 if (data.variants.size() != 1) 225 break; 226 227 emitPutByOffset( 228 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber); 198 229 break; 199 230 } … … 205 236 unsigned identifierNumber = node->identifierNumber(); 206 237 207 if (childEdge.useKind() != CellUse) 208 break; 209 210 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 211 if (!structure) 212 break; 213 238 AbstractValue baseValue = m_state.forNode(child); 239 240 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 241 eliminated = true; // Don't allow the default constant folder to do things to this. 242 243 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered() 244 || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell))) 245 break; 246 214 247 GetByIdStatus status = GetByIdStatus::computeFor( 215 vm(), structure, m_graph.identifiers()[identifierNumber]); 216 217 if (!status.isSimple() || status.numVariants() != 1 || 218 !status[0].constantChecks().isEmpty() || status[0].alternateBase()) { 219 // FIXME: We could handle prototype cases. 220 // https://bugs.webkit.org/show_bug.cgi?id=110386 221 break; 222 } 223 224 emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber); 225 eliminated = true; 248 vm(), baseValue.m_structure.set(), m_graph.identifiers()[identifierNumber]); 249 if (!status.isSimple()) 250 break; 251 252 for (unsigned i = status.numVariants(); i--;) { 253 if (!status[i].constantChecks().isEmpty() 254 || status[i].alternateBase()) { 255 // FIXME: We could handle prototype cases. 256 // https://bugs.webkit.org/show_bug.cgi?id=110386 257 break; 258 } 259 } 260 261 if (status.numVariants() == 1) { 262 emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber); 263 break; 264 } 265 266 if (!isFTL(m_graph.m_plan.mode)) 267 break; 268 269 MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add(); 270 data->variants = status.variants(); 271 data->identifierNumber = identifierNumber; 272 node->convertToMultiGetByOffset(data); 226 273 break; 227 274 } 228 275 229 276 case PutById: 230 case PutByIdDirect: { 277 case PutByIdDirect: 278 case PutByIdFlush: { 231 279 NodeOrigin origin = node->origin; 232 280 Edge childEdge = node->child1(); … … 236 284 ASSERT(childEdge.useKind() == CellUse); 237 285 238 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 239 if (!structure) 286 AbstractValue baseValue = m_state.forNode(child); 287 288 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 289 eliminated = true; // Don't allow the default constant folder to do things to this. 290 291 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()) 240 292 break; 241 293 … … 243 295 vm(), 244 296 m_graph.globalObjectFor(origin.semantic), 245 structure,297 baseValue.m_structure.set(), 246 298 m_graph.identifiers()[identifierNumber], 247 299 node->op() == PutByIdDirect); … … 249 301 if (!status.isSimple()) 250 302 break; 251 if (status.numVariants() != 1) 252 break; 253 254 emitPutByOffset(indexInBlock, node, structure, status[0], identifierNumber); 255 eliminated = true; 303 304 for (unsigned i = status.numVariants(); i--;) 305 addChecks(origin, indexInBlock, status[i].constantChecks()); 306 307 if (status.numVariants() == 1) { 308 emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber); 309 break; 310 } 311 312 if (!isFTL(m_graph.m_plan.mode)) 313 break; 314 315 MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add(); 316 data->variants = status.variants(); 317 data->identifierNumber = identifierNumber; 318 node->convertToMultiPutByOffset(data); 256 319 break; 257 320 } … … 344 407 } 345 408 346 void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber)409 void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber) 347 410 { 348 411 NodeOrigin origin = node->origin; … … 350 413 Node* child = childEdge.node(); 351 414 352 bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell; 353 354 ASSERT(!variant.alternateBase()); 355 ASSERT_UNUSED(structure, variant.structureSet().contains(structure)); 356 357 // Now before we do anything else, push the CFA forward over the GetById 358 // and make sure we signal to the loop that it should continue and not 359 // do any eliminations. 360 m_interpreter.execute(indexInBlock); 361 362 if (needsCellCheck) { 363 m_insertionSet.insertNode( 364 indexInBlock, SpecNone, Phantom, origin, childEdge); 365 } 415 addBaseCheck(indexInBlock, node, baseValue, variant.structureSet()); 366 416 367 417 if (variant.specificValue()) { … … 370 420 } 371 421 372 childEdge.setUseKind(KnownCellUse); 422 if (variant.alternateBase()) { 423 child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase()); 424 childEdge = Edge(child, KnownCellUse); 425 } else 426 childEdge.setUseKind(KnownCellUse); 373 427 374 428 Edge propertyStorage; … … 389 443 } 390 444 391 void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber)445 void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber) 392 446 { 393 447 NodeOrigin origin = node->origin; 394 448 Edge childEdge = node->child1(); 395 Node* child = childEdge.node(); 396 397 ASSERT(variant.oldStructure() == structure); 398 399 bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell; 400 401 // Now before we do anything else, push the CFA forward over the PutById 402 // and make sure we signal to the loop that it should continue and not 403 // do any eliminations. 404 m_interpreter.execute(indexInBlock); 405 406 if (needsCellCheck) { 407 m_insertionSet.insertNode( 408 indexInBlock, SpecNone, Phantom, origin, childEdge); 409 } 449 450 addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure()); 410 451 411 452 childEdge.setUseKind(KnownCellUse); … … 413 454 Transition* transition = 0; 414 455 if (variant.kind() == PutByIdVariant::Transition) { 415 transition = m_graph.m_transitions.add(structure, variant.newStructure()); 416 417 for (unsigned i = 0; i < variant.constantChecks().size(); ++i) { 418 addStructureTransitionCheck( 419 origin, indexInBlock, 420 variant.constantChecks()[i].constant(), 421 variant.constantChecks()[i].structure()); 422 } 456 transition = m_graph.m_transitions.add( 457 variant.oldStructureForTransition(), variant.newStructure()); 423 458 } 424 459 … … 427 462 if (isInlineOffset(variant.offset())) 428 463 propertyStorage = childEdge; 429 else if ( 430 variant.kind() == PutByIdVariant::Replace 431 || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) { 464 else if (!variant.reallocatesStorage()) { 432 465 propertyStorage = Edge(m_insertionSet.insertNode( 433 466 indexInBlock, SpecNone, GetButterfly, origin, childEdge)); 434 } else if (! structure->outOfLineCapacity()) {467 } else if (!variant.oldStructureForTransition()->outOfLineCapacity()) { 435 468 ASSERT(variant.newStructure()->outOfLineCapacity()); 436 469 ASSERT(!isInlineOffset(variant.offset())); … … 441 474 propertyStorage = Edge(allocatePropertyStorage); 442 475 } else { 443 ASSERT( structure->outOfLineCapacity());444 ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity());476 ASSERT(variant.oldStructureForTransition()->outOfLineCapacity()); 477 ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity()); 445 478 ASSERT(!isInlineOffset(variant.offset())); 446 479 … … 470 503 m_graph.m_storageAccessData.append(storageAccessData); 471 504 } 505 506 void addBaseCheck( 507 unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const StructureSet& set) 508 { 509 if (!baseValue.m_structure.isSubsetOf(set)) { 510 // Arises when we prune MultiGetByOffset. We could have a 511 // MultiGetByOffset with a single variant that checks for structure S, 512 // and the input has structures S and T, for example. 513 m_insertionSet.insertNode( 514 indexInBlock, SpecNone, CheckStructure, node->origin, 515 OpInfo(m_graph.addStructureSet(set)), node->child1()); 516 return; 517 } 518 519 if (baseValue.m_type & ~SpecCell) { 520 m_insertionSet.insertNode( 521 indexInBlock, SpecNone, Phantom, node->origin, node->child1()); 522 } 523 } 524 525 void addChecks( 526 NodeOrigin origin, unsigned indexInBlock, const ConstantStructureCheckVector& checks) 527 { 528 for (unsigned i = 0; i < checks.size(); ++i) { 529 addStructureTransitionCheck( 530 origin, indexInBlock, checks[i].constant(), checks[i].structure()); 531 } 532 } 472 533 473 534 void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
Note:
See TracChangeset
for help on using the changeset viewer.