DFGAbstractState.cpp 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828
  1. /*
  2. * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "DFGAbstractState.h"
  27. #if ENABLE(DFG_JIT)
  28. #include "CodeBlock.h"
  29. #include "DFGBasicBlock.h"
  30. #include "GetByIdStatus.h"
  31. #include "Operations.h"
  32. #include "PutByIdStatus.h"
  33. #include "StringObject.h"
  34. namespace JSC { namespace DFG {
  35. AbstractState::AbstractState(Graph& graph)
  36. : m_codeBlock(graph.m_codeBlock)
  37. , m_graph(graph)
  38. , m_variables(m_codeBlock->numParameters(), graph.m_localVars)
  39. , m_block(0)
  40. {
  41. }
  42. AbstractState::~AbstractState() { }
  43. void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
  44. {
  45. ASSERT(!m_block);
  46. ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
  47. ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
  48. ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
  49. for (size_t i = 0; i < basicBlock->size(); i++)
  50. forNode(basicBlock->at(i)).clear();
  51. m_variables = basicBlock->valuesAtHead;
  52. m_haveStructures = false;
  53. for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
  54. if (m_variables.argument(i).m_currentKnownStructure.isNeitherClearNorTop()) {
  55. m_haveStructures = true;
  56. break;
  57. }
  58. }
  59. for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
  60. if (m_variables.local(i).m_currentKnownStructure.isNeitherClearNorTop()) {
  61. m_haveStructures = true;
  62. break;
  63. }
  64. }
  65. basicBlock->cfaShouldRevisit = false;
  66. basicBlock->cfaHasVisited = true;
  67. m_block = basicBlock;
  68. m_isValid = true;
  69. m_foundConstants = false;
  70. m_branchDirection = InvalidBranchDirection;
  71. }
  72. void AbstractState::initialize(Graph& graph)
  73. {
  74. BasicBlock* root = graph.m_blocks[0].get();
  75. root->cfaShouldRevisit = true;
  76. root->cfaHasVisited = false;
  77. root->cfaFoundConstants = false;
  78. for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
  79. Node* node = root->variablesAtHead.argument(i);
  80. ASSERT(node->op() == SetArgument);
  81. if (!node->variableAccessData()->shouldUnboxIfPossible()) {
  82. root->valuesAtHead.argument(i).makeTop();
  83. continue;
  84. }
  85. SpeculatedType prediction = node->variableAccessData()->prediction();
  86. if (isInt32Speculation(prediction))
  87. root->valuesAtHead.argument(i).set(SpecInt32);
  88. else if (isBooleanSpeculation(prediction))
  89. root->valuesAtHead.argument(i).set(SpecBoolean);
  90. else if (isCellSpeculation(prediction))
  91. root->valuesAtHead.argument(i).set(SpecCell);
  92. else
  93. root->valuesAtHead.argument(i).makeTop();
  94. root->valuesAtTail.argument(i).clear();
  95. }
  96. for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
  97. Node* node = root->variablesAtHead.local(i);
  98. if (node && node->variableAccessData()->isCaptured())
  99. root->valuesAtHead.local(i).makeTop();
  100. else
  101. root->valuesAtHead.local(i).clear();
  102. root->valuesAtTail.local(i).clear();
  103. }
  104. for (BlockIndex blockIndex = 1 ; blockIndex < graph.m_blocks.size(); ++blockIndex) {
  105. BasicBlock* block = graph.m_blocks[blockIndex].get();
  106. if (!block)
  107. continue;
  108. if (!block->isReachable)
  109. continue;
  110. block->cfaShouldRevisit = false;
  111. block->cfaHasVisited = false;
  112. block->cfaFoundConstants = false;
  113. for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) {
  114. block->valuesAtHead.argument(i).clear();
  115. block->valuesAtTail.argument(i).clear();
  116. }
  117. for (size_t i = 0; i < block->valuesAtHead.numberOfLocals(); ++i) {
  118. block->valuesAtHead.local(i).clear();
  119. block->valuesAtTail.local(i).clear();
  120. }
  121. if (!block->isOSRTarget)
  122. continue;
  123. if (block->bytecodeBegin != graph.m_osrEntryBytecodeIndex)
  124. continue;
  125. for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) {
  126. AbstractValue value;
  127. value.setMostSpecific(graph.m_mustHandleValues[i]);
  128. int operand = graph.m_mustHandleValues.operandForIndex(i);
  129. block->valuesAtHead.operand(operand).merge(value);
  130. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  131. dataLogF(" Initializing Block #%u, operand r%d, to ", blockIndex, operand);
  132. block->valuesAtHead.operand(operand).dump(WTF::dataFile());
  133. dataLogF("\n");
  134. #endif
  135. }
  136. block->cfaShouldRevisit = true;
  137. }
  138. }
  139. bool AbstractState::endBasicBlock(MergeMode mergeMode)
  140. {
  141. ASSERT(m_block);
  142. BasicBlock* block = m_block; // Save the block for successor merging.
  143. block->cfaFoundConstants = m_foundConstants;
  144. block->cfaDidFinish = m_isValid;
  145. block->cfaBranchDirection = m_branchDirection;
  146. if (!m_isValid) {
  147. reset();
  148. return false;
  149. }
  150. bool changed = false;
  151. if (mergeMode != DontMerge || !ASSERT_DISABLED) {
  152. for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
  153. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  154. dataLogF(" Merging state for argument %zu.\n", argument);
  155. #endif
  156. AbstractValue& destination = block->valuesAtTail.argument(argument);
  157. changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
  158. }
  159. for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
  160. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  161. dataLogF(" Merging state for local %zu.\n", local);
  162. #endif
  163. AbstractValue& destination = block->valuesAtTail.local(local);
  164. changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
  165. }
  166. }
  167. ASSERT(mergeMode != DontMerge || !changed);
  168. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  169. dataLogF(" Branch direction = %s\n", branchDirectionToString(m_branchDirection));
  170. #endif
  171. reset();
  172. if (mergeMode != MergeToSuccessors)
  173. return changed;
  174. return mergeToSuccessors(m_graph, block);
  175. }
  176. void AbstractState::reset()
  177. {
  178. m_block = 0;
  179. m_isValid = false;
  180. m_branchDirection = InvalidBranchDirection;
  181. }
  182. AbstractState::BooleanResult AbstractState::booleanResult(Node* node, AbstractValue& value)
  183. {
  184. JSValue childConst = value.value();
  185. if (childConst) {
  186. if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->codeOrigin)->globalExec()))
  187. return DefinitelyTrue;
  188. return DefinitelyFalse;
  189. }
  190. // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
  191. if (isCellSpeculation(value.m_type)
  192. && value.m_currentKnownStructure.hasSingleton()) {
  193. Structure* structure = value.m_currentKnownStructure.singleton();
  194. if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->codeOrigin))
  195. && structure->typeInfo().type() != StringType)
  196. return DefinitelyTrue;
  197. }
  198. return UnknownBooleanResult;
  199. }
  200. bool AbstractState::startExecuting(Node* node)
  201. {
  202. ASSERT(m_block);
  203. ASSERT(m_isValid);
  204. m_didClobber = false;
  205. node->setCanExit(false);
  206. if (!node->shouldGenerate())
  207. return false;
  208. return true;
  209. }
  210. bool AbstractState::startExecuting(unsigned indexInBlock)
  211. {
  212. return startExecuting(m_block->at(indexInBlock));
  213. }
  214. void AbstractState::executeEdges(Node* node)
  215. {
  216. DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse);
  217. }
  218. void AbstractState::executeEdges(unsigned indexInBlock)
  219. {
  220. executeEdges(m_block->at(indexInBlock));
  221. }
  222. void AbstractState::verifyEdge(Node*, Edge edge)
  223. {
  224. RELEASE_ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())));
  225. }
  226. void AbstractState::verifyEdges(Node* node)
  227. {
  228. DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
  229. }
  230. bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
  231. {
  232. if (!ASSERT_DISABLED)
  233. verifyEdges(node);
  234. switch (node->op()) {
  235. case JSConstant:
  236. case WeakJSConstant:
  237. case PhantomArguments: {
  238. forNode(node).set(m_graph.valueOfJSConstant(node));
  239. break;
  240. }
  241. case Identity: {
  242. forNode(node) = forNode(node->child1());
  243. break;
  244. }
  245. case GetLocal: {
  246. VariableAccessData* variableAccessData = node->variableAccessData();
  247. if (variableAccessData->prediction() == SpecNone) {
  248. m_isValid = false;
  249. break;
  250. }
  251. AbstractValue value = m_variables.operand(variableAccessData->local());
  252. if (!variableAccessData->isCaptured()) {
  253. if (value.isClear())
  254. node->setCanExit(true);
  255. }
  256. if (value.value())
  257. m_foundConstants = true;
  258. forNode(node) = value;
  259. break;
  260. }
  261. case GetLocalUnlinked: {
  262. AbstractValue value = m_variables.operand(node->unlinkedLocal());
  263. if (value.value())
  264. m_foundConstants = true;
  265. forNode(node) = value;
  266. break;
  267. }
  268. case SetLocal: {
  269. m_variables.operand(node->local()) = forNode(node->child1());
  270. break;
  271. }
  272. case MovHintAndCheck: {
  273. // Don't need to do anything. A MovHint is effectively a promise that the SetLocal
  274. // was dead.
  275. break;
  276. }
  277. case MovHint:
  278. case ZombieHint: {
  279. RELEASE_ASSERT_NOT_REACHED();
  280. break;
  281. }
  282. case SetArgument:
  283. // Assert that the state of arguments has been set.
  284. ASSERT(!m_block->valuesAtHead.operand(node->local()).isClear());
  285. break;
  286. case BitAnd:
  287. case BitOr:
  288. case BitXor:
  289. case BitRShift:
  290. case BitLShift:
  291. case BitURShift: {
  292. JSValue left = forNode(node->child1()).value();
  293. JSValue right = forNode(node->child2()).value();
  294. if (left && right && left.isInt32() && right.isInt32()) {
  295. int32_t a = left.asInt32();
  296. int32_t b = right.asInt32();
  297. bool constantWasSet;
  298. switch (node->op()) {
  299. case BitAnd:
  300. constantWasSet = trySetConstant(node, JSValue(a & b));
  301. break;
  302. case BitOr:
  303. constantWasSet = trySetConstant(node, JSValue(a | b));
  304. break;
  305. case BitXor:
  306. constantWasSet = trySetConstant(node, JSValue(a ^ b));
  307. break;
  308. case BitRShift:
  309. constantWasSet = trySetConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
  310. break;
  311. case BitLShift:
  312. constantWasSet = trySetConstant(node, JSValue(a << static_cast<uint32_t>(b)));
  313. break;
  314. case BitURShift:
  315. constantWasSet = trySetConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
  316. break;
  317. default:
  318. RELEASE_ASSERT_NOT_REACHED();
  319. constantWasSet = false;
  320. }
  321. if (constantWasSet) {
  322. m_foundConstants = true;
  323. break;
  324. }
  325. }
  326. forNode(node).set(SpecInt32);
  327. break;
  328. }
  329. case UInt32ToNumber: {
  330. JSValue child = forNode(node->child1()).value();
  331. if (child && child.isNumber()) {
  332. ASSERT(child.isInt32());
  333. if (trySetConstant(node, JSValue(child.asUInt32()))) {
  334. m_foundConstants = true;
  335. break;
  336. }
  337. }
  338. if (!node->canSpeculateInteger())
  339. forNode(node).set(SpecDouble);
  340. else {
  341. forNode(node).set(SpecInt32);
  342. node->setCanExit(true);
  343. }
  344. break;
  345. }
  346. case DoubleAsInt32: {
  347. JSValue child = forNode(node->child1()).value();
  348. if (child && child.isNumber()) {
  349. double asDouble = child.asNumber();
  350. int32_t asInt = JSC::toInt32(asDouble);
  351. if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)
  352. && trySetConstant(node, JSValue(asInt))) {
  353. m_foundConstants = true;
  354. break;
  355. }
  356. }
  357. node->setCanExit(true);
  358. forNode(node).set(SpecInt32);
  359. break;
  360. }
  361. case ValueToInt32: {
  362. JSValue child = forNode(node->child1()).value();
  363. if (child && child.isNumber()) {
  364. bool constantWasSet;
  365. if (child.isInt32())
  366. constantWasSet = trySetConstant(node, child);
  367. else
  368. constantWasSet = trySetConstant(node, JSValue(JSC::toInt32(child.asDouble())));
  369. if (constantWasSet) {
  370. m_foundConstants = true;
  371. break;
  372. }
  373. }
  374. forNode(node).set(SpecInt32);
  375. break;
  376. }
  377. case Int32ToDouble:
  378. case ForwardInt32ToDouble: {
  379. JSValue child = forNode(node->child1()).value();
  380. if (child && child.isNumber()
  381. && trySetConstant(node, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) {
  382. m_foundConstants = true;
  383. break;
  384. }
  385. if (isInt32Speculation(forNode(node->child1()).m_type))
  386. forNode(node).set(SpecDoubleReal);
  387. else
  388. forNode(node).set(SpecDouble);
  389. break;
  390. }
  391. case ValueAdd:
  392. case ArithAdd: {
  393. JSValue left = forNode(node->child1()).value();
  394. JSValue right = forNode(node->child2()).value();
  395. if (left && right && left.isNumber() && right.isNumber()
  396. && trySetConstant(node, JSValue(left.asNumber() + right.asNumber()))) {
  397. m_foundConstants = true;
  398. break;
  399. }
  400. switch (node->binaryUseKind()) {
  401. case Int32Use:
  402. forNode(node).set(SpecInt32);
  403. if (!nodeCanTruncateInteger(node->arithNodeFlags()))
  404. node->setCanExit(true);
  405. break;
  406. case NumberUse:
  407. if (isRealNumberSpeculation(forNode(node->child1()).m_type)
  408. && isRealNumberSpeculation(forNode(node->child2()).m_type))
  409. forNode(node).set(SpecDoubleReal);
  410. else
  411. forNode(node).set(SpecDouble);
  412. break;
  413. default:
  414. RELEASE_ASSERT(node->op() == ValueAdd);
  415. clobberWorld(node->codeOrigin, indexInBlock);
  416. forNode(node).set(SpecString | SpecInt32 | SpecNumber);
  417. break;
  418. }
  419. break;
  420. }
  421. case MakeRope: {
  422. forNode(node).set(m_graph.m_vm.stringStructure.get());
  423. break;
  424. }
  425. case ArithSub: {
  426. JSValue left = forNode(node->child1()).value();
  427. JSValue right = forNode(node->child2()).value();
  428. if (left && right && left.isNumber() && right.isNumber()
  429. && trySetConstant(node, JSValue(left.asNumber() - right.asNumber()))) {
  430. m_foundConstants = true;
  431. break;
  432. }
  433. switch (node->binaryUseKind()) {
  434. case Int32Use:
  435. forNode(node).set(SpecInt32);
  436. if (!nodeCanTruncateInteger(node->arithNodeFlags()))
  437. node->setCanExit(true);
  438. break;
  439. case NumberUse:
  440. forNode(node).set(SpecDouble);
  441. break;
  442. default:
  443. RELEASE_ASSERT_NOT_REACHED();
  444. break;
  445. }
  446. break;
  447. }
  448. case ArithNegate: {
  449. JSValue child = forNode(node->child1()).value();
  450. if (child && child.isNumber()
  451. && trySetConstant(node, JSValue(-child.asNumber()))) {
  452. m_foundConstants = true;
  453. break;
  454. }
  455. switch (node->child1().useKind()) {
  456. case Int32Use:
  457. forNode(node).set(SpecInt32);
  458. if (!nodeCanTruncateInteger(node->arithNodeFlags()))
  459. node->setCanExit(true);
  460. break;
  461. case NumberUse:
  462. forNode(node).set(SpecDouble);
  463. break;
  464. default:
  465. RELEASE_ASSERT_NOT_REACHED();
  466. break;
  467. }
  468. break;
  469. }
  470. case ArithMul: {
  471. JSValue left = forNode(node->child1()).value();
  472. JSValue right = forNode(node->child2()).value();
  473. if (left && right && left.isNumber() && right.isNumber()
  474. && trySetConstant(node, JSValue(left.asNumber() * right.asNumber()))) {
  475. m_foundConstants = true;
  476. break;
  477. }
  478. switch (node->binaryUseKind()) {
  479. case Int32Use:
  480. forNode(node).set(SpecInt32);
  481. if (!nodeCanTruncateInteger(node->arithNodeFlags())
  482. || !nodeCanIgnoreNegativeZero(node->arithNodeFlags()))
  483. node->setCanExit(true);
  484. break;
  485. case NumberUse:
  486. if (isRealNumberSpeculation(forNode(node->child1()).m_type)
  487. || isRealNumberSpeculation(forNode(node->child2()).m_type))
  488. forNode(node).set(SpecDoubleReal);
  489. else
  490. forNode(node).set(SpecDouble);
  491. break;
  492. default:
  493. RELEASE_ASSERT_NOT_REACHED();
  494. break;
  495. }
  496. break;
  497. }
  498. case ArithIMul: {
  499. forNode(node).set(SpecInt32);
  500. break;
  501. }
  502. case ArithDiv:
  503. case ArithMin:
  504. case ArithMax:
  505. case ArithMod: {
  506. JSValue left = forNode(node->child1()).value();
  507. JSValue right = forNode(node->child2()).value();
  508. if (left && right && left.isNumber() && right.isNumber()) {
  509. double a = left.asNumber();
  510. double b = right.asNumber();
  511. bool constantWasSet;
  512. switch (node->op()) {
  513. case ArithDiv:
  514. constantWasSet = trySetConstant(node, JSValue(a / b));
  515. break;
  516. case ArithMin:
  517. constantWasSet = trySetConstant(node, JSValue(a < b ? a : (b <= a ? b : a + b)));
  518. break;
  519. case ArithMax:
  520. constantWasSet = trySetConstant(node, JSValue(a > b ? a : (b >= a ? b : a + b)));
  521. break;
  522. case ArithMod:
  523. constantWasSet = trySetConstant(node, JSValue(fmod(a, b)));
  524. break;
  525. default:
  526. RELEASE_ASSERT_NOT_REACHED();
  527. constantWasSet = false;
  528. break;
  529. }
  530. if (constantWasSet) {
  531. m_foundConstants = true;
  532. break;
  533. }
  534. }
  535. switch (node->binaryUseKind()) {
  536. case Int32Use:
  537. forNode(node).set(SpecInt32);
  538. node->setCanExit(true);
  539. break;
  540. case NumberUse:
  541. forNode(node).set(SpecDouble);
  542. break;
  543. default:
  544. RELEASE_ASSERT_NOT_REACHED();
  545. break;
  546. }
  547. break;
  548. }
  549. case ArithAbs: {
  550. JSValue child = forNode(node->child1()).value();
  551. if (child && child.isNumber()
  552. && trySetConstant(node, JSValue(fabs(child.asNumber())))) {
  553. m_foundConstants = true;
  554. break;
  555. }
  556. switch (node->child1().useKind()) {
  557. case Int32Use:
  558. forNode(node).set(SpecInt32);
  559. node->setCanExit(true);
  560. break;
  561. case NumberUse:
  562. forNode(node).set(SpecDouble);
  563. break;
  564. default:
  565. RELEASE_ASSERT_NOT_REACHED();
  566. break;
  567. }
  568. break;
  569. }
  570. case ArithSqrt: {
  571. JSValue child = forNode(node->child1()).value();
  572. if (child && child.isNumber()
  573. && trySetConstant(node, JSValue(sqrt(child.asNumber())))) {
  574. m_foundConstants = true;
  575. break;
  576. }
  577. forNode(node).set(SpecDouble);
  578. break;
  579. }
  580. case LogicalNot: {
  581. bool didSetConstant = false;
  582. switch (booleanResult(node, forNode(node->child1()))) {
  583. case DefinitelyTrue:
  584. didSetConstant = trySetConstant(node, jsBoolean(false));
  585. break;
  586. case DefinitelyFalse:
  587. didSetConstant = trySetConstant(node, jsBoolean(true));
  588. break;
  589. default:
  590. break;
  591. }
  592. if (didSetConstant) {
  593. m_foundConstants = true;
  594. break;
  595. }
  596. switch (node->child1().useKind()) {
  597. case BooleanUse:
  598. case Int32Use:
  599. case NumberUse:
  600. case UntypedUse:
  601. break;
  602. case ObjectOrOtherUse:
  603. node->setCanExit(true);
  604. break;
  605. default:
  606. RELEASE_ASSERT_NOT_REACHED();
  607. break;
  608. }
  609. forNode(node).set(SpecBoolean);
  610. break;
  611. }
  612. case IsUndefined:
  613. case IsBoolean:
  614. case IsNumber:
  615. case IsString:
  616. case IsObject:
  617. case IsFunction: {
  618. node->setCanExit(node->op() == IsUndefined && m_codeBlock->globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid());
  619. JSValue child = forNode(node->child1()).value();
  620. if (child) {
  621. bool constantWasSet;
  622. switch (node->op()) {
  623. case IsUndefined:
  624. if (m_codeBlock->globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
  625. constantWasSet = trySetConstant(node, jsBoolean(
  626. child.isCell()
  627. ? false
  628. : child.isUndefined()));
  629. } else {
  630. constantWasSet = trySetConstant(node, jsBoolean(
  631. child.isCell()
  632. ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->codeOrigin))
  633. : child.isUndefined()));
  634. }
  635. break;
  636. case IsBoolean:
  637. constantWasSet = trySetConstant(node, jsBoolean(child.isBoolean()));
  638. break;
  639. case IsNumber:
  640. constantWasSet = trySetConstant(node, jsBoolean(child.isNumber()));
  641. break;
  642. case IsString:
  643. constantWasSet = trySetConstant(node, jsBoolean(isJSString(child)));
  644. break;
  645. case IsObject:
  646. if (child.isNull() || !child.isObject()) {
  647. constantWasSet = trySetConstant(node, jsBoolean(child.isNull()));
  648. break;
  649. }
  650. default:
  651. constantWasSet = false;
  652. break;
  653. }
  654. if (constantWasSet) {
  655. m_foundConstants = true;
  656. break;
  657. }
  658. }
  659. forNode(node).set(SpecBoolean);
  660. break;
  661. }
  662. case TypeOf: {
  663. VM* vm = m_codeBlock->vm();
  664. JSValue child = forNode(node->child1()).value();
  665. AbstractValue& abstractChild = forNode(node->child1());
  666. if (child) {
  667. JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->codeOrigin), child);
  668. if (trySetConstant(node, typeString)) {
  669. m_foundConstants = true;
  670. break;
  671. }
  672. } else if (isNumberSpeculation(abstractChild.m_type)) {
  673. if (trySetConstant(node, vm->smallStrings.numberString())) {
  674. forNode(node->child1()).filter(SpecNumber);
  675. m_foundConstants = true;
  676. break;
  677. }
  678. } else if (isStringSpeculation(abstractChild.m_type)) {
  679. if (trySetConstant(node, vm->smallStrings.stringString())) {
  680. forNode(node->child1()).filter(SpecString);
  681. m_foundConstants = true;
  682. break;
  683. }
  684. } else if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) {
  685. if (trySetConstant(node, vm->smallStrings.objectString())) {
  686. forNode(node->child1()).filter(SpecFinalObject | SpecArray | SpecArguments);
  687. m_foundConstants = true;
  688. break;
  689. }
  690. } else if (isFunctionSpeculation(abstractChild.m_type)) {
  691. if (trySetConstant(node, vm->smallStrings.functionString())) {
  692. forNode(node->child1()).filter(SpecFunction);
  693. m_foundConstants = true;
  694. break;
  695. }
  696. } else if (isBooleanSpeculation(abstractChild.m_type)) {
  697. if (trySetConstant(node, vm->smallStrings.booleanString())) {
  698. forNode(node->child1()).filter(SpecBoolean);
  699. m_foundConstants = true;
  700. break;
  701. }
  702. }
  703. switch (node->child1().useKind()) {
  704. case StringUse:
  705. case CellUse:
  706. node->setCanExit(true);
  707. break;
  708. case UntypedUse:
  709. break;
  710. default:
  711. RELEASE_ASSERT_NOT_REACHED();
  712. break;
  713. }
  714. forNode(node).set(m_graph.m_vm.stringStructure.get());
  715. break;
  716. }
  717. case CompareLess:
  718. case CompareLessEq:
  719. case CompareGreater:
  720. case CompareGreaterEq:
  721. case CompareEq:
  722. case CompareEqConstant: {
  723. bool constantWasSet = false;
  724. JSValue leftConst = forNode(node->child1()).value();
  725. JSValue rightConst = forNode(node->child2()).value();
  726. if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
  727. double a = leftConst.asNumber();
  728. double b = rightConst.asNumber();
  729. switch (node->op()) {
  730. case CompareLess:
  731. constantWasSet = trySetConstant(node, jsBoolean(a < b));
  732. break;
  733. case CompareLessEq:
  734. constantWasSet = trySetConstant(node, jsBoolean(a <= b));
  735. break;
  736. case CompareGreater:
  737. constantWasSet = trySetConstant(node, jsBoolean(a > b));
  738. break;
  739. case CompareGreaterEq:
  740. constantWasSet = trySetConstant(node, jsBoolean(a >= b));
  741. break;
  742. case CompareEq:
  743. constantWasSet = trySetConstant(node, jsBoolean(a == b));
  744. break;
  745. default:
  746. RELEASE_ASSERT_NOT_REACHED();
  747. constantWasSet = false;
  748. break;
  749. }
  750. }
  751. if (!constantWasSet && (node->op() == CompareEqConstant || node->op() == CompareEq)) {
  752. SpeculatedType leftType = forNode(node->child1()).m_type;
  753. SpeculatedType rightType = forNode(node->child2()).m_type;
  754. if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
  755. || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
  756. constantWasSet = trySetConstant(node, jsBoolean(false));
  757. }
  758. if (constantWasSet) {
  759. m_foundConstants = true;
  760. break;
  761. }
  762. forNode(node).set(SpecBoolean);
  763. // This is overly conservative. But the only thing this prevents is store elimination,
  764. // and how likely is it, really, that you'll have redundant stores across a comparison
  765. // operation? Comparison operations are typically at the end of basic blocks, so
  766. // unless we have global store elimination (super unlikely given how unprofitable that
  767. // optimization is to begin with), you aren't going to be wanting to store eliminate
  768. // across an equality op.
  769. node->setCanExit(true);
  770. break;
  771. }
  772. case CompareStrictEq:
  773. case CompareStrictEqConstant: {
  774. Node* leftNode = node->child1().node();
  775. Node* rightNode = node->child2().node();
  776. JSValue left = forNode(leftNode).value();
  777. JSValue right = forNode(rightNode).value();
  778. if (left && right && left.isNumber() && right.isNumber()
  779. && trySetConstant(node, jsBoolean(left.asNumber() == right.asNumber()))) {
  780. m_foundConstants = true;
  781. break;
  782. }
  783. forNode(node).set(SpecBoolean);
  784. node->setCanExit(true); // This is overly conservative.
  785. break;
  786. }
  787. case StringCharCodeAt:
  788. node->setCanExit(true);
  789. forNode(node).set(SpecInt32);
  790. break;
  791. case StringFromCharCode:
  792. forNode(node).set(SpecString);
  793. break;
  794. case StringCharAt:
  795. node->setCanExit(true);
  796. forNode(node).set(m_graph.m_vm.stringStructure.get());
  797. break;
  798. case GetByVal: {
  799. node->setCanExit(true);
  800. switch (node->arrayMode().type()) {
  801. case Array::SelectUsingPredictions:
  802. case Array::Unprofiled:
  803. case Array::Undecided:
  804. RELEASE_ASSERT_NOT_REACHED();
  805. break;
  806. case Array::ForceExit:
  807. m_isValid = false;
  808. break;
  809. case Array::Generic:
  810. clobberWorld(node->codeOrigin, indexInBlock);
  811. forNode(node).makeTop();
  812. break;
  813. case Array::String:
  814. forNode(node).set(m_graph.m_vm.stringStructure.get());
  815. break;
  816. case Array::Arguments:
  817. forNode(node).makeTop();
  818. break;
  819. case Array::Int32:
  820. if (node->arrayMode().isOutOfBounds()) {
  821. clobberWorld(node->codeOrigin, indexInBlock);
  822. forNode(node).makeTop();
  823. } else
  824. forNode(node).set(SpecInt32);
  825. break;
  826. case Array::Double:
  827. if (node->arrayMode().isOutOfBounds()) {
  828. clobberWorld(node->codeOrigin, indexInBlock);
  829. forNode(node).makeTop();
  830. } else if (node->arrayMode().isSaneChain())
  831. forNode(node).set(SpecDouble);
  832. else
  833. forNode(node).set(SpecDoubleReal);
  834. break;
  835. case Array::Contiguous:
  836. case Array::ArrayStorage:
  837. case Array::SlowPutArrayStorage:
  838. if (node->arrayMode().isOutOfBounds())
  839. clobberWorld(node->codeOrigin, indexInBlock);
  840. forNode(node).makeTop();
  841. break;
  842. case Array::Int8Array:
  843. forNode(node).set(SpecInt32);
  844. break;
  845. case Array::Int16Array:
  846. forNode(node).set(SpecInt32);
  847. break;
  848. case Array::Int32Array:
  849. forNode(node).set(SpecInt32);
  850. break;
  851. case Array::Uint8Array:
  852. forNode(node).set(SpecInt32);
  853. break;
  854. case Array::Uint8ClampedArray:
  855. forNode(node).set(SpecInt32);
  856. break;
  857. case Array::Uint16Array:
  858. forNode(node).set(SpecInt32);
  859. break;
  860. case Array::Uint32Array:
  861. if (node->shouldSpeculateInteger())
  862. forNode(node).set(SpecInt32);
  863. else
  864. forNode(node).set(SpecDouble);
  865. break;
  866. case Array::Float32Array:
  867. forNode(node).set(SpecDouble);
  868. break;
  869. case Array::Float64Array:
  870. forNode(node).set(SpecDouble);
  871. break;
  872. default:
  873. RELEASE_ASSERT_NOT_REACHED();
  874. break;
  875. }
  876. break;
  877. }
  878. case PutByVal:
  879. case PutByValAlias: {
  880. node->setCanExit(true);
  881. switch (node->arrayMode().modeForPut().type()) {
  882. case Array::ForceExit:
  883. m_isValid = false;
  884. break;
  885. case Array::Generic:
  886. clobberWorld(node->codeOrigin, indexInBlock);
  887. break;
  888. case Array::Int32:
  889. if (node->arrayMode().isOutOfBounds())
  890. clobberWorld(node->codeOrigin, indexInBlock);
  891. break;
  892. case Array::Double:
  893. if (node->arrayMode().isOutOfBounds())
  894. clobberWorld(node->codeOrigin, indexInBlock);
  895. break;
  896. case Array::Contiguous:
  897. case Array::ArrayStorage:
  898. if (node->arrayMode().isOutOfBounds())
  899. clobberWorld(node->codeOrigin, indexInBlock);
  900. break;
  901. case Array::SlowPutArrayStorage:
  902. if (node->arrayMode().mayStoreToHole())
  903. clobberWorld(node->codeOrigin, indexInBlock);
  904. break;
  905. default:
  906. break;
  907. }
  908. break;
  909. }
  910. case ArrayPush:
  911. node->setCanExit(true);
  912. clobberWorld(node->codeOrigin, indexInBlock);
  913. forNode(node).set(SpecNumber);
  914. break;
  915. case ArrayPop:
  916. node->setCanExit(true);
  917. clobberWorld(node->codeOrigin, indexInBlock);
  918. forNode(node).makeTop();
  919. break;
  920. case RegExpExec:
  921. forNode(node).makeTop();
  922. break;
  923. case RegExpTest:
  924. forNode(node).set(SpecBoolean);
  925. break;
  926. case Jump:
  927. break;
  928. case Branch: {
  929. Node* child = node->child1().node();
  930. BooleanResult result = booleanResult(node, forNode(child));
  931. if (result == DefinitelyTrue) {
  932. m_branchDirection = TakeTrue;
  933. break;
  934. }
  935. if (result == DefinitelyFalse) {
  936. m_branchDirection = TakeFalse;
  937. break;
  938. }
  939. // FIXME: The above handles the trivial cases of sparse conditional
  940. // constant propagation, but we can do better:
  941. // We can specialize the source variable's value on each direction of
  942. // the branch.
  943. node->setCanExit(true); // This is overly conservative.
  944. m_branchDirection = TakeBoth;
  945. break;
  946. }
  947. case Return:
  948. m_isValid = false;
  949. break;
  950. case Throw:
  951. case ThrowReferenceError:
  952. m_isValid = false;
  953. node->setCanExit(true);
  954. break;
  955. case ToPrimitive: {
  956. JSValue childConst = forNode(node->child1()).value();
  957. if (childConst && childConst.isNumber() && trySetConstant(node, childConst)) {
  958. m_foundConstants = true;
  959. break;
  960. }
  961. ASSERT(node->child1().useKind() == UntypedUse);
  962. AbstractValue& source = forNode(node->child1());
  963. AbstractValue& destination = forNode(node);
  964. // NB. The more canonical way of writing this would have been:
  965. //
  966. // destination = source;
  967. // if (destination.m_type & !(SpecNumber | SpecString | SpecBoolean)) {
  968. // destination.filter(SpecNumber | SpecString | SpecBoolean);
  969. // AbstractValue string;
  970. // string.set(vm->stringStructure);
  971. // destination.merge(string);
  972. // }
  973. //
  974. // The reason why this would, in most other cases, have been better is that
  975. // then destination would preserve any non-SpeculatedType knowledge of source.
  976. // As it stands, the code below forgets any non-SpeculatedType knowledge that
  977. // source would have had. Fortunately, though, for things like strings and
  978. // numbers and booleans, we don't care about the non-SpeculatedType knowedge:
  979. // the structure won't tell us anything we don't already know, and neither
  980. // will ArrayModes. And if the source was a meaningful constant then we
  981. // would have handled that above. Unfortunately, this does mean that
  982. // ToPrimitive will currently forget string constants. But that's not a big
  983. // deal since we don't do any optimization on those currently.
  984. clobberWorld(node->codeOrigin, indexInBlock);
  985. SpeculatedType type = source.m_type;
  986. if (type & ~(SpecNumber | SpecString | SpecBoolean))
  987. type = (SpecTop & ~SpecCell) | SpecString;
  988. destination.set(type);
  989. break;
  990. }
  991. case ToString: {
  992. switch (node->child1().useKind()) {
  993. case StringObjectUse:
  994. // This also filters that the StringObject has the primordial StringObject
  995. // structure.
  996. forNode(node->child1()).filter(m_graph.globalObjectFor(node->codeOrigin)->stringObjectStructure());
  997. node->setCanExit(true); // We could be more precise but it's likely not worth it.
  998. break;
  999. case StringOrStringObjectUse:
  1000. node->setCanExit(true); // We could be more precise but it's likely not worth it.
  1001. break;
  1002. case CellUse:
  1003. case UntypedUse:
  1004. clobberWorld(node->codeOrigin, indexInBlock);
  1005. break;
  1006. default:
  1007. RELEASE_ASSERT_NOT_REACHED();
  1008. break;
  1009. }
  1010. forNode(node).set(m_graph.m_vm.stringStructure.get());
  1011. break;
  1012. }
  1013. case NewStringObject: {
  1014. #if ENABLE(DETACHED_JIT)
  1015. #pragma message "[SECURE JSCORE] try to enable this assert..."
  1016. #else
  1017. ASSERT(node->structure()->classInfo() == &StringObject::s_info);
  1018. #endif
  1019. forNode(node).set(node->structure());
  1020. break;
  1021. }
  1022. case NewArray:
  1023. node->setCanExit(true);
  1024. forNode(node).set(m_graph.globalObjectFor(node->codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
  1025. m_haveStructures = true;
  1026. break;
  1027. case NewArrayBuffer:
  1028. node->setCanExit(true);
  1029. forNode(node).set(m_graph.globalObjectFor(node->codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
  1030. m_haveStructures = true;
  1031. break;
  1032. case NewArrayWithSize:
  1033. node->setCanExit(true);
  1034. forNode(node).set(SpecArray);
  1035. m_haveStructures = true;
  1036. break;
  1037. case NewRegexp:
  1038. forNode(node).set(m_graph.globalObjectFor(node->codeOrigin)->regExpStructure());
  1039. m_haveStructures = true;
  1040. break;
  1041. case ConvertThis: {
  1042. AbstractValue& source = forNode(node->child1());
  1043. AbstractValue& destination = forNode(node);
  1044. destination = source;
  1045. destination.merge(SpecObjectOther);
  1046. break;
  1047. }
  1048. case CreateThis: {
  1049. forNode(node).set(SpecFinalObject);
  1050. break;
  1051. }
  1052. case AllocationProfileWatchpoint:
  1053. node->setCanExit(true);
  1054. break;
  1055. case NewObject:
  1056. forNode(node).set(node->structure());
  1057. m_haveStructures = true;
  1058. break;
  1059. case CreateActivation:
  1060. forNode(node).set(m_codeBlock->globalObjectFor(node->codeOrigin)->activationStructure());
  1061. m_haveStructures = true;
  1062. break;
  1063. case CreateArguments:
  1064. forNode(node).set(m_codeBlock->globalObjectFor(node->codeOrigin)->argumentsStructure());
  1065. m_haveStructures = true;
  1066. break;
  1067. case TearOffActivation:
  1068. case TearOffArguments:
  1069. // Does nothing that is user-visible.
  1070. break;
  1071. case CheckArgumentsNotCreated:
  1072. if (isEmptySpeculation(
  1073. m_variables.operand(
  1074. m_graph.argumentsRegisterFor(node->codeOrigin)).m_type))
  1075. m_foundConstants = true;
  1076. else
  1077. node->setCanExit(true);
  1078. break;
  1079. case GetMyArgumentsLength:
  1080. // We know that this executable does not escape its arguments, so we can optimize
  1081. // the arguments a bit. Note that this is not sufficient to force constant folding
  1082. // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
  1083. // We perform further optimizations on this later on.
  1084. if (node->codeOrigin.inlineCallFrame)
  1085. forNode(node).set(jsNumber(node->codeOrigin.inlineCallFrame->arguments.size() - 1));
  1086. else
  1087. forNode(node).set(SpecInt32);
  1088. node->setCanExit(
  1089. !isEmptySpeculation(
  1090. m_variables.operand(
  1091. m_graph.argumentsRegisterFor(node->codeOrigin)).m_type));
  1092. break;
  1093. case GetMyArgumentsLengthSafe:
  1094. // This potentially clobbers all structures if the arguments object had a getter
  1095. // installed on the length property.
  1096. clobberWorld(node->codeOrigin, indexInBlock);
  1097. // We currently make no guarantee about what this returns because it does not
  1098. // speculate that the length property is actually a length.
  1099. forNode(node).makeTop();
  1100. break;
  1101. case GetMyArgumentByVal:
  1102. node->setCanExit(true);
  1103. // We know that this executable does not escape its arguments, so we can optimize
  1104. // the arguments a bit. Note that this ends up being further optimized by the
  1105. // ArgumentsSimplificationPhase.
  1106. forNode(node).makeTop();
  1107. break;
  1108. case GetMyArgumentByValSafe:
  1109. node->setCanExit(true);
  1110. // This potentially clobbers all structures if the property we're accessing has
  1111. // a getter. We don't speculate against this.
  1112. clobberWorld(node->codeOrigin, indexInBlock);
  1113. // And the result is unknown.
  1114. forNode(node).makeTop();
  1115. break;
  1116. case NewFunction: {
  1117. AbstractValue& value = forNode(node);
  1118. value = forNode(node->child1());
  1119. if (!(value.m_type & SpecEmpty)) {
  1120. m_foundConstants = true;
  1121. break;
  1122. }
  1123. value.set((value.m_type & ~SpecEmpty) | SpecFunction);
  1124. break;
  1125. }
  1126. case NewFunctionExpression:
  1127. case NewFunctionNoCheck:
  1128. forNode(node).set(m_codeBlock->globalObjectFor(node->codeOrigin)->functionStructure());
  1129. break;
  1130. case GetCallee:
  1131. forNode(node).set(SpecFunction);
  1132. break;
  1133. case SetCallee:
  1134. case SetMyScope:
  1135. break;
  1136. case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202
  1137. case GetMyScope:
  1138. case SkipTopScope:
  1139. forNode(node).set(SpecObjectOther);
  1140. break;
  1141. case SkipScope: {
  1142. JSValue child = forNode(node->child1()).value();
  1143. if (child && trySetConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()))) {
  1144. m_foundConstants = true;
  1145. break;
  1146. }
  1147. forNode(node).set(SpecObjectOther);
  1148. break;
  1149. }
  1150. case GetScopeRegisters:
  1151. forNode(node).clear(); // The result is not a JS value.
  1152. break;
  1153. case GetScopedVar:
  1154. forNode(node).makeTop();
  1155. break;
  1156. case PutScopedVar:
  1157. clobberCapturedVars(node->codeOrigin);
  1158. break;
  1159. case GetById:
  1160. case GetByIdFlush:
  1161. node->setCanExit(true);
  1162. if (!node->prediction()) {
  1163. m_isValid = false;
  1164. break;
  1165. }
  1166. if (isCellSpeculation(node->child1()->prediction())) {
  1167. if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
  1168. GetByIdStatus status = GetByIdStatus::computeFor(
  1169. m_graph.m_vm, structure,
  1170. m_graph.m_codeBlock->identifier(node->identifierNumber()));
  1171. if (status.isSimple()) {
  1172. // Assert things that we can't handle and that the computeFor() method
  1173. // above won't be able to return.
  1174. ASSERT(status.structureSet().size() == 1);
  1175. ASSERT(status.chain().isEmpty());
  1176. if (status.specificValue())
  1177. forNode(node).set(status.specificValue());
  1178. else
  1179. forNode(node).makeTop();
  1180. forNode(node->child1()).filter(status.structureSet());
  1181. m_foundConstants = true;
  1182. break;
  1183. }
  1184. }
  1185. }
  1186. clobberWorld(node->codeOrigin, indexInBlock);
  1187. forNode(node).makeTop();
  1188. break;
  1189. case GetArrayLength:
  1190. node->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
  1191. forNode(node).set(SpecInt32);
  1192. break;
  1193. case CheckExecutable: {
  1194. // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks
  1195. // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200
  1196. // FIXME: We could eliminate these entirely if we know the exact value that flows into this.
  1197. // https://bugs.webkit.org/show_bug.cgi?id=106201
  1198. node->setCanExit(true);
  1199. break;
  1200. }
  1201. case CheckStructure:
  1202. case ForwardCheckStructure: {
  1203. // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
  1204. AbstractValue& value = forNode(node->child1());
  1205. ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
  1206. // If this structure check is attempting to prove knowledge already held in
  1207. // the futurePossibleStructure set then the constant folding phase should
  1208. // turn this into a watchpoint instead.
  1209. StructureSet& set = node->structureSet();
  1210. if (value.m_futurePossibleStructure.isSubsetOf(set)
  1211. || value.m_currentKnownStructure.isSubsetOf(set))
  1212. m_foundConstants = true;
  1213. if (!value.m_currentKnownStructure.isSubsetOf(set))
  1214. node->setCanExit(true);
  1215. value.filter(set);
  1216. m_haveStructures = true;
  1217. break;
  1218. }
  1219. case StructureTransitionWatchpoint:
  1220. case ForwardStructureTransitionWatchpoint: {
  1221. AbstractValue& value = forNode(node->child1());
  1222. // It's only valid to issue a structure transition watchpoint if we already
  1223. // know that the watchpoint covers a superset of the structures known to
  1224. // belong to the set of future structures that this value may have.
  1225. // Currently, we only issue singleton watchpoints (that check one structure)
  1226. // and our futurePossibleStructure set can only contain zero, one, or an
  1227. // infinity of structures.
  1228. ASSERT(value.m_futurePossibleStructure.isSubsetOf(StructureSet(node->structure())));
  1229. value.filter(node->structure());
  1230. m_haveStructures = true;
  1231. node->setCanExit(true);
  1232. break;
  1233. }
  1234. case PutStructure:
  1235. case PhantomPutStructure:
  1236. if (!forNode(node->child1()).m_currentKnownStructure.isClear()) {
  1237. clobberStructures(indexInBlock);
  1238. forNode(node->child1()).set(node->structureTransitionData().newStructure);
  1239. m_haveStructures = true;
  1240. }
  1241. break;
  1242. case GetButterfly:
  1243. case AllocatePropertyStorage:
  1244. case ReallocatePropertyStorage:
  1245. forNode(node).clear(); // The result is not a JS value.
  1246. break;
  1247. case CheckArray: {
  1248. if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
  1249. m_foundConstants = true;
  1250. break;
  1251. }
  1252. node->setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
  1253. switch (node->arrayMode().type()) {
  1254. case Array::String:
  1255. forNode(node->child1()).filter(SpecString);
  1256. break;
  1257. case Array::Int32:
  1258. case Array::Double:
  1259. case Array::Contiguous:
  1260. case Array::ArrayStorage:
  1261. case Array::SlowPutArrayStorage:
  1262. break;
  1263. case Array::Arguments:
  1264. forNode(node->child1()).filter(SpecArguments);
  1265. break;
  1266. case Array::Int8Array:
  1267. forNode(node->child1()).filter(SpecInt8Array);
  1268. break;
  1269. case Array::Int16Array:
  1270. forNode(node->child1()).filter(SpecInt16Array);
  1271. break;
  1272. case Array::Int32Array:
  1273. forNode(node->child1()).filter(SpecInt32Array);
  1274. break;
  1275. case Array::Uint8Array:
  1276. forNode(node->child1()).filter(SpecUint8Array);
  1277. break;
  1278. case Array::Uint8ClampedArray:
  1279. forNode(node->child1()).filter(SpecUint8ClampedArray);
  1280. break;
  1281. case Array::Uint16Array:
  1282. forNode(node->child1()).filter(SpecUint16Array);
  1283. break;
  1284. case Array::Uint32Array:
  1285. forNode(node->child1()).filter(SpecUint32Array);
  1286. break;
  1287. case Array::Float32Array:
  1288. forNode(node->child1()).filter(SpecFloat32Array);
  1289. break;
  1290. case Array::Float64Array:
  1291. forNode(node->child1()).filter(SpecFloat64Array);
  1292. break;
  1293. default:
  1294. RELEASE_ASSERT_NOT_REACHED();
  1295. break;
  1296. }
  1297. forNode(node->child1()).filterArrayModes(node->arrayMode().arrayModesThatPassFiltering());
  1298. m_haveStructures = true;
  1299. break;
  1300. }
  1301. case Arrayify: {
  1302. if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
  1303. m_foundConstants = true;
  1304. break;
  1305. }
  1306. ASSERT(node->arrayMode().conversion() == Array::Convert
  1307. || node->arrayMode().conversion() == Array::RageConvert);
  1308. node->setCanExit(true);
  1309. clobberStructures(indexInBlock);
  1310. forNode(node->child1()).filterArrayModes(node->arrayMode().arrayModesThatPassFiltering());
  1311. m_haveStructures = true;
  1312. break;
  1313. }
  1314. case ArrayifyToStructure: {
  1315. AbstractValue& value = forNode(node->child1());
  1316. StructureSet set = node->structure();
  1317. if (value.m_futurePossibleStructure.isSubsetOf(set)
  1318. || value.m_currentKnownStructure.isSubsetOf(set))
  1319. m_foundConstants = true;
  1320. node->setCanExit(true);
  1321. clobberStructures(indexInBlock);
  1322. value.filter(set);
  1323. m_haveStructures = true;
  1324. break;
  1325. }
  1326. case GetIndexedPropertyStorage: {
  1327. forNode(node).clear();
  1328. break;
  1329. }
  1330. case GetByOffset: {
  1331. forNode(node).makeTop();
  1332. break;
  1333. }
  1334. case PutByOffset: {
  1335. break;
  1336. }
  1337. case CheckFunction: {
  1338. JSValue value = forNode(node->child1()).value();
  1339. if (value == node->function()) {
  1340. m_foundConstants = true;
  1341. ASSERT(value);
  1342. break;
  1343. }
  1344. node->setCanExit(true); // Lies! We can do better.
  1345. forNode(node->child1()).filterByValue(node->function());
  1346. break;
  1347. }
  1348. case PutById:
  1349. case PutByIdDirect:
  1350. node->setCanExit(true);
  1351. if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
  1352. PutByIdStatus status = PutByIdStatus::computeFor(
  1353. m_graph.m_vm,
  1354. m_graph.globalObjectFor(node->codeOrigin),
  1355. structure,
  1356. m_graph.m_codeBlock->identifier(node->identifierNumber()),
  1357. node->op() == PutByIdDirect);
  1358. if (status.isSimpleReplace()) {
  1359. forNode(node->child1()).filter(structure);
  1360. m_foundConstants = true;
  1361. break;
  1362. }
  1363. if (status.isSimpleTransition()) {
  1364. clobberStructures(indexInBlock);
  1365. forNode(node->child1()).set(status.newStructure());
  1366. m_haveStructures = true;
  1367. m_foundConstants = true;
  1368. break;
  1369. }
  1370. }
  1371. clobberWorld(node->codeOrigin, indexInBlock);
  1372. break;
  1373. case GetGlobalVar:
  1374. forNode(node).makeTop();
  1375. break;
  1376. case GlobalVarWatchpoint:
  1377. node->setCanExit(true);
  1378. break;
  1379. case PutGlobalVar:
  1380. case PutGlobalVarCheck:
  1381. break;
  1382. case CheckHasInstance:
  1383. node->setCanExit(true);
  1384. // Sadly, we don't propagate the fact that we've done CheckHasInstance
  1385. break;
  1386. case InstanceOf:
  1387. node->setCanExit(true);
  1388. // Again, sadly, we don't propagate the fact that we've done InstanceOf
  1389. forNode(node).set(SpecBoolean);
  1390. break;
  1391. case Phi:
  1392. case Flush:
  1393. case PhantomLocal:
  1394. case Breakpoint:
  1395. break;
  1396. case Call:
  1397. case Construct:
  1398. case Resolve:
  1399. case ResolveBase:
  1400. case ResolveBaseStrictPut:
  1401. case ResolveGlobal:
  1402. node->setCanExit(true);
  1403. clobberWorld(node->codeOrigin, indexInBlock);
  1404. forNode(node).makeTop();
  1405. break;
  1406. case GarbageValue:
  1407. clobberWorld(node->codeOrigin, indexInBlock);
  1408. forNode(node).makeTop();
  1409. break;
  1410. case ForceOSRExit:
  1411. node->setCanExit(true);
  1412. m_isValid = false;
  1413. break;
  1414. case CheckWatchdogTimer:
  1415. node->setCanExit(true);
  1416. break;
  1417. case Phantom:
  1418. case InlineStart:
  1419. case Nop:
  1420. case CountExecution:
  1421. break;
  1422. case LastNodeType:
  1423. RELEASE_ASSERT_NOT_REACHED();
  1424. break;
  1425. }
  1426. return m_isValid;
  1427. }
  1428. bool AbstractState::executeEffects(unsigned indexInBlock)
  1429. {
  1430. return executeEffects(indexInBlock, m_block->at(indexInBlock));
  1431. }
  1432. bool AbstractState::execute(unsigned indexInBlock)
  1433. {
  1434. Node* node = m_block->at(indexInBlock);
  1435. if (!startExecuting(node))
  1436. return true;
  1437. executeEdges(node);
  1438. return executeEffects(indexInBlock, node);
  1439. }
  1440. inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock)
  1441. {
  1442. clobberCapturedVars(codeOrigin);
  1443. clobberStructures(indexInBlock);
  1444. }
  1445. inline void AbstractState::clobberCapturedVars(const CodeOrigin& codeOrigin)
  1446. {
  1447. if (codeOrigin.inlineCallFrame) {
  1448. const BitVector_shared& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
  1449. for (size_t i = capturedVars.size(); i--;) {
  1450. if (!capturedVars.quickGet(i))
  1451. continue;
  1452. m_variables.local(i).makeTop();
  1453. }
  1454. } else {
  1455. for (size_t i = m_codeBlock->m_numVars; i--;) {
  1456. if (m_codeBlock->isCaptured(i))
  1457. m_variables.local(i).makeTop();
  1458. }
  1459. }
  1460. for (size_t i = m_variables.numberOfArguments(); i--;) {
  1461. if (m_codeBlock->isCaptured(argumentToOperand(i)))
  1462. m_variables.argument(i).makeTop();
  1463. }
  1464. }
  1465. inline void AbstractState::clobberStructures(unsigned indexInBlock)
  1466. {
  1467. if (!m_haveStructures)
  1468. return;
  1469. for (size_t i = indexInBlock + 1; i--;)
  1470. forNode(m_block->at(i)).clobberStructures();
  1471. for (size_t i = m_variables.numberOfArguments(); i--;)
  1472. m_variables.argument(i).clobberStructures();
  1473. for (size_t i = m_variables.numberOfLocals(); i--;)
  1474. m_variables.local(i).clobberStructures();
  1475. m_haveStructures = false;
  1476. m_didClobber = true;
  1477. }
  1478. inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node)
  1479. {
  1480. if (!node)
  1481. return false;
  1482. AbstractValue source;
  1483. if (node->variableAccessData()->isCaptured()) {
  1484. // If it's captured then we know that whatever value was stored into the variable last is the
  1485. // one we care about. This is true even if the variable at tail is dead, which might happen if
  1486. // the last thing we did to the variable was a GetLocal and then ended up now using the
  1487. // GetLocal's result.
  1488. source = inVariable;
  1489. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1490. dataLogF(" Transfering ");
  1491. source.dump(WTF::dataFile());
  1492. dataLogF(" from last access due to captured variable.\n");
  1493. #endif
  1494. } else {
  1495. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1496. dataLogF(" It's live, node @%u.\n", node->index());
  1497. #endif
  1498. switch (node->op()) {
  1499. case Phi:
  1500. case SetArgument:
  1501. case PhantomLocal:
  1502. case Flush:
  1503. // The block transfers the value from head to tail.
  1504. source = inVariable;
  1505. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1506. dataLogF(" Transfering ");
  1507. source.dump(WTF::dataFile());
  1508. dataLogF(" from head to tail.\n");
  1509. #endif
  1510. break;
  1511. case GetLocal:
  1512. // The block refines the value with additional speculations.
  1513. source = forNode(node);
  1514. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1515. dataLogF(" Refining to ");
  1516. source.dump(WTF::dataFile());
  1517. dataLogF("\n");
  1518. #endif
  1519. break;
  1520. case SetLocal:
  1521. // The block sets the variable, and potentially refines it, both
  1522. // before and after setting it.
  1523. if (node->variableAccessData()->shouldUseDoubleFormat()) {
  1524. // FIXME: This unnecessarily loses precision.
  1525. source.set(SpecDouble);
  1526. } else
  1527. source = forNode(node->child1());
  1528. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1529. dataLogF(" Setting to ");
  1530. source.dump(WTF::dataFile());
  1531. dataLogF("\n");
  1532. #endif
  1533. break;
  1534. default:
  1535. RELEASE_ASSERT_NOT_REACHED();
  1536. break;
  1537. }
  1538. }
  1539. if (destination == source) {
  1540. // Abstract execution did not change the output value of the variable, for this
  1541. // basic block, on this iteration.
  1542. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1543. dataLogF(" Not changed!\n");
  1544. #endif
  1545. return false;
  1546. }
  1547. // Abstract execution reached a new conclusion about the speculations reached about
  1548. // this variable after execution of this basic block. Update the state, and return
  1549. // true to indicate that the fixpoint must go on!
  1550. destination = source;
  1551. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1552. dataLogF(" Changed!\n");
  1553. #endif
  1554. return true;
  1555. }
  1556. inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
  1557. {
  1558. ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
  1559. ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
  1560. bool changed = false;
  1561. for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
  1562. AbstractValue& destination = to->valuesAtHead.argument(argument);
  1563. changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
  1564. }
  1565. for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
  1566. AbstractValue& destination = to->valuesAtHead.local(local);
  1567. changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
  1568. }
  1569. if (!to->cfaHasVisited)
  1570. changed = true;
  1571. to->cfaShouldRevisit |= changed;
  1572. return changed;
  1573. }
  1574. inline bool AbstractState::mergeToSuccessors(Graph& graph, BasicBlock* basicBlock)
  1575. {
  1576. Node* terminal = basicBlock->last();
  1577. ASSERT(terminal->isTerminal());
  1578. switch (terminal->op()) {
  1579. case Jump: {
  1580. ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
  1581. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1582. dataLogF(" Merging to block #%u.\n", terminal->takenBlockIndex());
  1583. #endif
  1584. return merge(basicBlock, graph.m_blocks[terminal->takenBlockIndex()].get());
  1585. }
  1586. case Branch: {
  1587. ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection);
  1588. bool changed = false;
  1589. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1590. dataLogF(" Merging to block #%u.\n", terminal->takenBlockIndex());
  1591. #endif
  1592. if (basicBlock->cfaBranchDirection != TakeFalse)
  1593. changed |= merge(basicBlock, graph.m_blocks[terminal->takenBlockIndex()].get());
  1594. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
  1595. dataLogF(" Merging to block #%u.\n", terminal->notTakenBlockIndex());
  1596. #endif
  1597. if (basicBlock->cfaBranchDirection != TakeTrue)
  1598. changed |= merge(basicBlock, graph.m_blocks[terminal->notTakenBlockIndex()].get());
  1599. return changed;
  1600. }
  1601. case Return:
  1602. case Throw:
  1603. case ThrowReferenceError:
  1604. ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
  1605. return false;
  1606. default:
  1607. RELEASE_ASSERT_NOT_REACHED();
  1608. return false;
  1609. }
  1610. }
  1611. inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, Node* destinationNode, Node* sourceNode)
  1612. {
  1613. if (!destinationNode)
  1614. return false;
  1615. ASSERT_UNUSED(sourceNode, sourceNode);
  1616. // FIXME: We could do some sparse conditional propagation here!
  1617. return destination.merge(source);
  1618. }
  1619. void AbstractState::dump(PrintStream& out)
  1620. {
  1621. bool first = true;
  1622. for (size_t i = 0; i < m_block->size(); ++i) {
  1623. Node* node = m_block->at(i);
  1624. AbstractValue& value = forNode(node);
  1625. if (value.isClear())
  1626. continue;
  1627. if (first)
  1628. first = false;
  1629. else
  1630. out.printf(" ");
  1631. out.printf("@%lu:", static_cast<unsigned long>(node->index()));
  1632. value.dump(out);
  1633. }
  1634. }
  1635. } } // namespace JSC::DFG
  1636. #endif // ENABLE(DFG_JIT)