Changeset 103250 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Dec 19, 2011, 11:36:37 AM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r103243 r103250 1 2011-12-16 Oliver Hunt <[email protected]> 2 3 Rolling r103120 back in with merge errors corrected. 4 5 PutByVal[Alias] unnecessarily reloads the storage buffer 6 https://bugs.webkit.org/show_bug.cgi?id=74747 7 8 Reviewed by Gavin Barraclough. 9 10 Make PutByVal use GetIndexedStorage to load the storage buffer. 11 This required switching PutByVal to a vararg node (which is 12 responsible for most of the noise in this patch). This fixes the 13 remaining portion of the kraken regression caused by the GetByVal 14 storage load elimination, and a 1-5% win on some of the sub tests of 15 the typed array benchmark at: 16 http://stepheneb.github.com/webgl-matrix-benchmarks/matrix_benchmark.html 17 18 * dfg/DFGAbstractState.cpp: 19 (JSC::DFG::AbstractState::execute): 20 * dfg/DFGByteCodeParser.cpp: 21 (JSC::DFG::ByteCodeParser::parseBlock): 22 * dfg/DFGNode.h: 23 * dfg/DFGPropagator.cpp: 24 (JSC::DFG::Propagator::propagateArithNodeFlags): 25 (JSC::DFG::Propagator::fixupNode): 26 (JSC::DFG::Propagator::byValIndexIsPure): 27 (JSC::DFG::Propagator::clobbersWorld): 28 (JSC::DFG::Propagator::getByValLoadElimination): 29 (JSC::DFG::Propagator::checkStructureLoadElimination): 30 (JSC::DFG::Propagator::getByOffsetLoadElimination): 31 (JSC::DFG::Propagator::getPropertyStorageLoadElimination): 32 (JSC::DFG::Propagator::getIndexedPropertyStorageLoadElimination): 33 (JSC::DFG::Propagator::performNodeCSE): 34 * dfg/DFGSpeculativeJIT.cpp: 35 (JSC::DFG::SpeculativeJIT::compilePutByValForByteArray): 36 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): 37 (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray): 38 * dfg/DFGSpeculativeJIT.h: 39 * dfg/DFGSpeculativeJIT32_64.cpp: 40 (JSC::DFG::SpeculativeJIT::compile): 41 * dfg/DFGSpeculativeJIT64.cpp: 42 (JSC::DFG::SpeculativeJIT::compile): 43 1 44 2011-12-15 Geoffrey Garen <[email protected]> 2 45 … … 333 376 (WTF::lowerNibbleToASCIIHexDigit): 334 377 (WTF::upperNibbleToASCIIHexDigit): 335 336 2011-12-16 Gavin Barraclough <[email protected]>337 338 Reverted r103120, this breaks v8 on ARMv7 DFG.339 340 * dfg/DFGAbstractState.cpp:341 (JSC::DFG::AbstractState::execute):342 * dfg/DFGByteCodeParser.cpp:343 (JSC::DFG::ByteCodeParser::parseBlock):344 * dfg/DFGNode.h:345 * dfg/DFGPropagator.cpp:346 (JSC::DFG::Propagator::propagateArithNodeFlags):347 (JSC::DFG::Propagator::fixupNode):348 (JSC::DFG::Propagator::byValIsPure):349 (JSC::DFG::Propagator::clobbersWorld):350 (JSC::DFG::Propagator::getByValLoadElimination):351 (JSC::DFG::Propagator::checkStructureLoadElimination):352 (JSC::DFG::Propagator::getByOffsetLoadElimination):353 (JSC::DFG::Propagator::getPropertyStorageLoadElimination):354 (JSC::DFG::Propagator::getIndexedPropertyStorageLoadElimination):355 (JSC::DFG::Propagator::performNodeCSE):356 * dfg/DFGSpeculativeJIT.cpp:357 (JSC::DFG::SpeculativeJIT::compilePutByValForByteArray):358 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):359 (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):360 * dfg/DFGSpeculativeJIT.h:361 * dfg/DFGSpeculativeJIT32_64.cpp:362 (JSC::DFG::SpeculativeJIT::compile):363 * dfg/DFGSpeculativeJIT64.cpp:364 (JSC::DFG::SpeculativeJIT::compile):365 378 366 379 2011-12-16 Filip Pizlo <[email protected]> -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r103218 r103250 494 494 case PutByVal: 495 495 case PutByValAlias: { 496 PredictedType indexPrediction = m_graph[node.child2()].prediction(); 496 NodeIndex child1 = m_graph.m_varArgChildren[node.firstChild()]; 497 NodeIndex child2 = m_graph.m_varArgChildren[node.firstChild() + 1]; 498 NodeIndex child3 = m_graph.m_varArgChildren[node.firstChild() + 2]; 499 PredictedType indexPrediction = m_graph[child2].prediction(); 497 500 if (!(indexPrediction & PredictInt32) && indexPrediction) { 498 501 clobberStructures(nodeIndex); … … 500 503 break; 501 504 } 502 if (m_graph[ node.child1()].shouldSpeculateByteArray()) {503 forNode( node.child1()).filter(PredictByteArray);504 forNode( node.child2()).filter(PredictInt32);505 forNode( node.child3()).filter(PredictNumber);506 break; 507 } 508 509 if (m_graph[ node.child1()].shouldSpeculateInt8Array()) {510 forNode( node.child1()).filter(PredictInt8Array);511 forNode( node.child2()).filter(PredictInt32);512 forNode( node.child3()).filter(PredictNumber);513 break; 514 } 515 if (m_graph[ node.child1()].shouldSpeculateInt16Array()) {516 forNode( node.child1()).filter(PredictInt16Array);517 forNode( node.child2()).filter(PredictInt32);518 forNode( node.child3()).filter(PredictNumber);519 break; 520 } 521 if (m_graph[ node.child1()].shouldSpeculateInt32Array()) {522 forNode( node.child1()).filter(PredictInt32Array);523 forNode( node.child2()).filter(PredictInt32);524 forNode( node.child3()).filter(PredictNumber);525 break; 526 } 527 if (m_graph[ node.child1()].shouldSpeculateUint8Array()) {528 forNode( node.child1()).filter(PredictUint8Array);529 forNode( node.child2()).filter(PredictInt32);530 forNode( node.child3()).filter(PredictNumber);531 break; 532 } 533 if (m_graph[ node.child1()].shouldSpeculateUint16Array()) {534 forNode( node.child1()).filter(PredictUint16Array);535 forNode( node.child2()).filter(PredictInt32);536 forNode( node.child3()).filter(PredictNumber);537 break; 538 } 539 if (m_graph[ node.child1()].shouldSpeculateUint32Array()) {540 forNode( node.child1()).filter(PredictUint32Array);541 forNode( node.child2()).filter(PredictInt32);542 forNode( node.child3()).filter(PredictNumber);543 break; 544 } 545 if (m_graph[ node.child1()].shouldSpeculateFloat32Array()) {546 forNode( node.child1()).filter(PredictFloat32Array);547 forNode( node.child2()).filter(PredictInt32);548 forNode( node.child3()).filter(PredictNumber);549 break; 550 } 551 if (m_graph[ node.child1()].shouldSpeculateFloat64Array()) {552 forNode( node.child1()).filter(PredictFloat64Array);553 forNode( node.child2()).filter(PredictInt32);554 forNode( node.child3()).filter(PredictNumber);555 break; 556 } 557 558 forNode( node.child1()).filter(PredictArray);559 forNode( node.child2()).filter(PredictInt32);505 if (m_graph[child1].shouldSpeculateByteArray()) { 506 forNode(child1).filter(PredictByteArray); 507 forNode(child2).filter(PredictInt32); 508 forNode(child3).filter(PredictNumber); 509 break; 510 } 511 512 if (m_graph[child1].shouldSpeculateInt8Array()) { 513 forNode(child1).filter(PredictInt8Array); 514 forNode(child2).filter(PredictInt32); 515 forNode(child3).filter(PredictNumber); 516 break; 517 } 518 if (m_graph[child1].shouldSpeculateInt16Array()) { 519 forNode(child1).filter(PredictInt16Array); 520 forNode(child2).filter(PredictInt32); 521 forNode(child3).filter(PredictNumber); 522 break; 523 } 524 if (m_graph[child1].shouldSpeculateInt32Array()) { 525 forNode(child1).filter(PredictInt32Array); 526 forNode(child2).filter(PredictInt32); 527 forNode(child3).filter(PredictNumber); 528 break; 529 } 530 if (m_graph[child1].shouldSpeculateUint8Array()) { 531 forNode(child1).filter(PredictUint8Array); 532 forNode(child2).filter(PredictInt32); 533 forNode(child3).filter(PredictNumber); 534 break; 535 } 536 if (m_graph[child1].shouldSpeculateUint16Array()) { 537 forNode(child1).filter(PredictUint16Array); 538 forNode(child2).filter(PredictInt32); 539 forNode(child3).filter(PredictNumber); 540 break; 541 } 542 if (m_graph[child1].shouldSpeculateUint32Array()) { 543 forNode(child1).filter(PredictUint32Array); 544 forNode(child2).filter(PredictInt32); 545 forNode(child3).filter(PredictNumber); 546 break; 547 } 548 if (m_graph[child1].shouldSpeculateFloat32Array()) { 549 forNode(child1).filter(PredictFloat32Array); 550 forNode(child2).filter(PredictInt32); 551 forNode(child3).filter(PredictNumber); 552 break; 553 } 554 if (m_graph[child1].shouldSpeculateFloat64Array()) { 555 forNode(child1).filter(PredictFloat64Array); 556 forNode(child2).filter(PredictInt32); 557 forNode(child3).filter(PredictNumber); 558 break; 559 } 560 561 forNode(child1).filter(PredictArray); 562 forNode(child2).filter(PredictInt32); 560 563 break; 561 564 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r103138 r103250 1663 1663 NodeIndex property = get(currentInstruction[2].u.operand); 1664 1664 NodeIndex value = get(currentInstruction[3].u.operand); 1665 1666 addToGraph(PutByVal, base, property, value); 1665 NodeIndex propertyStorage = addToGraph(GetIndexedPropertyStorage, base, property); 1666 1667 addVarArgChild(base); 1668 addVarArgChild(property); 1669 addVarArgChild(value); 1670 addVarArgChild(propertyStorage); 1671 1672 addToGraph(Node::VarArg, PutByVal, OpInfo(0), OpInfo(0)); 1667 1673 1668 1674 NEXT_OPCODE(op_put_by_val); -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r103218 r103250 227 227 /* this must be the directly subsequent property put. */\ 228 228 macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ 229 macro(PutByVal, NodeMustGenerate | NodeClobbersWorld ) \230 macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld ) \229 macro(PutByVal, NodeMustGenerate | NodeClobbersWorld | NodeHasVarArgs) \ 230 macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld | NodeHasVarArgs) \ 231 231 macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ 232 232 macro(PutById, NodeMustGenerate | NodeClobbersWorld) \ … … 235 235 macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \ 236 236 macro(GetPropertyStorage, NodeResultStorage) \ 237 macro(GetIndexedPropertyStorage, Node MustGenerate | NodeResultStorage) \237 macro(GetIndexedPropertyStorage, NodeResultStorage) \ 238 238 macro(GetByOffset, NodeResultJS) \ 239 239 macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \ -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r103218 r103250 193 193 194 194 case PutByVal: { 195 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); 196 changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber); 197 changed |= m_graph[node.child3()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); 195 NodeIndex base = m_graph.m_varArgChildren[node.firstChild()]; 196 NodeIndex property = m_graph.m_varArgChildren[node.firstChild() + 1]; 197 NodeIndex value = m_graph.m_varArgChildren[node.firstChild() + 2]; 198 changed |= m_graph[base].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); 199 changed |= m_graph[property].mergeArithNodeFlags(flags | NodeUsedAsNumber); 200 changed |= m_graph[value].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); 198 201 break; 199 202 } … … 931 934 break; 932 935 } 936 case PutByVal: 937 case PutByValAlias: { 938 NodeIndex storage = m_graph.m_varArgChildren[node.firstChild() + 3]; 939 if (m_graph[storage].op == Nop) 940 node.children.variable.numChildren = 3; 941 break; 942 } 943 933 944 case GetByVal: 934 945 case StringCharAt: … … 1086 1097 } 1087 1098 1088 bool byValI sPure(Node& node)1089 { 1090 PredictedType prediction = m_graph[node.child2()].prediction();1099 bool byValIndexIsPure(Node& node) 1100 { 1101 PredictedType prediction = node.prediction(); 1091 1102 return (prediction & PredictInt32) || !prediction; 1092 1103 } … … 1110 1121 return !logicalNotIsPure(node); 1111 1122 case GetByVal: 1112 return !byValI sPure(node);1123 return !byValIndexIsPure(m_graph[node.child2()]); 1113 1124 default: 1114 1125 ASSERT_NOT_REACHED(); … … 1180 1191 switch (node.op) { 1181 1192 case GetByVal: 1182 if (!byValI sPure(node))1193 if (!byValIndexIsPure(m_graph[node.child2()])) 1183 1194 return NoNode; 1184 1195 if (node.child1() == child1 && canonicalize(node.child2()) == canonicalize(child2)) … … 1186 1197 break; 1187 1198 case PutByVal: 1188 case PutByValAlias: 1189 if (!byValIsPure(node)) 1199 case PutByValAlias: { 1200 1201 NodeIndex base = m_graph.m_varArgChildren[node.firstChild()]; 1202 NodeIndex property = m_graph.m_varArgChildren[node.firstChild() + 1]; 1203 if (!byValIndexIsPure(m_graph[property])) 1190 1204 return NoNode; 1191 if ( node.child1() == child1 && canonicalize(node.child2()) == canonicalize(child2))1192 return node.child3();1205 if (base == child1 && canonicalize(property) == canonicalize(child2)) 1206 return m_graph.m_varArgChildren[node.firstChild() + 2]; 1193 1207 // We must assume that the PutByVal will clobber the location we're getting from. 1194 1208 // FIXME: We can do better; if we know that the PutByVal is accessing an array of a 1195 1209 // different type than the GetByVal, then we know that they won't clobber each other. 1196 1210 return NoNode; 1211 } 1197 1212 case PutStructure: 1198 1213 case PutByOffset: … … 1250 1265 1251 1266 case PutByVal: 1252 case PutByValAlias: 1253 if (byValIsPure(node)) { 1267 case PutByValAlias: { 1268 NodeIndex property = m_graph.m_varArgChildren[node.firstChild() + 1]; 1269 if (byValIndexIsPure(m_graph[property])) { 1254 1270 // If PutByVal speculates that it's accessing an array with an 1255 1271 // integer index, then it's impossible for it to cause a structure … … 1258 1274 } 1259 1275 return false; 1260 1276 } 1277 1261 1278 default: 1262 1279 if (clobbersWorld(index)) … … 1293 1310 1294 1311 case PutByVal: 1295 case PutByValAlias: 1296 if (byValIsPure(node)) { 1312 case PutByValAlias: { 1313 NodeIndex property = m_graph.m_varArgChildren[node.firstChild() + 1]; 1314 if (byValIndexIsPure(m_graph[property])) { 1297 1315 // If PutByVal speculates that it's accessing an array with an 1298 1316 // integer index, then it's impossible for it to cause a structure … … 1301 1319 } 1302 1320 return NoNode; 1303 1321 } 1322 1304 1323 default: 1305 1324 if (clobbersWorld(index)) … … 1329 1348 1330 1349 case PutByVal: 1331 case PutByValAlias: 1332 if (byValIsPure(node)) { 1350 case PutByValAlias: { 1351 NodeIndex property = m_graph.m_varArgChildren[node.firstChild() + 1]; 1352 if (byValIndexIsPure(m_graph[property])) { 1333 1353 // If PutByVal speculates that it's accessing an array with an 1334 1354 // integer index, then it's impossible for it to cause a structure … … 1337 1357 } 1338 1358 return NoNode; 1339 1359 } 1360 1340 1361 default: 1341 1362 if (clobbersWorld(index)) … … 1347 1368 } 1348 1369 1349 NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1 , bool hasIntegerIndexPrediction)1370 NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1) 1350 1371 { 1351 1372 NodeIndex start = startIndexForChildren(child1); … … 1356 1377 PredictedType basePrediction = m_graph[node.child2()].prediction(); 1357 1378 bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction); 1358 if (node.child1() == child1 && hasIntegerIndexPrediction ==nodeHasIntegerIndexPrediction)1379 if (node.child1() == child1 && nodeHasIntegerIndexPrediction) 1359 1380 return index; 1360 1381 break; … … 1371 1392 break; 1372 1393 1373 case PutByVal: 1374 if (isFixedIndexedStorageObjectPrediction(m_graph[node.child1()].prediction()) && byValIsPure(node)) 1394 case PutByVal: { 1395 NodeIndex base = m_graph.m_varArgChildren[node.firstChild()]; 1396 NodeIndex property = m_graph.m_varArgChildren[node.firstChild() + 1]; 1397 if (isFixedIndexedStorageObjectPrediction(m_graph[base].prediction()) && byValIndexIsPure(m_graph[property])) 1375 1398 break; 1376 1399 return NoNode; 1400 } 1377 1401 1378 1402 default: … … 1555 1579 1556 1580 case GetByVal: 1557 if (byValI sPure(node))1581 if (byValIndexIsPure(m_graph[node.child2()])) 1558 1582 setReplacement(getByValLoadElimination(node.child1(), node.child2())); 1559 1583 break; 1560 1584 1561 case PutByVal: 1562 if (byValIsPure(node) && getByValLoadElimination(node.child1(), node.child2()) != NoNode) 1585 case PutByVal: { 1586 NodeIndex base = m_graph.m_varArgChildren[node.firstChild()]; 1587 NodeIndex property = m_graph.m_varArgChildren[node.firstChild() + 1]; 1588 if (byValIndexIsPure(m_graph[property]) && getByValLoadElimination(base, property) != NoNode) 1563 1589 node.op = PutByValAlias; 1564 1590 break; 1591 } 1565 1592 1566 1593 case CheckStructure: … … 1577 1604 PredictedType basePrediction = m_graph[node.child2()].prediction(); 1578 1605 bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction); 1579 setReplacement(getIndexedPropertyStorageLoadElimination(node.child1(), nodeHasIntegerIndexPrediction)); 1606 if (nodeHasIntegerIndexPrediction) 1607 setReplacement(getIndexedPropertyStorageLoadElimination(node.child1())); 1580 1608 break; 1581 1609 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r103218 r103250 1554 1554 } 1555 1555 1556 void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node) 1557 { 1558 NodeIndex baseIndex = node.child1(); 1559 NodeIndex valueIndex = node.child3(); 1560 1561 if (!isByteArrayPrediction(m_state.forNode(baseIndex).m_type)) 1562 speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); 1556 void SpeculativeJIT::compilePutByValForByteArray(Node& node) 1557 { 1558 NodeIndex baseIndex = m_jit.graph().m_varArgChildren[node.firstChild()]; 1559 NodeIndex propertyIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1]; 1560 NodeIndex valueIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 2]; 1561 NodeIndex storageIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 3]; 1562 1563 if (!isByteArrayPrediction(m_state.forNode(baseIndex).m_type)) { 1564 SpeculateCellOperand base(this, baseIndex); 1565 speculationCheck(BadType, JSValueSource::unboxedCell(base.gpr()), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); 1566 } 1563 1567 GPRTemporary value; 1564 1568 GPRReg valueGPR; … … 1607 1611 valueGPR = gpr; 1608 1612 } 1609 ASSERT_UNUSED(valueGPR, valueGPR != property); 1610 ASSERT(valueGPR != base); 1611 GPRTemporary storage(this); 1613 StorageOperand storage(this, storageIndex); 1614 SpeculateIntegerOperand property(this, propertyIndex); 1612 1615 GPRReg storageReg = storage.gpr(); 1613 ASSERT(valueGPR != storageReg); 1614 m_jit.loadPtr(MacroAssembler::Address(base, JSByteArray::offsetOfStorage()), storageReg); 1615 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())); 1616 m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne, ByteArray::offsetOfData())); 1616 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property.gpr(), MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())); 1617 m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property.gpr(), MacroAssembler::TimesOne, ByteArray::offsetOfData())); 1617 1618 outOfBounds.link(&m_jit); 1618 1619 noResult(m_compileIndex); … … 1711 1712 } 1712 1713 1713 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness) 1714 { 1715 NodeIndex baseIndex = node.child1(); 1716 NodeIndex valueIndex = node.child3(); 1717 1718 if (speculationRequirements != NoTypedArrayTypeSpecCheck) 1719 speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); 1714 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness) 1715 { 1716 NodeIndex baseIndex = m_jit.graph().m_varArgChildren[node.firstChild()]; 1717 NodeIndex propertyIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1]; 1718 NodeIndex valueIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 2]; 1719 NodeIndex storageIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 3]; 1720 1721 if (speculationRequirements != NoTypedArrayTypeSpecCheck) { 1722 SpeculateCellOperand base(this, baseIndex); 1723 speculationCheck(BadType, JSValueSource::unboxedCell(base.gpr()), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base.gpr()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); 1724 } 1725 1726 StorageOperand storage(this, storageIndex); 1727 GPRReg storageReg = storage.gpr(); 1728 SpeculateIntegerOperand property(this, propertyIndex); 1729 GPRReg propertyReg = property.gpr(); 1730 MacroAssembler::Jump outOfBounds; 1731 if (speculationRequirements != NoTypedArrayTypeSpecCheck || speculationRequirements != NoTypedArraySpecCheck) { 1732 SpeculateCellOperand base(this, baseIndex); 1733 if (speculationRequirements != NoTypedArrayTypeSpecCheck) 1734 speculationCheck(BadType, JSValueSource::unboxedCell(base.gpr()), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); 1735 if (speculationRequirements != NoTypedArraySpecCheck) 1736 outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(base.gpr(), descriptor.m_lengthOffset)); 1737 } 1720 1738 GPRTemporary value; 1721 1739 GPRReg valueGPR; … … 1759 1777 valueGPR = gpr; 1760 1778 } 1761 ASSERT_UNUSED(valueGPR, valueGPR != property);1762 ASSERT(valueGPR != base);1763 GPRTemporary storage(this);1764 GPRReg storageReg = storage.gpr();1765 ASSERT(valueGPR != storageReg);1766 m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);1767 MacroAssembler::Jump outOfBounds;1768 if (speculationRequirements != NoTypedArraySpecCheck)1769 outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));1770 1779 1771 1780 switch (elementSize) { 1772 1781 case 1: 1773 m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property , MacroAssembler::TimesOne));1782 m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne)); 1774 1783 break; 1775 1784 case 2: 1776 m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property , MacroAssembler::TimesTwo));1785 m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo)); 1777 1786 break; 1778 1787 case 4: 1779 m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property , MacroAssembler::TimesFour));1788 m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour)); 1780 1789 break; 1781 1790 default: … … 1832 1841 } 1833 1842 1834 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements) 1835 { 1836 NodeIndex baseIndex = node.child1(); 1837 NodeIndex valueIndex = node.child3(); 1843 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements) 1844 { 1845 NodeIndex baseIndex = m_jit.graph().m_varArgChildren[node.firstChild()]; 1846 NodeIndex propertyIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1]; 1847 NodeIndex valueIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 2]; 1848 NodeIndex storageIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 3]; 1838 1849 1839 1850 SpeculateDoubleOperand valueOp(this, valueIndex); 1840 1841 if (speculationRequirements != NoTypedArrayTypeSpecCheck) 1842 speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); 1843 1844 GPRTemporary result(this); 1845 1846 GPRTemporary storage(this); 1851 SpeculateStrictInt32Operand property(this, propertyIndex); 1852 StorageOperand storage(this, storageIndex); 1847 1853 GPRReg storageReg = storage.gpr(); 1848 1849 m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);1854 GPRReg propertyReg = property.gpr(); 1855 1850 1856 MacroAssembler::Jump outOfBounds; 1851 if (speculationRequirements != NoTypedArraySpecCheck) 1852 outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset)); 1857 if (speculationRequirements != NoTypedArrayTypeSpecCheck || speculationRequirements != NoTypedArraySpecCheck) { 1858 SpeculateCellOperand base(this, baseIndex); 1859 if (speculationRequirements != NoTypedArrayTypeSpecCheck) 1860 speculationCheck(BadType, JSValueSource::unboxedCell(base.gpr()), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); 1861 if (speculationRequirements != NoTypedArraySpecCheck) 1862 outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(base.gpr(), descriptor.m_lengthOffset)); 1863 } 1864 1865 1853 1866 1854 1867 switch (elementSize) { … … 1857 1870 m_jit.moveDouble(valueOp.fpr(), scratch.fpr()); 1858 1871 m_jit.convertDoubleToFloat(valueOp.fpr(), scratch.fpr()); 1859 m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, property , MacroAssembler::TimesFour));1872 m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour)); 1860 1873 break; 1861 1874 } 1862 1875 case 8: 1863 m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, property , MacroAssembler::TimesEight));1876 m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight)); 1864 1877 break; 1865 1878 default: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r103138 r103250 1971 1971 void compileUInt32ToNumber(Node&); 1972 1972 void compileGetByValOnByteArray(Node&); 1973 void compilePutByValForByteArray( GPRReg base, GPRReg property,Node&);1973 void compilePutByValForByteArray(Node&); 1974 1974 void compileArithMul(Node&); 1975 1975 void compileArithMod(Node&); … … 1987 1987 void compileGetIndexedPropertyStorage(Node&); 1988 1988 void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness); 1989 void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property,Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);1989 void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness); 1990 1990 void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements); 1991 void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property,Node&, size_t elementSize, TypedArraySpeculationRequirements);1991 void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements); 1992 1992 1993 1993 // It is acceptable to have structure be equal to scratch, so long as you're fine -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r103218 r103250 2694 2694 2695 2695 case PutByVal: { 2696 PredictedType basePrediction = at(node.child2()).prediction(); 2696 NodeIndex child1 = m_jit.graph().m_varArgChildren[node.firstChild()]; 2697 NodeIndex child2 = m_jit.graph().m_varArgChildren[node.firstChild() + 1]; 2698 NodeIndex child3 = m_jit.graph().m_varArgChildren[node.firstChild() + 2]; 2699 NodeIndex child4 = m_jit.graph().m_varArgChildren[node.firstChild() + 3]; 2700 2701 PredictedType basePrediction = at(child2).prediction(); 2697 2702 if (!(basePrediction & PredictInt32) && basePrediction) { 2698 SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.2699 JSValueOperand property(this, node.child2());2700 JSValueOperand value(this, node.child3());2703 SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right. 2704 JSValueOperand property(this, child2); 2705 JSValueOperand value(this, child3); 2701 2706 GPRReg baseGPR = base.gpr(); 2702 2707 GPRReg propertyTagGPR = property.tagGPR(); … … 2712 2717 } 2713 2718 2714 SpeculateCellOperand base(this, node.child1()); 2715 SpeculateStrictInt32Operand property(this, node.child2()); 2716 if (at(node.child1()).shouldSpeculateByteArray()) { 2717 compilePutByValForByteArray(base.gpr(), property.gpr(), node); 2719 if (at(child1).shouldSpeculateByteArray()) { 2720 compilePutByValForByteArray(node); 2718 2721 break; 2719 2722 } 2720 if (at(node.child1()).shouldSpeculateByteArray()) { 2721 compilePutByValForByteArray(base.gpr(), property.gpr(), node); 2722 break; 2723 } 2724 2725 if (at(node.child1()).shouldSpeculateInt8Array()) { 2726 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); 2723 2724 if (at(child1).shouldSpeculateInt8Array()) { 2725 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); 2727 2726 if (!m_compileOkay) 2728 2727 return; … … 2730 2729 } 2731 2730 2732 if (at( node.child1()).shouldSpeculateInt16Array()) {2733 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);2731 if (at(child1).shouldSpeculateInt16Array()) { 2732 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); 2734 2733 if (!m_compileOkay) 2735 2734 return; … … 2737 2736 } 2738 2737 2739 if (at( node.child1()).shouldSpeculateInt32Array()) {2740 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);2738 if (at(child1).shouldSpeculateInt32Array()) { 2739 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); 2741 2740 if (!m_compileOkay) 2742 2741 return; … … 2744 2743 } 2745 2744 2746 if (at( node.child1()).shouldSpeculateUint8Array()) {2747 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);2745 if (at(child1).shouldSpeculateUint8Array()) { 2746 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray); 2748 2747 if (!m_compileOkay) 2749 2748 return; … … 2751 2750 } 2752 2751 2753 if (at( node.child1()).shouldSpeculateUint16Array()) {2754 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);2752 if (at(child1).shouldSpeculateUint16Array()) { 2753 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray); 2755 2754 if (!m_compileOkay) 2756 2755 return; … … 2758 2757 } 2759 2758 2760 if (at( node.child1()).shouldSpeculateUint32Array()) {2761 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);2759 if (at(child1).shouldSpeculateUint32Array()) { 2760 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray); 2762 2761 if (!m_compileOkay) 2763 2762 return; … … 2765 2764 } 2766 2765 2767 if (at( node.child1()).shouldSpeculateFloat32Array()) {2768 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);2766 if (at(child1).shouldSpeculateFloat32Array()) { 2767 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks); 2769 2768 if (!m_compileOkay) 2770 2769 return; … … 2772 2771 } 2773 2772 2774 if (at( node.child1()).shouldSpeculateFloat64Array()) {2775 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);2773 if (at(child1).shouldSpeculateFloat64Array()) { 2774 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks); 2776 2775 if (!m_compileOkay) 2777 2776 return; … … 2779 2778 } 2780 2779 2781 JSValueOperand value(this, node.child3()); 2782 GPRTemporary scratch(this); 2780 SpeculateCellOperand base(this, child1); 2781 SpeculateStrictInt32Operand property(this, child2); 2782 JSValueOperand value(this, child3); 2783 2783 2784 2784 // Map base, property & value into registers, allocate a scratch register. … … 2787 2787 GPRReg valueTagReg = value.tagGPR(); 2788 2788 GPRReg valuePayloadReg = value.payloadGPR(); 2789 GPRReg scratchReg = scratch.gpr();2790 2789 2791 2790 if (!m_compileOkay) 2792 2791 return; 2793 2794 writeBarrier(baseReg, valueTagReg, node.child3(), WriteBarrierForPropertyAccess, scratchReg); 2792 2793 { 2794 GPRTemporary scratch(this); 2795 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratch.gpr()); 2796 } 2795 2797 2796 2798 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 2797 2799 // If we have predicted the base to be type array, we can skip the check. 2798 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 2799 speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2800 if (!isArrayPrediction(m_state.forNode(child1).m_type)) 2801 speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2802 2803 StorageOperand storage(this, child4); 2804 GPRReg storageReg = storage.gpr(); 2800 2805 2801 2806 base.use(); 2802 2807 property.use(); 2803 2808 value.use(); 2809 storage.use(); 2804 2810 2805 2811 MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); 2806 2812 2807 2813 // Code to handle put beyond array bounds. 2808 silentSpillAllRegisters( scratchReg);2814 silentSpillAllRegisters(InvalidGPRReg); 2809 2815 callOperation(operationPutByValBeyondArrayBounds, baseReg, propertyReg, valueTagReg, valuePayloadReg); 2810 silentFillAllRegisters( scratchReg);2816 silentFillAllRegisters(InvalidGPRReg); 2811 2817 JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump(); 2812 2818 2813 2819 withinArrayBounds.link(&m_jit); 2814 2815 // Get the array storage.2816 GPRReg storageReg = scratchReg;2817 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);2818 2820 2819 2821 // Check if we're writing to a hole; if so increment m_numValuesInVector. … … 2841 2843 2842 2844 case PutByValAlias: { 2843 SpeculateCellOperand base(this, node.child1()); 2844 SpeculateStrictInt32Operand property(this, node.child2()); 2845 2846 if (at(node.child1()).shouldSpeculateByteArray()) { 2847 compilePutByValForByteArray(base.gpr(), property.gpr(), node); 2845 NodeIndex child1 = m_jit.graph().m_varArgChildren[node.firstChild()]; 2846 NodeIndex child2 = m_jit.graph().m_varArgChildren[node.firstChild() + 1]; 2847 NodeIndex child3 = m_jit.graph().m_varArgChildren[node.firstChild() + 2]; 2848 NodeIndex child4 = m_jit.graph().m_varArgChildren[node.firstChild() + 3]; 2849 2850 if (at(child1).shouldSpeculateByteArray()) { 2851 compilePutByValForByteArray(node); 2848 2852 break; 2849 2853 } 2850 2854 2851 if (at( node.child1()).shouldSpeculateInt8Array()) {2852 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray);2855 if (at(child1).shouldSpeculateInt8Array()) { 2856 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray); 2853 2857 if (!m_compileOkay) 2854 2858 return; … … 2856 2860 } 2857 2861 2858 if (at( node.child1()).shouldSpeculateInt16Array()) {2859 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(int16_t), NoTypedArraySpecCheck, SignedTypedArray);2862 if (at(child1).shouldSpeculateInt16Array()) { 2863 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), NoTypedArraySpecCheck, SignedTypedArray); 2860 2864 if (!m_compileOkay) 2861 2865 return; … … 2863 2867 } 2864 2868 2865 if (at( node.child1()).shouldSpeculateInt32Array()) {2866 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(int32_t), NoTypedArraySpecCheck, SignedTypedArray);2869 if (at(child1).shouldSpeculateInt32Array()) { 2870 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), NoTypedArraySpecCheck, SignedTypedArray); 2867 2871 if (!m_compileOkay) 2868 2872 return; … … 2870 2874 } 2871 2875 2872 if (at( node.child1()).shouldSpeculateUint8Array()) {2873 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray);2876 if (at(child1).shouldSpeculateUint8Array()) { 2877 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray); 2874 2878 if (!m_compileOkay) 2875 2879 return; … … 2877 2881 } 2878 2882 2879 if (at( node.child1()).shouldSpeculateUint16Array()) {2880 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray);2883 if (at(child1).shouldSpeculateUint16Array()) { 2884 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray); 2881 2885 if (!m_compileOkay) 2882 2886 return; … … 2884 2888 } 2885 2889 2886 if (at( node.child1()).shouldSpeculateUint32Array()) {2887 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(uint32_t), NoTypedArraySpecCheck, UnsignedTypedArray);2890 if (at(child1).shouldSpeculateUint32Array()) { 2891 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), NoTypedArraySpecCheck, UnsignedTypedArray); 2888 2892 if (!m_compileOkay) 2889 2893 return; … … 2891 2895 } 2892 2896 2893 if (at( node.child1()).shouldSpeculateFloat32Array()) {2894 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(float), NoTypedArraySpecCheck);2897 if (at(child1).shouldSpeculateFloat32Array()) { 2898 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), NoTypedArraySpecCheck); 2895 2899 if (!m_compileOkay) 2896 2900 return; … … 2898 2902 } 2899 2903 2900 if (at( node.child1()).shouldSpeculateFloat64Array()) {2901 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(double), NoTypedArraySpecCheck);2904 if (at(child1).shouldSpeculateFloat64Array()) { 2905 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), NoTypedArraySpecCheck); 2902 2906 if (!m_compileOkay) 2903 2907 return; 2904 2908 break; 2905 2909 } 2906 2907 JSValueOperand value(this, node.child3()); 2908 GPRTemporary scratch(this, base); 2909 2910 GPRReg baseReg = base.gpr(); 2911 GPRReg scratchReg = scratch.gpr(); 2912 2913 writeBarrier(baseReg, value.tagGPR(), node.child3(), WriteBarrierForPropertyAccess, scratchReg); 2914 2915 // Get the array storage. 2916 GPRReg storageReg = scratchReg; 2917 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); 2918 2910 2911 JSValueOperand value(this, child3); 2912 { 2913 SpeculateCellOperand base(this, child1); 2914 GPRTemporary scratch(this, base); 2915 GPRReg baseReg = base.gpr(); 2916 GPRReg scratchReg = scratch.gpr(); 2917 writeBarrier(baseReg, value.tagGPR(), child3, WriteBarrierForPropertyAccess, scratchReg); 2918 } 2919 2920 SpeculateStrictInt32Operand property(this, child2); 2921 StorageOperand storage(this, child4); 2919 2922 // Store the value to the array. 2920 2923 GPRReg propertyReg = property.gpr(); 2921 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storage Reg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));2922 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storage Reg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));2924 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storage.gpr(), propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2925 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storage.gpr(), propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 2923 2926 2924 2927 noResult(m_compileIndex); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r103218 r103250 2598 2598 break; 2599 2599 } 2600 2600 ASSERT(node.child3() != NoNode); 2601 2601 if (at(node.child1()).prediction() == PredictString) { 2602 2602 compileGetByValOnString(node); … … 2696 2696 2697 2697 case PutByVal: { 2698 PredictedType basePrediction = at(node.child2()).prediction(); 2698 NodeIndex child1 = m_jit.graph().m_varArgChildren[node.firstChild()]; 2699 NodeIndex child2 = m_jit.graph().m_varArgChildren[node.firstChild() + 1]; 2700 NodeIndex child3 = m_jit.graph().m_varArgChildren[node.firstChild() + 2]; 2701 2702 PredictedType basePrediction = at(child2).prediction(); 2699 2703 if (!(basePrediction & PredictInt32) && basePrediction) { 2700 JSValueOperand arg1(this, node.child1());2701 JSValueOperand arg2(this, node.child2());2702 JSValueOperand arg3(this, node.child3());2704 JSValueOperand arg1(this, child1); 2705 JSValueOperand arg2(this, child2); 2706 JSValueOperand arg3(this, child3); 2703 2707 GPRReg arg1GPR = arg1.gpr(); 2704 2708 GPRReg arg2GPR = arg2.gpr(); … … 2712 2716 } 2713 2717 2714 SpeculateCellOperand base(this, node.child1()); 2715 SpeculateStrictInt32Operand property(this, node.child2()); 2716 if (at(node.child1()).shouldSpeculateByteArray()) { 2717 compilePutByValForByteArray(base.gpr(), property.gpr(), node); 2718 if (at(child1).shouldSpeculateByteArray()) { 2719 compilePutByValForByteArray(node); 2718 2720 break; 2719 2721 } 2720 2722 2721 if (at( node.child1()).shouldSpeculateInt8Array()) {2722 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);2723 if (at(child1).shouldSpeculateInt8Array()) { 2724 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); 2723 2725 if (!m_compileOkay) 2724 2726 return; … … 2726 2728 } 2727 2729 2728 if (at( node.child1()).shouldSpeculateInt16Array()) {2729 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);2730 if (at(child1).shouldSpeculateInt16Array()) { 2731 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); 2730 2732 if (!m_compileOkay) 2731 2733 return; … … 2733 2735 } 2734 2736 2735 if (at( node.child1()).shouldSpeculateInt32Array()) {2736 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);2737 if (at(child1).shouldSpeculateInt32Array()) { 2738 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); 2737 2739 if (!m_compileOkay) 2738 2740 return; … … 2740 2742 } 2741 2743 2742 if (at( node.child1()).shouldSpeculateUint8Array()) {2743 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);2744 if (at(child1).shouldSpeculateUint8Array()) { 2745 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray); 2744 2746 if (!m_compileOkay) 2745 2747 return; … … 2747 2749 } 2748 2750 2749 if (at( node.child1()).shouldSpeculateUint16Array()) {2750 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);2751 if (at(child1).shouldSpeculateUint16Array()) { 2752 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray); 2751 2753 if (!m_compileOkay) 2752 2754 return; … … 2754 2756 } 2755 2757 2756 if (at( node.child1()).shouldSpeculateUint32Array()) {2757 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);2758 if (at(child1).shouldSpeculateUint32Array()) { 2759 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray); 2758 2760 if (!m_compileOkay) 2759 2761 return; … … 2761 2763 } 2762 2764 2763 if (at( node.child1()).shouldSpeculateFloat32Array()) {2764 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);2765 if (at(child1).shouldSpeculateFloat32Array()) { 2766 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks); 2765 2767 if (!m_compileOkay) 2766 2768 return; … … 2768 2770 } 2769 2771 2770 if (at( node.child1()).shouldSpeculateFloat64Array()) {2771 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);2772 if (at(child1).shouldSpeculateFloat64Array()) { 2773 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(child1).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks); 2772 2774 if (!m_compileOkay) 2773 2775 return; 2774 2776 break; 2775 2777 } 2776 2777 JSValueOperand value(this, node.child3()); 2778 2779 SpeculateCellOperand base(this, child1); 2780 SpeculateStrictInt32Operand property(this, child2); 2781 JSValueOperand value(this, child3); 2782 NodeIndex child4 = m_jit.graph().m_varArgChildren[node.firstChild() + 3]; 2783 StorageOperand storage(this, child4); 2778 2784 GPRTemporary scratch(this); 2779 2785 2780 2786 // Map base, property & value into registers, allocate a scratch register. 2781 2787 GPRReg baseReg = base.gpr(); 2782 2788 GPRReg propertyReg = property.gpr(); 2783 2789 GPRReg valueReg = value.gpr(); 2790 GPRReg storageReg = storage.gpr(); 2784 2791 GPRReg scratchReg = scratch.gpr(); 2785 2792 … … 2787 2794 return; 2788 2795 2789 writeBarrier(baseReg, value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);2796 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg); 2790 2797 2791 2798 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 2792 2799 // If we have predicted the base to be type array, we can skip the check. 2793 if (!isArrayPrediction(m_state.forNode( node.child1()).m_type))2794 speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));2800 if (!isArrayPrediction(m_state.forNode(child1).m_type)) 2801 speculationCheck(BadType, JSValueRegs(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2795 2802 2796 2803 base.use(); 2797 2804 property.use(); 2798 2805 value.use(); 2799 2806 storage.use(); 2807 2800 2808 MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); 2801 2809 … … 2808 2816 withinArrayBounds.link(&m_jit); 2809 2817 2810 // Get the array storage.2811 GPRReg storageReg = scratchReg;2812 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);2813 2814 2818 // Check if we're writing to a hole; if so increment m_numValuesInVector. 2815 2819 MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); … … 2835 2839 2836 2840 case PutByValAlias: { 2837 PredictedType basePrediction = at(node.child2()).prediction(); 2841 NodeIndex child1 = m_jit.graph().m_varArgChildren[node.firstChild()]; 2842 NodeIndex child2 = m_jit.graph().m_varArgChildren[node.firstChild() + 1]; 2843 NodeIndex child3 = m_jit.graph().m_varArgChildren[node.firstChild() + 2]; 2844 NodeIndex child4 = m_jit.graph().m_varArgChildren[node.firstChild() + 3]; 2845 2846 PredictedType basePrediction = at(child2).prediction(); 2838 2847 ASSERT_UNUSED(basePrediction, (basePrediction & PredictInt32) || !basePrediction); 2839 2848 2840 SpeculateCellOperand base(this, node.child1()); 2841 SpeculateStrictInt32Operand property(this, node.child2()); 2842 if (at(node.child1()).shouldSpeculateByteArray()) { 2843 compilePutByValForByteArray(base.gpr(), property.gpr(), node); 2849 if (at(child1).shouldSpeculateByteArray()) { 2850 compilePutByValForByteArray(node); 2844 2851 break; 2845 2852 } 2846 2853 2847 if (at( node.child1()).shouldSpeculateInt8Array()) {2848 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray);2854 if (at(child1).shouldSpeculateInt8Array()) { 2855 compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray); 2849 2856 if (!m_compileOkay) 2850 2857 return; 2851 2858 break; 2852 2859 } 2853 2854 if (at( node.child1()).shouldSpeculateInt16Array()) {2855 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(int16_t), NoTypedArraySpecCheck, SignedTypedArray);2860 2861 if (at(child1).shouldSpeculateInt16Array()) { 2862 compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), NoTypedArraySpecCheck, SignedTypedArray); 2856 2863 if (!m_compileOkay) 2857 2864 return; 2858 2865 break; 2859 2866 } 2860 2861 if (at( node.child1()).shouldSpeculateInt32Array()) {2862 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(int32_t), NoTypedArraySpecCheck, SignedTypedArray);2867 2868 if (at(child1).shouldSpeculateInt32Array()) { 2869 compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), NoTypedArraySpecCheck, SignedTypedArray); 2863 2870 if (!m_compileOkay) 2864 2871 return; 2865 2872 break; 2866 2873 } 2867 2868 if (at( node.child1()).shouldSpeculateUint8Array()) {2869 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray);2874 2875 if (at(child1).shouldSpeculateUint8Array()) { 2876 compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray); 2870 2877 if (!m_compileOkay) 2871 2878 return; 2872 2879 break; 2873 2880 } 2874 2875 if (at( node.child1()).shouldSpeculateUint16Array()) {2876 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray);2881 2882 if (at(child1).shouldSpeculateUint16Array()) { 2883 compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray); 2877 2884 if (!m_compileOkay) 2878 2885 return; 2879 2886 break; 2880 2887 } 2881 2882 if (at( node.child1()).shouldSpeculateUint32Array()) {2883 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(uint32_t), NoTypedArraySpecCheck, UnsignedTypedArray);2888 2889 if (at(child1).shouldSpeculateUint32Array()) { 2890 compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), NoTypedArraySpecCheck, UnsignedTypedArray); 2884 2891 if (!m_compileOkay) 2885 2892 return; 2886 2893 break; 2887 2894 } 2888 2889 if (at( node.child1()).shouldSpeculateFloat32Array()) {2890 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(float), NoTypedArraySpecCheck);2895 2896 if (at(child1).shouldSpeculateFloat32Array()) { 2897 compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), NoTypedArraySpecCheck); 2891 2898 if (!m_compileOkay) 2892 2899 return; 2893 2900 break; 2894 2901 } 2895 2896 if (at( node.child1()).shouldSpeculateFloat64Array()) {2897 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(),node, sizeof(double), NoTypedArraySpecCheck);2902 2903 if (at(child1).shouldSpeculateFloat64Array()) { 2904 compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), NoTypedArraySpecCheck); 2898 2905 if (!m_compileOkay) 2899 2906 return; … … 2901 2908 } 2902 2909 2903 JSValueOperand value(this, node.child3()); 2904 GPRTemporary scratch(this); 2905 2906 GPRReg baseReg = base.gpr(); 2907 GPRReg scratchReg = scratch.gpr(); 2908 2909 writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg); 2910 2910 SpeculateCellOperand base(this, child1); 2911 SpeculateStrictInt32Operand property(this, child2); 2912 JSValueOperand value(this, child3); 2913 2914 { 2915 GPRTemporary scratch(this); 2916 GPRReg scratchReg = scratch.gpr(); 2917 writeBarrier(base.gpr(), value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg); 2918 } 2919 StorageOperand storage(this, child4); 2911 2920 // Get the array storage. 2912 GPRReg storageReg = scratchReg; 2913 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); 2921 GPRReg storageReg = storage.gpr(); 2914 2922 2915 2923 // Store the value to the array.
Note:
See TracChangeset
for help on using the changeset viewer.