Changeset 134151 in webkit
- Timestamp:
- Nov 9, 2012, 9:54:11 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r134134 r134151 1 2012-11-09 Filip Pizlo <fpizlo@apple.com> 2 3 If the DFG ArrayMode says that an access is on an OriginalArray, then the checks should always enforce this 4 https://bugs.webkit.org/show_bug.cgi?id=101720 5 6 Reviewed by Mark Hahnenberg. 7 8 Previously, "original" arrays was just a hint that we could find the structure 9 of the array if we needed to even if the array profile didn't have it due to 10 polymorphism. Now, "original" arrays are a property that is actually checked: 11 if an array access has ArrayMode::arrayClass() == Array::OriginalArray, then we 12 can be sure that the code performing the access is dealing with not just a 13 JSArray, but a JSArray that has no named properties, no indexed accessors, and 14 the ArrayPrototype as its prototype. This will be useful for optimizations that 15 are being done as part of https://bugs.webkit.org/show_bug.cgi?id=101720. 16 17 * dfg/DFGAbstractState.cpp: 18 (JSC::DFG::AbstractState::execute): 19 * dfg/DFGArrayMode.cpp: 20 (JSC::DFG::ArrayMode::originalArrayStructure): 21 (DFG): 22 (JSC::DFG::ArrayMode::alreadyChecked): 23 * dfg/DFGArrayMode.h: 24 (JSC): 25 (DFG): 26 (JSC::DFG::ArrayMode::withProfile): 27 (ArrayMode): 28 (JSC::DFG::ArrayMode::benefitsFromOriginalArray): 29 * dfg/DFGConstantFoldingPhase.cpp: 30 (JSC::DFG::ConstantFoldingPhase::foldConstants): 31 * dfg/DFGFixupPhase.cpp: 32 (JSC::DFG::FixupPhase::checkArray): 33 * dfg/DFGSpeculativeJIT.cpp: 34 (JSC::DFG::SpeculativeJIT::jumpSlowForUnwantedArrayMode): 35 (JSC::DFG::SpeculativeJIT::checkArray): 36 (JSC::DFG::SpeculativeJIT::compileGetByValOnString): 37 (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): 38 (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray): 39 (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray): 40 (JSC::DFG::SpeculativeJIT::compileGetByValOnArguments): 41 (JSC::DFG::SpeculativeJIT::compileGetArgumentsLength): 42 1 43 2012-11-09 Filip Pizlo <fpizlo@apple.com> 2 44 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r133990 r134151 1453 1453 break; 1454 1454 case CheckArray: { 1455 if (node.arrayMode().alreadyChecked( forNode(node.child1()))) {1455 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) { 1456 1456 m_foundConstants = true; 1457 1457 node.setCanExit(false); … … 1509 1509 } 1510 1510 case Arrayify: { 1511 if (node.arrayMode().alreadyChecked( forNode(node.child1()))) {1511 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) { 1512 1512 m_foundConstants = true; 1513 1513 node.setCanExit(false); -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
r133953 r134151 30 30 31 31 #include "DFGAbstractValue.h" 32 #include "DFGGraph.h" 32 33 33 34 namespace JSC { namespace DFG { … … 201 202 } 202 203 203 bool ArrayMode::alreadyChecked(AbstractValue& value, IndexingType shape) const 204 { 205 if (isJSArray()) { 204 Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& codeOrigin) const 205 { 206 if (!isJSArrayWithOriginalStructure()) 207 return 0; 208 209 JSGlobalObject* globalObject = graph.globalObjectFor(codeOrigin); 210 211 switch (type()) { 212 case Array::Int32: 213 return globalObject->originalArrayStructureForIndexingType(ArrayWithInt32); 214 case Array::Double: 215 return globalObject->originalArrayStructureForIndexingType(ArrayWithDouble); 216 case Array::Contiguous: 217 return globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous); 218 case Array::ArrayStorage: 219 return globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage); 220 default: 221 CRASH(); 222 return 0; 223 } 224 } 225 226 Structure* ArrayMode::originalArrayStructure(Graph& graph, Node& node) const 227 { 228 return originalArrayStructure(graph, node.codeOrigin); 229 } 230 231 bool ArrayMode::alreadyChecked(Graph& graph, Node& node, AbstractValue& value, IndexingType shape) const 232 { 233 switch (arrayClass()) { 234 case Array::OriginalArray: 235 return value.m_currentKnownStructure.hasSingleton() 236 && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape 237 && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray) 238 && graph.globalObjectFor(node.codeOrigin)->isOriginalArrayStructure(value.m_currentKnownStructure.singleton()); 239 240 case Array::Array: 206 241 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray))) 207 242 return true; … … 209 244 && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape 210 245 && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); 211 } 212 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray))) 213 return true; 214 return value.m_currentKnownStructure.hasSingleton() 215 && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape; 216 } 217 218 bool ArrayMode::alreadyChecked(AbstractValue& value) const 246 247 default: 248 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray))) 249 return true; 250 return value.m_currentKnownStructure.hasSingleton() 251 && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape; 252 } 253 } 254 255 bool ArrayMode::alreadyChecked(Graph& graph, Node& node, AbstractValue& value) const 219 256 { 220 257 switch (type()) { … … 229 266 230 267 case Array::Int32: 231 return alreadyChecked( value, Int32Shape);268 return alreadyChecked(graph, node, value, Int32Shape); 232 269 233 270 case Array::Double: 234 return alreadyChecked( value, DoubleShape);271 return alreadyChecked(graph, node, value, DoubleShape); 235 272 236 273 case Array::Contiguous: 237 return alreadyChecked( value, ContiguousShape);274 return alreadyChecked(graph, node, value, ContiguousShape); 238 275 239 276 case Array::ArrayStorage: 240 return alreadyChecked( value, ArrayStorageShape);277 return alreadyChecked(graph, node, value, ArrayStorageShape); 241 278 242 279 case Array::SlowPutArrayStorage: 243 if (isJSArray()) { 280 switch (arrayClass()) { 281 case Array::OriginalArray: 282 CRASH(); 283 return false; 284 285 case Array::Array: 244 286 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) 245 287 return true; … … 247 289 && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) 248 290 && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); 291 292 default: 293 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) 294 return true; 295 return value.m_currentKnownStructure.hasSingleton() 296 && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()); 249 297 } 250 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))251 return true;252 return value.m_currentKnownStructure.hasSingleton()253 && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType());254 298 255 299 case Array::Arguments: -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h
r133953 r134151 34 34 #include "SpeculatedType.h" 35 35 36 namespace JSC { namespace DFG { 37 36 namespace JSC { 37 38 struct CodeOrigin; 39 40 namespace DFG { 41 42 class Graph; 38 43 struct AbstractValue; 44 struct Node; 39 45 40 46 // Use a namespace + enum instead of enum alone to avoid the namespace collision … … 162 168 163 169 if (isJSArray()) { 164 if (profile->usesOriginalArrayStructures() )170 if (profile->usesOriginalArrayStructures() && benefitsFromOriginalArray()) 165 171 myArrayClass = Array::OriginalArray; 166 172 else … … 184 190 ArrayMode refine(SpeculatedType base, SpeculatedType index, SpeculatedType value = SpecNone) const; 185 191 186 bool alreadyChecked( AbstractValue&) const;192 bool alreadyChecked(Graph&, Node&, AbstractValue&) const; 187 193 188 194 const char* toString() const; … … 303 309 } 304 310 } 311 312 bool benefitsFromOriginalArray() const 313 { 314 switch (type()) { 315 case Array::Int32: 316 case Array::Double: 317 case Array::Contiguous: 318 case Array::ArrayStorage: 319 return true; 320 default: 321 return false; 322 } 323 } 324 325 // Returns 0 if this is not OriginalArray. 326 Structure* originalArrayStructure(Graph&, const CodeOrigin&) const; 327 Structure* originalArrayStructure(Graph&, Node&) const; 305 328 306 329 bool benefitsFromStructureCheck() const … … 376 399 } 377 400 378 bool alreadyChecked( AbstractValue&, IndexingType shape) const;401 bool alreadyChecked(Graph&, Node&, AbstractValue&, IndexingType shape) const; 379 402 380 403 union { -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r132759 r134151 117 117 case CheckArray: 118 118 case Arrayify: { 119 if (!node.arrayMode().alreadyChecked(m_ state.forNode(node.child1())))119 if (!node.arrayMode().alreadyChecked(m_graph, node, m_state.forNode(node.child1()))) 120 120 break; 121 121 ASSERT(node.refCount() == 1); -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r133956 r134151 425 425 m_graph.ref(array); 426 426 427 Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin); 428 427 429 if (arrayMode.doesConversion()) { 428 430 if (index != NoNode) 429 431 m_graph.ref(index); 430 431 Structure* structure = 0;432 if (arrayMode.isJSArrayWithOriginalStructure()) {433 JSGlobalObject* globalObject = m_graph.baselineCodeBlockFor(codeOrigin)->globalObject();434 switch (arrayMode.type()) {435 case Array::Int32:436 structure = globalObject->originalArrayStructureForIndexingType(ArrayWithInt32);437 break;438 case Array::Double:439 structure = globalObject->originalArrayStructureForIndexingType(ArrayWithDouble);440 break;441 case Array::Contiguous:442 structure = globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous);443 break;444 case Array::ArrayStorage:445 structure = globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage);446 break;447 default:448 break;449 }450 }451 432 452 433 if (structure) { … … 464 445 } 465 446 } else { 466 Node checkArray(CheckArray, codeOrigin, OpInfo(arrayMode.asWord()), array); 467 checkArray.ref(); 468 NodeIndex checkArrayIndex = m_graph.size(); 469 m_graph.append(checkArray); 470 m_insertionSet.append(m_indexInBlock, checkArrayIndex); 447 if (structure) { 448 Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(structure)), array); 449 checkStructure.ref(); 450 NodeIndex checkStructureIndex = m_graph.size(); 451 m_graph.append(checkStructure); 452 m_insertionSet.append(m_indexInBlock, checkStructureIndex); 453 } else { 454 Node checkArray(CheckArray, codeOrigin, OpInfo(arrayMode.asWord()), array); 455 checkArray.ref(); 456 NodeIndex checkArrayIndex = m_graph.size(); 457 m_graph.append(checkArray); 458 m_insertionSet.append(m_indexInBlock, checkArrayIndex); 459 } 471 460 } 472 461 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r133956 r134151 362 362 JITCompiler::Jump SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, IndexingType shape, bool invert) 363 363 { 364 if (arrayMode.isJSArray()) { 364 switch (arrayMode.arrayClass()) { 365 case Array::OriginalArray: { 366 CRASH(); 367 JITCompiler::Jump result; // I already know that VC++ takes unkindly to the expression "return Jump()", so I'm doing it this way in anticipation of someone eventually using VC++ to compile the DFG. 368 return result; 369 } 370 371 case Array::Array: 365 372 m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR); 366 373 return m_jit.branch32( 367 374 invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape)); 368 } 369 m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR); 370 return m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape)); 375 376 default: 377 m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR); 378 return m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape)); 379 } 371 380 } 372 381 … … 387 396 case Array::ArrayStorage: 388 397 case Array::SlowPutArrayStorage: { 398 ASSERT(!arrayMode.isJSArrayWithOriginalStructure()); 399 389 400 if (arrayMode.isJSArray()) { 390 401 if (arrayMode.isSlowPut()) { 391 402 if (invert) { 392 JITCompiler::Jump slow = 393 m_jit.branchTest32( 394 MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)); 403 JITCompiler::Jump slow = m_jit.branchTest32( 404 MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)); 395 405 m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR); 396 406 m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR); … … 450 460 const TypedArrayDescriptor* result = typedArrayDescriptor(node.arrayMode()); 451 461 452 if (node.arrayMode().alreadyChecked(m_ state.forNode(node.child1()))) {462 if (node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))) { 453 463 noResult(m_compileIndex); 454 464 return; … … 1960 1970 GPRReg storageReg = storage.gpr(); 1961 1971 1962 ASSERT(ArrayMode(Array::String).alreadyChecked(m_ state.forNode(node.child1())));1972 ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))); 1963 1973 1964 1974 // unsigned comparison so we can filter out negative indices and indices that are too large … … 2369 2379 GPRReg resultReg = result.gpr(); 2370 2380 2371 ASSERT(node.arrayMode().alreadyChecked(m_ state.forNode(node.child1())));2381 ASSERT(node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))); 2372 2382 2373 2383 speculationCheck( … … 2519 2529 GPRReg storageReg = storage.gpr(); 2520 2530 2521 ASSERT(node.arrayMode().alreadyChecked(m_ state.forNode(node.child1())));2531 ASSERT(node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))); 2522 2532 2523 2533 FPRTemporary result(this); … … 2556 2566 SpeculateDoubleOperand valueOp(this, valueUse); 2557 2567 2558 ASSERT_UNUSED(baseUse, node.arrayMode().alreadyChecked(m_ state.forNode(baseUse)));2568 ASSERT_UNUSED(baseUse, node.arrayMode().alreadyChecked(m_jit.graph(), m_jit.graph()[m_compileIndex], m_state.forNode(baseUse))); 2559 2569 2560 2570 GPRTemporary result(this); … … 3379 3389 return; 3380 3390 3381 ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_ state.forNode(node.child1())));3391 ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))); 3382 3392 3383 3393 // Two really lame checks. … … 3436 3446 return; 3437 3447 3438 ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_ state.forNode(node.child1())));3448 ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))); 3439 3449 3440 3450 speculationCheck(
Note:
See TracChangeset
for help on using the changeset viewer.