Changeset 171648 in webkit for trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
- Timestamp:
- Jul 26, 2014, 12:06:44 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r171641 r171648 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 144 135 case CheckFunction: { 145 136 if (m_state.forNode(node->child1()).value() != node->function()->value()) … … 164 155 165 156 case MultiGetByOffset: { 166 Edge baseEdge = node->child1();167 Node* base = baseEdge.node();157 Edge childEdge = node->child1(); 158 Node* child = childEdge.node(); 168 159 MultiGetByOffsetData& data = node->multiGetByOffsetData(); 169 160 170 // First prune the variants, then check if the MultiGetByOffset can be171 // 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 }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)) 168 continue; 169 170 if (variant.alternateBase()) 171 break; 172 173 emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 174 eliminated = true; 175 break; 185 176 } 186 187 if (data.variants.size() != 1)188 break;189 190 emitGetByOffset(191 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);192 177 break; 193 178 } 194 179 195 180 case MultiPutByOffset: { 196 Edge baseEdge = node->child1();197 Node* base = baseEdge.node();181 Edge childEdge = node->child1(); 182 Node* child = childEdge.node(); 198 183 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); 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; 209 193 210 if (variant.oldStructure().isEmpty()) { 211 data.variants[i--] = data.variants.last(); 212 data.variants.removeLast(); 213 continue; 214 } 215 216 if (variant.kind() == PutByIdVariant::Transition 217 && variant.oldStructure().onlyStructure() == variant.newStructure()) { 218 variant = PutByIdVariant::replace( 219 variant.oldStructure(), 220 variant.offset()); 221 } 194 emitPutByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 195 eliminated = true; 196 break; 222 197 } 223 224 if (data.variants.size() != 1)225 break;226 227 emitPutByOffset(228 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);229 198 break; 230 199 } … … 236 205 unsigned identifierNumber = node->identifierNumber(); 237 206 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 207 if (childEdge.useKind() != CellUse) 208 break; 209 210 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 211 if (!structure) 212 break; 213 247 214 GetByIdStatus status = GetByIdStatus::computeFor( 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 } 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; 259 222 } 260 223 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); 224 emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber); 225 eliminated = true; 273 226 break; 274 227 } 275 228 276 229 case PutById: 277 case PutByIdDirect: 278 case PutByIdFlush: { 230 case PutByIdDirect: { 279 231 NodeOrigin origin = node->origin; 280 232 Edge childEdge = node->child1(); … … 284 236 ASSERT(childEdge.useKind() == CellUse); 285 237 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()) 238 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 239 if (!structure) 292 240 break; 293 241 … … 295 243 vm(), 296 244 m_graph.globalObjectFor(origin.semantic), 297 baseValue.m_structure.set(),245 structure, 298 246 m_graph.identifiers()[identifierNumber], 299 247 node->op() == PutByIdDirect); … … 301 249 if (!status.isSimple()) 302 250 break; 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); 251 if (status.numVariants() != 1) 252 break; 253 254 emitPutByOffset(indexInBlock, node, structure, status[0], identifierNumber); 255 eliminated = true; 319 256 break; 320 257 } … … 407 344 } 408 345 409 void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber)346 void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber) 410 347 { 411 348 NodeOrigin origin = node->origin; … … 413 350 Node* child = childEdge.node(); 414 351 415 addBaseCheck(indexInBlock, node, baseValue, variant.structureSet()); 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 } 416 366 417 367 if (variant.specificValue()) { … … 420 370 } 421 371 422 if (variant.alternateBase()) { 423 child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase()); 424 childEdge = Edge(child, KnownCellUse); 425 } else 426 childEdge.setUseKind(KnownCellUse); 372 childEdge.setUseKind(KnownCellUse); 427 373 428 374 Edge propertyStorage; … … 443 389 } 444 390 445 void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber)391 void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber) 446 392 { 447 393 NodeOrigin origin = node->origin; 448 394 Edge childEdge = node->child1(); 449 450 addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure()); 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 } 451 410 452 411 childEdge.setUseKind(KnownCellUse); … … 454 413 Transition* transition = 0; 455 414 if (variant.kind() == PutByIdVariant::Transition) { 456 transition = m_graph.m_transitions.add( 457 variant.oldStructureForTransition(), variant.newStructure()); 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 } 458 423 } 459 424 … … 462 427 if (isInlineOffset(variant.offset())) 463 428 propertyStorage = childEdge; 464 else if (!variant.reallocatesStorage()) { 429 else if ( 430 variant.kind() == PutByIdVariant::Replace 431 || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) { 465 432 propertyStorage = Edge(m_insertionSet.insertNode( 466 433 indexInBlock, SpecNone, GetButterfly, origin, childEdge)); 467 } else if (! variant.oldStructureForTransition()->outOfLineCapacity()) {434 } else if (!structure->outOfLineCapacity()) { 468 435 ASSERT(variant.newStructure()->outOfLineCapacity()); 469 436 ASSERT(!isInlineOffset(variant.offset())); … … 474 441 propertyStorage = Edge(allocatePropertyStorage); 475 442 } else { 476 ASSERT( variant.oldStructureForTransition()->outOfLineCapacity());477 ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity());443 ASSERT(structure->outOfLineCapacity()); 444 ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity()); 478 445 ASSERT(!isInlineOffset(variant.offset())); 479 446 … … 503 470 m_graph.m_storageAccessData.append(storageAccessData); 504 471 } 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 a511 // 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 }533 472 534 473 void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
Note:
See TracChangeset
for help on using the changeset viewer.