1/* 2 * Copyright (C) 2013, 2014 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 26#ifndef DFGAbstractInterpreterInlines_h 27#define DFGAbstractInterpreterInlines_h 28 29#if ENABLE(DFG_JIT) 30 31#include "DFGAbstractInterpreter.h" 32#include "GetByIdStatus.h" 33#include "Operations.h" 34#include "PutByIdStatus.h" 35#include "StringObject.h" 36 37namespace JSC { namespace DFG { 38 39template<typename AbstractStateType> 40AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state) 41 : m_codeBlock(graph.m_codeBlock) 42 , m_graph(graph) 43 , m_state(state) 44{ 45} 46 47template<typename AbstractStateType> 48AbstractInterpreter<AbstractStateType>::~AbstractInterpreter() 49{ 50} 51 52template<typename AbstractStateType> 53typename AbstractInterpreter<AbstractStateType>::BooleanResult 54AbstractInterpreter<AbstractStateType>::booleanResult( 55 Node* node, AbstractValue& value) 56{ 57 JSValue childConst = value.value(); 58 if (childConst) { 59 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec())) 60 return DefinitelyTrue; 61 return DefinitelyFalse; 62 } 63 64 // Next check if we can fold because we know that the source is an object or string and does not equal undefined. 65 if (isCellSpeculation(value.m_type) 66 && value.m_currentKnownStructure.hasSingleton()) { 67 Structure* structure = value.m_currentKnownStructure.singleton(); 68 if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic)) 69 && structure->typeInfo().type() != StringType) 70 return DefinitelyTrue; 71 } 72 73 return UnknownBooleanResult; 74} 75 76template<typename AbstractStateType> 77bool AbstractInterpreter<AbstractStateType>::startExecuting(Node* node) 78{ 79 ASSERT(m_state.block()); 80 ASSERT(m_state.isValid()); 81 82 m_state.setDidClobber(false); 83 84 node->setCanExit(false); 85 86 return node->shouldGenerate(); 87} 88 89template<typename AbstractStateType> 90bool AbstractInterpreter<AbstractStateType>::startExecuting(unsigned indexInBlock) 91{ 92 return startExecuting(m_state.block()->at(indexInBlock)); 93} 94 95template<typename AbstractStateType> 96void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node) 97{ 98 DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse); 99} 100 101template<typename AbstractStateType> 102void AbstractInterpreter<AbstractStateType>::executeEdges(unsigned indexInBlock) 103{ 104 executeEdges(m_state.block()->at(indexInBlock)); 105} 106 107template<typename AbstractStateType> 108void AbstractInterpreter<AbstractStateType>::verifyEdge(Node*, Edge edge) 109{ 110 RELEASE_ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind()))); 111} 112 113template<typename AbstractStateType> 114void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node) 115{ 116 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge); 117} 118 119template<typename AbstractStateType> 120bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node) 121{ 122 if (!ASSERT_DISABLED) 123 verifyEdges(node); 124 125 m_state.createValueForNode(node); 126 127 switch (node->op()) { 128 case JSConstant: 129 case DoubleConstant: 130 case Int52Constant: 131 case WeakJSConstant: 132 case PhantomArguments: { 133 setBuiltInConstant(node, m_graph.valueOfJSConstant(node)); 134 break; 135 } 136 137 case Identity: { 138 forNode(node) = forNode(node->child1()); 139 break; 140 } 141 142 case GetArgument: { 143 ASSERT(m_graph.m_form == SSA); 144 VariableAccessData* variable = node->variableAccessData(); 145 AbstractValue& value = m_state.variables().operand(variable->local().offset()); 146 ASSERT(value.isHeapTop()); 147 FiltrationResult result = 148 value.filter(typeFilterFor(useKindFor(variable->flushFormat()))); 149 ASSERT_UNUSED(result, result == FiltrationOK); 150 forNode(node) = value; 151 break; 152 } 153 154 case ExtractOSREntryLocal: { 155 if (!(node->unlinkedLocal().isArgument()) 156 && m_graph.m_lazyVars.get(node->unlinkedLocal().toLocal())) { 157 // This is kind of pessimistic - we could know in some cases that the 158 // DFG code at the point of the OSR had already initialized the lazy 159 // variable. But maybe this is fine, since we're inserting OSR 160 // entrypoints very early in the pipeline - so any lazy initializations 161 // ought to be hoisted out anyway. 162 forNode(node).makeBytecodeTop(); 163 } else 164 forNode(node).makeHeapTop(); 165 break; 166 } 167 168 case GetLocal: { 169 VariableAccessData* variableAccessData = node->variableAccessData(); 170 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset()); 171 if (!variableAccessData->isCaptured()) { 172 if (value.isClear()) 173 node->setCanExit(true); 174 } 175 if (value.value()) 176 m_state.setFoundConstants(true); 177 forNode(node) = value; 178 break; 179 } 180 181 case GetLocalUnlinked: { 182 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset()); 183 if (value.value()) 184 m_state.setFoundConstants(true); 185 forNode(node) = value; 186 break; 187 } 188 189 case SetLocal: { 190 m_state.variables().operand(node->local().offset()) = forNode(node->child1()); 191 break; 192 } 193 194 case MovHint: { 195 // Don't need to do anything. A MovHint only informs us about what would have happened 196 // in bytecode, but this code is just concerned with what is actually happening during 197 // DFG execution. 198 break; 199 } 200 201 case SetArgument: 202 // Assert that the state of arguments has been set. 203 ASSERT(!m_state.block()->valuesAtHead.operand(node->local()).isClear()); 204 break; 205 206 case BitAnd: 207 case BitOr: 208 case BitXor: 209 case BitRShift: 210 case BitLShift: 211 case BitURShift: { 212 JSValue left = forNode(node->child1()).value(); 213 JSValue right = forNode(node->child2()).value(); 214 if (left && right && left.isInt32() && right.isInt32()) { 215 int32_t a = left.asInt32(); 216 int32_t b = right.asInt32(); 217 switch (node->op()) { 218 case BitAnd: 219 setConstant(node, JSValue(a & b)); 220 break; 221 case BitOr: 222 setConstant(node, JSValue(a | b)); 223 break; 224 case BitXor: 225 setConstant(node, JSValue(a ^ b)); 226 break; 227 case BitRShift: 228 setConstant(node, JSValue(a >> static_cast<uint32_t>(b))); 229 break; 230 case BitLShift: 231 setConstant(node, JSValue(a << static_cast<uint32_t>(b))); 232 break; 233 case BitURShift: 234 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b))); 235 break; 236 default: 237 RELEASE_ASSERT_NOT_REACHED(); 238 break; 239 } 240 break; 241 } 242 forNode(node).setType(SpecInt32); 243 break; 244 } 245 246 case UInt32ToNumber: { 247 JSValue child = forNode(node->child1()).value(); 248 if (doesOverflow(node->arithMode())) { 249 if (child && child.isInt32()) { 250 uint32_t value = child.asInt32(); 251 setConstant(node, jsNumber(value)); 252 break; 253 } 254 forNode(node).setType(SpecInt52AsDouble); 255 break; 256 } 257 if (child && child.isInt32()) { 258 int32_t value = child.asInt32(); 259 if (value >= 0) { 260 setConstant(node, jsNumber(value)); 261 break; 262 } 263 } 264 forNode(node).setType(SpecInt32); 265 node->setCanExit(true); 266 break; 267 } 268 269 case BooleanToNumber: { 270 JSValue concreteValue = forNode(node->child1()).value(); 271 if (concreteValue) { 272 if (concreteValue.isBoolean()) 273 setConstant(node, jsNumber(concreteValue.asBoolean())); 274 else 275 setConstant(node, concreteValue); 276 break; 277 } 278 AbstractValue& value = forNode(node); 279 value = forNode(node->child1()); 280 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean)) 281 m_state.setFoundConstants(true); 282 if (value.m_type & SpecBoolean) { 283 value.merge(SpecInt32); 284 value.filter(~SpecBoolean); 285 } 286 break; 287 } 288 289 case DoubleAsInt32: { 290 JSValue child = forNode(node->child1()).value(); 291 if (child && child.isNumber()) { 292 double asDouble = child.asNumber(); 293 int32_t asInt = JSC::toInt32(asDouble); 294 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) { 295 setConstant(node, JSValue(asInt)); 296 break; 297 } 298 } 299 node->setCanExit(true); 300 forNode(node).setType(SpecInt32); 301 break; 302 } 303 304 case ValueToInt32: { 305 JSValue child = forNode(node->child1()).value(); 306 if (child) { 307 if (child.isNumber()) { 308 if (child.isInt32()) 309 setConstant(node, child); 310 else 311 setConstant(node, JSValue(JSC::toInt32(child.asDouble()))); 312 break; 313 } 314 if (child.isBoolean()) { 315 setConstant(node, jsNumber(child.asBoolean())); 316 break; 317 } 318 if (child.isUndefinedOrNull()) { 319 setConstant(node, jsNumber(0)); 320 break; 321 } 322 } 323 324 forNode(node).setType(SpecInt32); 325 break; 326 } 327 328 case DoubleRep: { 329 JSValue child = forNode(node->child1()).value(); 330 if (child && child.isNumber()) { 331 setConstant(node, jsDoubleNumber(child.asNumber())); 332 break; 333 } 334 forNode(node).setType(forNode(node->child1()).m_type); 335 forNode(node).fixTypeForRepresentation(node); 336 break; 337 } 338 339 case Int52Rep: { 340 JSValue child = forNode(node->child1()).value(); 341 if (child && child.isMachineInt()) { 342 setConstant(node, child); 343 break; 344 } 345 346 forNode(node).setType(SpecInt32); 347 break; 348 } 349 350 case ValueRep: { 351 JSValue value = forNode(node->child1()).value(); 352 if (value) { 353 setConstant(node, value); 354 break; 355 } 356 357 forNode(node).setType(forNode(node->child1()).m_type & ~SpecDoubleImpureNaN); 358 forNode(node).fixTypeForRepresentation(node); 359 break; 360 } 361 362 case ValueAdd: { 363 ASSERT(node->binaryUseKind() == UntypedUse); 364 clobberWorld(node->origin.semantic, clobberLimit); 365 forNode(node).setType(SpecString | SpecBytecodeNumber); 366 break; 367 } 368 369 case ArithAdd: { 370 JSValue left = forNode(node->child1()).value(); 371 JSValue right = forNode(node->child2()).value(); 372 switch (node->binaryUseKind()) { 373 case Int32Use: 374 if (left && right && left.isInt32() && right.isInt32()) { 375 if (!shouldCheckOverflow(node->arithMode())) { 376 setConstant(node, jsNumber(left.asInt32() + right.asInt32())); 377 break; 378 } 379 JSValue result = jsNumber(left.asNumber() + right.asNumber()); 380 if (result.isInt32()) { 381 setConstant(node, result); 382 break; 383 } 384 } 385 forNode(node).setType(SpecInt32); 386 if (shouldCheckOverflow(node->arithMode())) 387 node->setCanExit(true); 388 break; 389 case Int52RepUse: 390 if (left && right && left.isMachineInt() && right.isMachineInt()) { 391 JSValue result = jsNumber(left.asMachineInt() + right.asMachineInt()); 392 if (result.isMachineInt()) { 393 setConstant(node, result); 394 break; 395 } 396 } 397 forNode(node).setType(SpecMachineInt); 398 if (!forNode(node->child1()).isType(SpecInt32) 399 || !forNode(node->child2()).isType(SpecInt32)) 400 node->setCanExit(true); 401 break; 402 case DoubleRepUse: 403 if (left && right && left.isNumber() && right.isNumber()) { 404 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber())); 405 break; 406 } 407 forNode(node).setType( 408 typeOfDoubleSum( 409 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 410 break; 411 default: 412 RELEASE_ASSERT_NOT_REACHED(); 413 break; 414 } 415 break; 416 } 417 418 case MakeRope: { 419 node->setCanExit(true); 420 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); 421 break; 422 } 423 424 case ArithSub: { 425 JSValue left = forNode(node->child1()).value(); 426 JSValue right = forNode(node->child2()).value(); 427 switch (node->binaryUseKind()) { 428 case Int32Use: 429 if (left && right && left.isInt32() && right.isInt32()) { 430 if (!shouldCheckOverflow(node->arithMode())) { 431 setConstant(node, jsNumber(left.asInt32() - right.asInt32())); 432 break; 433 } 434 JSValue result = jsNumber(left.asNumber() - right.asNumber()); 435 if (result.isInt32()) { 436 setConstant(node, result); 437 break; 438 } 439 } 440 forNode(node).setType(SpecInt32); 441 if (shouldCheckOverflow(node->arithMode())) 442 node->setCanExit(true); 443 break; 444 case Int52RepUse: 445 if (left && right && left.isMachineInt() && right.isMachineInt()) { 446 JSValue result = jsNumber(left.asMachineInt() - right.asMachineInt()); 447 if (result.isMachineInt() || !shouldCheckOverflow(node->arithMode())) { 448 setConstant(node, result); 449 break; 450 } 451 } 452 forNode(node).setType(SpecMachineInt); 453 if (!forNode(node->child1()).isType(SpecInt32) 454 || !forNode(node->child2()).isType(SpecInt32)) 455 node->setCanExit(true); 456 break; 457 case DoubleRepUse: 458 if (left && right && left.isNumber() && right.isNumber()) { 459 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber())); 460 break; 461 } 462 forNode(node).setType( 463 typeOfDoubleDifference( 464 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 465 break; 466 default: 467 RELEASE_ASSERT_NOT_REACHED(); 468 break; 469 } 470 break; 471 } 472 473 case ArithNegate: { 474 JSValue child = forNode(node->child1()).value(); 475 switch (node->child1().useKind()) { 476 case Int32Use: 477 if (child && child.isInt32()) { 478 if (!shouldCheckOverflow(node->arithMode())) { 479 setConstant(node, jsNumber(-child.asInt32())); 480 break; 481 } 482 double doubleResult; 483 if (shouldCheckNegativeZero(node->arithMode())) 484 doubleResult = -child.asNumber(); 485 else 486 doubleResult = 0 - child.asNumber(); 487 JSValue valueResult = jsNumber(doubleResult); 488 if (valueResult.isInt32()) { 489 setConstant(node, valueResult); 490 break; 491 } 492 } 493 forNode(node).setType(SpecInt32); 494 if (shouldCheckOverflow(node->arithMode())) 495 node->setCanExit(true); 496 break; 497 case Int52RepUse: 498 if (child && child.isMachineInt()) { 499 double doubleResult; 500 if (shouldCheckNegativeZero(node->arithMode())) 501 doubleResult = -child.asNumber(); 502 else 503 doubleResult = 0 - child.asNumber(); 504 JSValue valueResult = jsNumber(doubleResult); 505 if (valueResult.isMachineInt()) { 506 setConstant(node, valueResult); 507 break; 508 } 509 } 510 forNode(node).setType(SpecMachineInt); 511 if (m_state.forNode(node->child1()).couldBeType(SpecInt52)) 512 node->setCanExit(true); 513 if (shouldCheckNegativeZero(node->arithMode())) 514 node->setCanExit(true); 515 break; 516 case DoubleRepUse: 517 if (child && child.isNumber()) { 518 setConstant(node, jsDoubleNumber(-child.asNumber())); 519 break; 520 } 521 forNode(node).setType( 522 typeOfDoubleNegation( 523 forNode(node->child1()).m_type)); 524 break; 525 default: 526 RELEASE_ASSERT_NOT_REACHED(); 527 break; 528 } 529 break; 530 } 531 532 case ArithMul: { 533 JSValue left = forNode(node->child1()).value(); 534 JSValue right = forNode(node->child2()).value(); 535 switch (node->binaryUseKind()) { 536 case Int32Use: 537 if (left && right && left.isInt32() && right.isInt32()) { 538 if (!shouldCheckOverflow(node->arithMode())) { 539 setConstant(node, jsNumber(left.asInt32() * right.asInt32())); 540 break; 541 } 542 double doubleResult = left.asNumber() * right.asNumber(); 543 if (!shouldCheckNegativeZero(node->arithMode())) 544 doubleResult += 0; // Sanitizes zero. 545 JSValue valueResult = jsNumber(doubleResult); 546 if (valueResult.isInt32()) { 547 setConstant(node, valueResult); 548 break; 549 } 550 } 551 forNode(node).setType(SpecInt32); 552 if (shouldCheckOverflow(node->arithMode())) 553 node->setCanExit(true); 554 break; 555 case Int52RepUse: 556 if (left && right && left.isMachineInt() && right.isMachineInt()) { 557 double doubleResult = left.asNumber() * right.asNumber(); 558 if (!shouldCheckNegativeZero(node->arithMode())) 559 doubleResult += 0; 560 JSValue valueResult = jsNumber(doubleResult); 561 if (valueResult.isMachineInt()) { 562 setConstant(node, valueResult); 563 break; 564 } 565 } 566 forNode(node).setType(SpecMachineInt); 567 node->setCanExit(true); 568 break; 569 case DoubleRepUse: 570 if (left && right && left.isNumber() && right.isNumber()) { 571 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber())); 572 break; 573 } 574 forNode(node).setType( 575 typeOfDoubleProduct( 576 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 577 break; 578 default: 579 RELEASE_ASSERT_NOT_REACHED(); 580 break; 581 } 582 break; 583 } 584 585 case ArithDiv: { 586 JSValue left = forNode(node->child1()).value(); 587 JSValue right = forNode(node->child2()).value(); 588 switch (node->binaryUseKind()) { 589 case Int32Use: 590 if (left && right && left.isInt32() && right.isInt32()) { 591 double doubleResult = left.asNumber() / right.asNumber(); 592 if (!shouldCheckOverflow(node->arithMode())) 593 doubleResult = toInt32(doubleResult); 594 else if (!shouldCheckNegativeZero(node->arithMode())) 595 doubleResult += 0; // Sanitizes zero. 596 JSValue valueResult = jsNumber(doubleResult); 597 if (valueResult.isInt32()) { 598 setConstant(node, valueResult); 599 break; 600 } 601 } 602 forNode(node).setType(SpecInt32); 603 node->setCanExit(true); 604 break; 605 case DoubleRepUse: 606 if (left && right && left.isNumber() && right.isNumber()) { 607 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber())); 608 break; 609 } 610 forNode(node).setType( 611 typeOfDoubleQuotient( 612 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 613 break; 614 default: 615 RELEASE_ASSERT_NOT_REACHED(); 616 break; 617 } 618 break; 619 } 620 621 case ArithMod: { 622 JSValue left = forNode(node->child1()).value(); 623 JSValue right = forNode(node->child2()).value(); 624 switch (node->binaryUseKind()) { 625 case Int32Use: 626 if (left && right && left.isInt32() && right.isInt32()) { 627 double doubleResult = fmod(left.asNumber(), right.asNumber()); 628 if (!shouldCheckOverflow(node->arithMode())) 629 doubleResult = toInt32(doubleResult); 630 else if (!shouldCheckNegativeZero(node->arithMode())) 631 doubleResult += 0; // Sanitizes zero. 632 JSValue valueResult = jsNumber(doubleResult); 633 if (valueResult.isInt32()) { 634 setConstant(node, valueResult); 635 break; 636 } 637 } 638 forNode(node).setType(SpecInt32); 639 node->setCanExit(true); 640 break; 641 case DoubleRepUse: 642 if (left && right && left.isNumber() && right.isNumber()) { 643 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber()))); 644 break; 645 } 646 forNode(node).setType( 647 typeOfDoubleBinaryOp( 648 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 649 break; 650 default: 651 RELEASE_ASSERT_NOT_REACHED(); 652 break; 653 } 654 break; 655 } 656 657 case ArithMin: { 658 JSValue left = forNode(node->child1()).value(); 659 JSValue right = forNode(node->child2()).value(); 660 switch (node->binaryUseKind()) { 661 case Int32Use: 662 if (left && right && left.isInt32() && right.isInt32()) { 663 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32()))); 664 break; 665 } 666 forNode(node).setType(SpecInt32); 667 node->setCanExit(true); 668 break; 669 case DoubleRepUse: 670 if (left && right && left.isNumber() && right.isNumber()) { 671 double a = left.asNumber(); 672 double b = right.asNumber(); 673 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b))); 674 break; 675 } 676 forNode(node).setType( 677 typeOfDoubleMinMax( 678 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 679 break; 680 default: 681 RELEASE_ASSERT_NOT_REACHED(); 682 break; 683 } 684 break; 685 } 686 687 case ArithMax: { 688 JSValue left = forNode(node->child1()).value(); 689 JSValue right = forNode(node->child2()).value(); 690 switch (node->binaryUseKind()) { 691 case Int32Use: 692 if (left && right && left.isInt32() && right.isInt32()) { 693 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32()))); 694 break; 695 } 696 forNode(node).setType(SpecInt32); 697 node->setCanExit(true); 698 break; 699 case DoubleRepUse: 700 if (left && right && left.isNumber() && right.isNumber()) { 701 double a = left.asNumber(); 702 double b = right.asNumber(); 703 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b))); 704 break; 705 } 706 forNode(node).setType( 707 typeOfDoubleMinMax( 708 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 709 break; 710 default: 711 RELEASE_ASSERT_NOT_REACHED(); 712 break; 713 } 714 break; 715 } 716 717 case ArithAbs: { 718 JSValue child = forNode(node->child1()).value(); 719 switch (node->child1().useKind()) { 720 case Int32Use: 721 if (child && child.isInt32()) { 722 JSValue result = jsNumber(fabs(child.asNumber())); 723 if (result.isInt32()) { 724 setConstant(node, result); 725 break; 726 } 727 } 728 forNode(node).setType(SpecInt32); 729 node->setCanExit(true); 730 break; 731 case DoubleRepUse: 732 if (child && child.isNumber()) { 733 setConstant(node, jsDoubleNumber(child.asNumber())); 734 break; 735 } 736 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type)); 737 break; 738 default: 739 RELEASE_ASSERT_NOT_REACHED(); 740 break; 741 } 742 break; 743 } 744 745 case ArithSqrt: { 746 JSValue child = forNode(node->child1()).value(); 747 if (child && child.isNumber()) { 748 setConstant(node, jsDoubleNumber(sqrt(child.asNumber()))); 749 break; 750 } 751 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type)); 752 break; 753 } 754 755 case ArithFRound: { 756 JSValue child = forNode(node->child1()).value(); 757 if (child && child.isNumber()) { 758 setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber()))); 759 break; 760 } 761 forNode(node).setType(typeOfDoubleFRound(forNode(node->child1()).m_type)); 762 break; 763 } 764 765 case ArithSin: { 766 JSValue child = forNode(node->child1()).value(); 767 if (child && child.isNumber()) { 768 setConstant(node, jsDoubleNumber(sin(child.asNumber()))); 769 break; 770 } 771 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type)); 772 break; 773 } 774 775 case ArithCos: { 776 JSValue child = forNode(node->child1()).value(); 777 if (child && child.isNumber()) { 778 setConstant(node, jsDoubleNumber(cos(child.asNumber()))); 779 break; 780 } 781 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type)); 782 break; 783 } 784 785 case LogicalNot: { 786 switch (booleanResult(node, forNode(node->child1()))) { 787 case DefinitelyTrue: 788 setConstant(node, jsBoolean(false)); 789 break; 790 case DefinitelyFalse: 791 setConstant(node, jsBoolean(true)); 792 break; 793 default: 794 switch (node->child1().useKind()) { 795 case BooleanUse: 796 case Int32Use: 797 case DoubleRepUse: 798 case UntypedUse: 799 case StringUse: 800 break; 801 case ObjectOrOtherUse: 802 node->setCanExit(true); 803 break; 804 default: 805 RELEASE_ASSERT_NOT_REACHED(); 806 break; 807 } 808 forNode(node).setType(SpecBoolean); 809 break; 810 } 811 break; 812 } 813 814 case IsUndefined: 815 case IsBoolean: 816 case IsNumber: 817 case IsString: 818 case IsObject: 819 case IsFunction: { 820 node->setCanExit( 821 node->op() == IsUndefined 822 && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)); 823 JSValue child = forNode(node->child1()).value(); 824 if (child) { 825 bool constantWasSet = true; 826 switch (node->op()) { 827 case IsUndefined: 828 setConstant(node, jsBoolean( 829 child.isCell() 830 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic)) 831 : child.isUndefined())); 832 break; 833 case IsBoolean: 834 setConstant(node, jsBoolean(child.isBoolean())); 835 break; 836 case IsNumber: 837 setConstant(node, jsBoolean(child.isNumber())); 838 break; 839 case IsString: 840 setConstant(node, jsBoolean(isJSString(child))); 841 break; 842 case IsObject: 843 if (child.isNull() || !child.isObject()) { 844 setConstant(node, jsBoolean(child.isNull())); 845 break; 846 } 847 constantWasSet = false; 848 break; 849 default: 850 constantWasSet = false; 851 break; 852 } 853 if (constantWasSet) 854 break; 855 } 856 857 forNode(node).setType(SpecBoolean); 858 break; 859 } 860 861 case TypeOf: { 862 VM* vm = m_codeBlock->vm(); 863 JSValue child = forNode(node->child1()).value(); 864 AbstractValue& abstractChild = forNode(node->child1()); 865 if (child) { 866 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child); 867 setConstant(node, typeString); 868 break; 869 } 870 871 if (isFullNumberSpeculation(abstractChild.m_type)) { 872 setConstant(node, vm->smallStrings.numberString()); 873 break; 874 } 875 876 if (isStringSpeculation(abstractChild.m_type)) { 877 setConstant(node, vm->smallStrings.stringString()); 878 break; 879 } 880 881 if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) { 882 setConstant(node, vm->smallStrings.objectString()); 883 break; 884 } 885 886 if (isFunctionSpeculation(abstractChild.m_type)) { 887 setConstant(node, vm->smallStrings.functionString()); 888 break; 889 } 890 891 if (isBooleanSpeculation(abstractChild.m_type)) { 892 setConstant(node, vm->smallStrings.booleanString()); 893 break; 894 } 895 896 switch (node->child1().useKind()) { 897 case StringUse: 898 case CellUse: 899 node->setCanExit(true); 900 break; 901 case UntypedUse: 902 break; 903 default: 904 RELEASE_ASSERT_NOT_REACHED(); 905 break; 906 } 907 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); 908 break; 909 } 910 911 case CompareLess: 912 case CompareLessEq: 913 case CompareGreater: 914 case CompareGreaterEq: 915 case CompareEq: 916 case CompareEqConstant: { 917 JSValue leftConst = forNode(node->child1()).value(); 918 JSValue rightConst = forNode(node->child2()).value(); 919 if (leftConst && rightConst) { 920 if (leftConst.isNumber() && rightConst.isNumber()) { 921 double a = leftConst.asNumber(); 922 double b = rightConst.asNumber(); 923 switch (node->op()) { 924 case CompareLess: 925 setConstant(node, jsBoolean(a < b)); 926 break; 927 case CompareLessEq: 928 setConstant(node, jsBoolean(a <= b)); 929 break; 930 case CompareGreater: 931 setConstant(node, jsBoolean(a > b)); 932 break; 933 case CompareGreaterEq: 934 setConstant(node, jsBoolean(a >= b)); 935 break; 936 case CompareEq: 937 setConstant(node, jsBoolean(a == b)); 938 break; 939 default: 940 RELEASE_ASSERT_NOT_REACHED(); 941 break; 942 } 943 break; 944 } 945 946 if (node->op() == CompareEq && leftConst.isString() && rightConst.isString()) { 947 const StringImpl* a = asString(leftConst)->tryGetValueImpl(); 948 const StringImpl* b = asString(rightConst)->tryGetValueImpl(); 949 if (a && b) { 950 setConstant(node, jsBoolean(WTF::equal(a, b))); 951 break; 952 } 953 } 954 } 955 956 if (node->op() == CompareEqConstant || node->op() == CompareEq) { 957 SpeculatedType leftType = forNode(node->child1()).m_type; 958 SpeculatedType rightType = forNode(node->child2()).m_type; 959 if (!valuesCouldBeEqual(leftType, rightType)) { 960 setConstant(node, jsBoolean(false)); 961 break; 962 } 963 } 964 965 forNode(node).setType(SpecBoolean); 966 967 // This is overly conservative. But the only thing this prevents is store elimination, 968 // and how likely is it, really, that you'll have redundant stores across a comparison 969 // operation? Comparison operations are typically at the end of basic blocks, so 970 // unless we have global store elimination (super unlikely given how unprofitable that 971 // optimization is to begin with), you aren't going to be wanting to store eliminate 972 // across an equality op. 973 node->setCanExit(true); 974 break; 975 } 976 977 case CompareStrictEq: { 978 Node* leftNode = node->child1().node(); 979 Node* rightNode = node->child2().node(); 980 JSValue left = forNode(leftNode).value(); 981 JSValue right = forNode(rightNode).value(); 982 if (left && right) { 983 if (left.isString() && right.isString()) { 984 // We need this case because JSValue::strictEqual is otherwise too racy for 985 // string comparisons. 986 const StringImpl* a = asString(left)->tryGetValueImpl(); 987 const StringImpl* b = asString(right)->tryGetValueImpl(); 988 if (a && b) { 989 setConstant(node, jsBoolean(WTF::equal(a, b))); 990 break; 991 } 992 } else { 993 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right))); 994 break; 995 } 996 } 997 998 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type); 999 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type); 1000 if (!(leftLUB & rightLUB)) { 1001 setConstant(node, jsBoolean(false)); 1002 break; 1003 } 1004 1005 forNode(node).setType(SpecBoolean); 1006 node->setCanExit(true); // This is overly conservative. 1007 break; 1008 } 1009 1010 case StringCharCodeAt: 1011 node->setCanExit(true); 1012 forNode(node).setType(SpecInt32); 1013 break; 1014 1015 case StringFromCharCode: 1016 forNode(node).setType(SpecString); 1017 break; 1018 1019 case StringCharAt: 1020 node->setCanExit(true); 1021 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); 1022 break; 1023 1024 case GetByVal: { 1025 node->setCanExit(true); 1026 switch (node->arrayMode().type()) { 1027 case Array::SelectUsingPredictions: 1028 case Array::Unprofiled: 1029 case Array::Undecided: 1030 RELEASE_ASSERT_NOT_REACHED(); 1031 break; 1032 case Array::ForceExit: 1033 m_state.setIsValid(false); 1034 break; 1035 case Array::Generic: 1036 clobberWorld(node->origin.semantic, clobberLimit); 1037 forNode(node).makeHeapTop(); 1038 break; 1039 case Array::String: 1040 if (node->arrayMode().isOutOfBounds()) { 1041 // If the watchpoint was still valid we could totally set this to be 1042 // SpecString | SpecOther. Except that we'd have to be careful. If we 1043 // tested the watchpoint state here then it could change by the time 1044 // we got to the backend. So to do this right, we'd have to get the 1045 // fixup phase to check the watchpoint state and then bake into the 1046 // GetByVal operation the fact that we're using a watchpoint, using 1047 // something like Array::SaneChain (except not quite, because that 1048 // implies an in-bounds access). None of this feels like it's worth it, 1049 // so we're going with TOP for now. The same thing applies to 1050 // clobbering the world. 1051 clobberWorld(node->origin.semantic, clobberLimit); 1052 forNode(node).makeHeapTop(); 1053 } else 1054 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); 1055 break; 1056 case Array::Arguments: 1057 forNode(node).makeHeapTop(); 1058 break; 1059 case Array::Int32: 1060 if (node->arrayMode().isOutOfBounds()) { 1061 clobberWorld(node->origin.semantic, clobberLimit); 1062 forNode(node).makeHeapTop(); 1063 } else 1064 forNode(node).setType(SpecInt32); 1065 break; 1066 case Array::Double: 1067 if (node->arrayMode().isOutOfBounds()) { 1068 clobberWorld(node->origin.semantic, clobberLimit); 1069 forNode(node).makeHeapTop(); 1070 } else if (node->arrayMode().isSaneChain()) 1071 forNode(node).setType(SpecBytecodeDouble); 1072 else 1073 forNode(node).setType(SpecDoubleReal); 1074 break; 1075 case Array::Contiguous: 1076 case Array::ArrayStorage: 1077 case Array::SlowPutArrayStorage: 1078 if (node->arrayMode().isOutOfBounds()) 1079 clobberWorld(node->origin.semantic, clobberLimit); 1080 forNode(node).makeHeapTop(); 1081 break; 1082 case Array::Int8Array: 1083 forNode(node).setType(SpecInt32); 1084 break; 1085 case Array::Int16Array: 1086 forNode(node).setType(SpecInt32); 1087 break; 1088 case Array::Int32Array: 1089 forNode(node).setType(SpecInt32); 1090 break; 1091 case Array::Uint8Array: 1092 forNode(node).setType(SpecInt32); 1093 break; 1094 case Array::Uint8ClampedArray: 1095 forNode(node).setType(SpecInt32); 1096 break; 1097 case Array::Uint16Array: 1098 forNode(node).setType(SpecInt32); 1099 break; 1100 case Array::Uint32Array: 1101 if (node->shouldSpeculateInt32()) 1102 forNode(node).setType(SpecInt32); 1103 else if (enableInt52() && node->shouldSpeculateMachineInt()) 1104 forNode(node).setType(SpecInt52); 1105 else 1106 forNode(node).setType(SpecInt52AsDouble); 1107 break; 1108 case Array::Float32Array: 1109 forNode(node).setType(SpecFullDouble); 1110 break; 1111 case Array::Float64Array: 1112 forNode(node).setType(SpecFullDouble); 1113 break; 1114 default: 1115 RELEASE_ASSERT_NOT_REACHED(); 1116 break; 1117 } 1118 break; 1119 } 1120 1121 case PutByValDirect: 1122 case PutByVal: 1123 case PutByValAlias: { 1124 node->setCanExit(true); 1125 switch (node->arrayMode().modeForPut().type()) { 1126 case Array::ForceExit: 1127 m_state.setIsValid(false); 1128 break; 1129 case Array::Generic: 1130 clobberWorld(node->origin.semantic, clobberLimit); 1131 break; 1132 case Array::Int32: 1133 if (node->arrayMode().isOutOfBounds()) 1134 clobberWorld(node->origin.semantic, clobberLimit); 1135 break; 1136 case Array::Double: 1137 if (node->arrayMode().isOutOfBounds()) 1138 clobberWorld(node->origin.semantic, clobberLimit); 1139 break; 1140 case Array::Contiguous: 1141 case Array::ArrayStorage: 1142 if (node->arrayMode().isOutOfBounds()) 1143 clobberWorld(node->origin.semantic, clobberLimit); 1144 break; 1145 case Array::SlowPutArrayStorage: 1146 if (node->arrayMode().mayStoreToHole()) 1147 clobberWorld(node->origin.semantic, clobberLimit); 1148 break; 1149 default: 1150 break; 1151 } 1152 break; 1153 } 1154 1155 case ArrayPush: 1156 node->setCanExit(true); 1157 clobberWorld(node->origin.semantic, clobberLimit); 1158 forNode(node).setType(SpecBytecodeNumber); 1159 break; 1160 1161 case ArrayPop: 1162 node->setCanExit(true); 1163 clobberWorld(node->origin.semantic, clobberLimit); 1164 forNode(node).makeHeapTop(); 1165 break; 1166 1167 case RegExpExec: 1168 forNode(node).makeHeapTop(); 1169 break; 1170 1171 case RegExpTest: 1172 forNode(node).setType(SpecBoolean); 1173 break; 1174 1175 case Jump: 1176 break; 1177 1178 case Branch: { 1179 Node* child = node->child1().node(); 1180 BooleanResult result = booleanResult(node, forNode(child)); 1181 if (result == DefinitelyTrue) { 1182 m_state.setBranchDirection(TakeTrue); 1183 break; 1184 } 1185 if (result == DefinitelyFalse) { 1186 m_state.setBranchDirection(TakeFalse); 1187 break; 1188 } 1189 // FIXME: The above handles the trivial cases of sparse conditional 1190 // constant propagation, but we can do better: 1191 // We can specialize the source variable's value on each direction of 1192 // the branch. 1193 node->setCanExit(true); // This is overly conservative. 1194 m_state.setBranchDirection(TakeBoth); 1195 break; 1196 } 1197 1198 case Switch: { 1199 // Nothing to do for now. 1200 // FIXME: Do sparse conditional things. 1201 break; 1202 } 1203 1204 case Return: 1205 m_state.setIsValid(false); 1206 break; 1207 1208 case Throw: 1209 case ThrowReferenceError: 1210 m_state.setIsValid(false); 1211 node->setCanExit(true); 1212 break; 1213 1214 case ToPrimitive: { 1215 JSValue childConst = forNode(node->child1()).value(); 1216 if (childConst && childConst.isNumber()) { 1217 setConstant(node, childConst); 1218 break; 1219 } 1220 1221 ASSERT(node->child1().useKind() == UntypedUse); 1222 1223 if (!forNode(node->child1()).m_type) { 1224 m_state.setIsValid(false); 1225 break; 1226 } 1227 1228 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString))) { 1229 m_state.setFoundConstants(true); 1230 forNode(node) = forNode(node->child1()); 1231 break; 1232 } 1233 1234 clobberWorld(node->origin.semantic, clobberLimit); 1235 1236 forNode(node).setType((SpecHeapTop & ~SpecCell) | SpecString); 1237 break; 1238 } 1239 1240 case ToString: { 1241 switch (node->child1().useKind()) { 1242 case StringObjectUse: 1243 // This also filters that the StringObject has the primordial StringObject 1244 // structure. 1245 filter( 1246 node->child1(), 1247 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure()); 1248 node->setCanExit(true); // We could be more precise but it's likely not worth it. 1249 break; 1250 case StringOrStringObjectUse: 1251 node->setCanExit(true); // We could be more precise but it's likely not worth it. 1252 break; 1253 case CellUse: 1254 case UntypedUse: 1255 clobberWorld(node->origin.semantic, clobberLimit); 1256 break; 1257 default: 1258 RELEASE_ASSERT_NOT_REACHED(); 1259 break; 1260 } 1261 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); 1262 break; 1263 } 1264 1265 case NewStringObject: { 1266 ASSERT(node->structure()->classInfo() == StringObject::info()); 1267 forNode(node).set(m_graph, node->structure()); 1268 break; 1269 } 1270 1271 case NewArray: 1272 node->setCanExit(true); 1273 forNode(node).set( 1274 m_graph, 1275 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())); 1276 m_state.setHaveStructures(true); 1277 break; 1278 1279 case NewArrayBuffer: 1280 node->setCanExit(true); 1281 forNode(node).set( 1282 m_graph, 1283 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())); 1284 m_state.setHaveStructures(true); 1285 break; 1286 1287 case NewArrayWithSize: 1288 node->setCanExit(true); 1289 forNode(node).setType(SpecArray); 1290 m_state.setHaveStructures(true); 1291 break; 1292 1293 case NewTypedArray: 1294 switch (node->child1().useKind()) { 1295 case Int32Use: 1296 break; 1297 case UntypedUse: 1298 clobberWorld(node->origin.semantic, clobberLimit); 1299 break; 1300 default: 1301 RELEASE_ASSERT_NOT_REACHED(); 1302 break; 1303 } 1304 forNode(node).set( 1305 m_graph, 1306 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure( 1307 node->typedArrayType())); 1308 m_state.setHaveStructures(true); 1309 break; 1310 1311 case NewRegexp: 1312 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure()); 1313 m_state.setHaveStructures(true); 1314 break; 1315 1316 case ToThis: { 1317 AbstractValue& source = forNode(node->child1()); 1318 AbstractValue& destination = forNode(node); 1319 1320 if (m_graph.executableFor(node->origin.semantic)->isStrictMode()) 1321 destination.makeHeapTop(); 1322 else { 1323 destination = source; 1324 destination.merge(SpecObject); 1325 } 1326 break; 1327 } 1328 1329 case CreateThis: { 1330 forNode(node).setType(SpecFinalObject); 1331 break; 1332 } 1333 1334 case AllocationProfileWatchpoint: 1335 node->setCanExit(true); 1336 break; 1337 1338 case NewObject: 1339 ASSERT(node->structure()); 1340 forNode(node).set(m_graph, node->structure()); 1341 m_state.setHaveStructures(true); 1342 break; 1343 1344 case CreateActivation: 1345 forNode(node).set( 1346 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure()); 1347 m_state.setHaveStructures(true); 1348 break; 1349 1350 case FunctionReentryWatchpoint: 1351 case TypedArrayWatchpoint: 1352 break; 1353 1354 case CreateArguments: 1355 forNode(node) = forNode(node->child1()); 1356 forNode(node).filter(~SpecEmpty); 1357 forNode(node).merge(SpecArguments); 1358 break; 1359 1360 case TearOffActivation: 1361 case TearOffArguments: 1362 // Does nothing that is user-visible. 1363 break; 1364 1365 case CheckArgumentsNotCreated: 1366 if (isEmptySpeculation( 1367 m_state.variables().operand( 1368 m_graph.argumentsRegisterFor(node->origin.semantic).offset()).m_type)) 1369 m_state.setFoundConstants(true); 1370 else 1371 node->setCanExit(true); 1372 break; 1373 1374 case GetMyArgumentsLength: 1375 // We know that this executable does not escape its arguments, so we can optimize 1376 // the arguments a bit. Note that this is not sufficient to force constant folding 1377 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation. 1378 // We perform further optimizations on this later on. 1379 if (node->origin.semantic.inlineCallFrame) { 1380 forNode(node).set( 1381 m_graph, jsNumber(node->origin.semantic.inlineCallFrame->arguments.size() - 1)); 1382 } else 1383 forNode(node).setType(SpecInt32); 1384 node->setCanExit( 1385 !isEmptySpeculation( 1386 m_state.variables().operand( 1387 m_graph.argumentsRegisterFor(node->origin.semantic)).m_type)); 1388 break; 1389 1390 case GetMyArgumentsLengthSafe: 1391 // This potentially clobbers all structures if the arguments object had a getter 1392 // installed on the length property. 1393 clobberWorld(node->origin.semantic, clobberLimit); 1394 // We currently make no guarantee about what this returns because it does not 1395 // speculate that the length property is actually a length. 1396 forNode(node).makeHeapTop(); 1397 break; 1398 1399 case GetMyArgumentByVal: 1400 node->setCanExit(true); 1401 // We know that this executable does not escape its arguments, so we can optimize 1402 // the arguments a bit. Note that this ends up being further optimized by the 1403 // ArgumentsSimplificationPhase. 1404 forNode(node).makeHeapTop(); 1405 break; 1406 1407 case GetMyArgumentByValSafe: 1408 node->setCanExit(true); 1409 // This potentially clobbers all structures if the property we're accessing has 1410 // a getter. We don't speculate against this. 1411 clobberWorld(node->origin.semantic, clobberLimit); 1412 // And the result is unknown. 1413 forNode(node).makeHeapTop(); 1414 break; 1415 1416 case NewFunction: { 1417 AbstractValue& value = forNode(node); 1418 value = forNode(node->child1()); 1419 1420 if (!(value.m_type & SpecEmpty)) { 1421 m_state.setFoundConstants(true); 1422 break; 1423 } 1424 1425 value.setType((value.m_type & ~SpecEmpty) | SpecFunction); 1426 break; 1427 } 1428 1429 case NewFunctionExpression: 1430 case NewFunctionNoCheck: 1431 forNode(node).set( 1432 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure()); 1433 m_state.setHaveStructures(true); 1434 break; 1435 1436 case GetCallee: 1437 forNode(node).setType(SpecFunction); 1438 break; 1439 1440 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 1441 case GetMyScope: 1442 case SkipTopScope: 1443 forNode(node).setType(SpecObjectOther); 1444 break; 1445 1446 case SkipScope: { 1447 JSValue child = forNode(node->child1()).value(); 1448 if (child) { 1449 setConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next())); 1450 break; 1451 } 1452 forNode(node).setType(SpecObjectOther); 1453 break; 1454 } 1455 1456 case GetClosureRegisters: 1457 forNode(node).clear(); // The result is not a JS value. 1458 break; 1459 1460 case GetClosureVar: 1461 forNode(node).makeHeapTop(); 1462 break; 1463 1464 case PutClosureVar: 1465 clobberCapturedVars(node->origin.semantic); 1466 break; 1467 1468 case GetById: 1469 case GetByIdFlush: 1470 node->setCanExit(true); 1471 if (!node->prediction()) { 1472 m_state.setIsValid(false); 1473 break; 1474 } 1475 if (isCellSpeculation(node->child1()->prediction())) { 1476 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) { 1477 GetByIdStatus status = GetByIdStatus::computeFor( 1478 m_graph.m_vm, structure, 1479 m_graph.identifiers()[node->identifierNumber()]); 1480 if (status.isSimple() && status.numVariants() == 1) { 1481 // Assert things that we can't handle and that the computeFor() method 1482 // above won't be able to return. 1483 ASSERT(status[0].structureSet().size() == 1); 1484 ASSERT(!status[0].chain()); 1485 1486 if (status[0].specificValue()) 1487 setConstant(node, status[0].specificValue()); 1488 else 1489 forNode(node).makeHeapTop(); 1490 filter(node->child1(), status[0].structureSet()); 1491 1492 m_state.setFoundConstants(true); 1493 m_state.setHaveStructures(true); 1494 break; 1495 } 1496 } 1497 } 1498 clobberWorld(node->origin.semantic, clobberLimit); 1499 forNode(node).makeHeapTop(); 1500 break; 1501 1502 case GetArrayLength: 1503 node->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough. 1504 forNode(node).setType(SpecInt32); 1505 break; 1506 1507 case CheckExecutable: { 1508 // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks 1509 // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200 1510 // FIXME: We could eliminate these entirely if we know the exact value that flows into this. 1511 // https://bugs.webkit.org/show_bug.cgi?id=106201 1512 node->setCanExit(true); 1513 break; 1514 } 1515 1516 case CheckStructure: { 1517 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes). 1518 AbstractValue& value = forNode(node->child1()); 1519 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this. 1520 1521 StructureSet& set = node->structureSet(); 1522 1523 if (value.m_currentKnownStructure.isSubsetOf(set)) { 1524 m_state.setFoundConstants(true); 1525 break; 1526 } 1527 1528 node->setCanExit(true); 1529 m_state.setHaveStructures(true); 1530 1531 // If this structure check is attempting to prove knowledge already held in 1532 // the futurePossibleStructure set then the constant folding phase should 1533 // turn this into a watchpoint instead. 1534 if (value.m_futurePossibleStructure.isSubsetOf(set) 1535 && value.m_futurePossibleStructure.hasSingleton()) { 1536 m_state.setFoundConstants(true); 1537 filter(value, value.m_futurePossibleStructure.singleton()); 1538 break; 1539 } 1540 1541 filter(value, set); 1542 break; 1543 } 1544 1545 case StructureTransitionWatchpoint: { 1546 AbstractValue& value = forNode(node->child1()); 1547 1548 filter(value, node->structure()); 1549 m_state.setHaveStructures(true); 1550 node->setCanExit(true); 1551 break; 1552 } 1553 1554 case PutStructure: 1555 case PhantomPutStructure: 1556 if (!forNode(node->child1()).m_currentKnownStructure.isClear()) { 1557 clobberStructures(clobberLimit); 1558 forNode(node->child1()).set(m_graph, node->structureTransitionData().newStructure); 1559 m_state.setHaveStructures(true); 1560 } 1561 break; 1562 case GetButterfly: 1563 case AllocatePropertyStorage: 1564 case ReallocatePropertyStorage: 1565 forNode(node).clear(); // The result is not a JS value. 1566 break; 1567 case CheckArray: { 1568 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) { 1569 m_state.setFoundConstants(true); 1570 break; 1571 } 1572 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. 1573 switch (node->arrayMode().type()) { 1574 case Array::String: 1575 filter(node->child1(), SpecString); 1576 break; 1577 case Array::Int32: 1578 case Array::Double: 1579 case Array::Contiguous: 1580 case Array::ArrayStorage: 1581 case Array::SlowPutArrayStorage: 1582 break; 1583 case Array::Arguments: 1584 filter(node->child1(), SpecArguments); 1585 break; 1586 case Array::Int8Array: 1587 filter(node->child1(), SpecInt8Array); 1588 break; 1589 case Array::Int16Array: 1590 filter(node->child1(), SpecInt16Array); 1591 break; 1592 case Array::Int32Array: 1593 filter(node->child1(), SpecInt32Array); 1594 break; 1595 case Array::Uint8Array: 1596 filter(node->child1(), SpecUint8Array); 1597 break; 1598 case Array::Uint8ClampedArray: 1599 filter(node->child1(), SpecUint8ClampedArray); 1600 break; 1601 case Array::Uint16Array: 1602 filter(node->child1(), SpecUint16Array); 1603 break; 1604 case Array::Uint32Array: 1605 filter(node->child1(), SpecUint32Array); 1606 break; 1607 case Array::Float32Array: 1608 filter(node->child1(), SpecFloat32Array); 1609 break; 1610 case Array::Float64Array: 1611 filter(node->child1(), SpecFloat64Array); 1612 break; 1613 default: 1614 RELEASE_ASSERT_NOT_REACHED(); 1615 break; 1616 } 1617 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering()); 1618 m_state.setHaveStructures(true); 1619 break; 1620 } 1621 case Arrayify: { 1622 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) { 1623 m_state.setFoundConstants(true); 1624 break; 1625 } 1626 ASSERT(node->arrayMode().conversion() == Array::Convert 1627 || node->arrayMode().conversion() == Array::RageConvert); 1628 node->setCanExit(true); 1629 clobberStructures(clobberLimit); 1630 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering()); 1631 m_state.setHaveStructures(true); 1632 break; 1633 } 1634 case ArrayifyToStructure: { 1635 AbstractValue& value = forNode(node->child1()); 1636 StructureSet set = node->structure(); 1637 if (value.m_futurePossibleStructure.isSubsetOf(set) 1638 || value.m_currentKnownStructure.isSubsetOf(set)) 1639 m_state.setFoundConstants(true); 1640 node->setCanExit(true); 1641 clobberStructures(clobberLimit); 1642 filter(value, set); 1643 m_state.setHaveStructures(true); 1644 break; 1645 } 1646 case GetIndexedPropertyStorage: 1647 case ConstantStoragePointer: { 1648 forNode(node).clear(); 1649 break; 1650 } 1651 1652 case GetTypedArrayByteOffset: { 1653 forNode(node).setType(SpecInt32); 1654 break; 1655 } 1656 1657 case GetByOffset: { 1658 forNode(node).makeHeapTop(); 1659 break; 1660 } 1661 1662 case MultiGetByOffset: { 1663 AbstractValue& value = forNode(node->child1()); 1664 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this. 1665 1666 if (Structure* structure = value.bestProvenStructure()) { 1667 bool done = false; 1668 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) { 1669 const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i]; 1670 if (!variant.structureSet().contains(structure)) 1671 continue; 1672 1673 if (variant.chain()) 1674 break; 1675 1676 filter(value, structure); 1677 forNode(node).makeHeapTop(); 1678 m_state.setFoundConstants(true); 1679 done = true; 1680 break; 1681 } 1682 if (done) 1683 break; 1684 } 1685 1686 StructureSet set; 1687 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) 1688 set.addAll(node->multiGetByOffsetData().variants[i].structureSet()); 1689 1690 filter(node->child1(), set); 1691 forNode(node).makeHeapTop(); 1692 break; 1693 } 1694 1695 case PutByOffset: { 1696 break; 1697 } 1698 1699 case MultiPutByOffset: { 1700 AbstractValue& value = forNode(node->child1()); 1701 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this. 1702 1703 if (Structure* structure = value.bestProvenStructure()) { 1704 bool done = false; 1705 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) { 1706 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i]; 1707 if (variant.oldStructure() != structure) 1708 continue; 1709 1710 if (variant.kind() == PutByIdVariant::Replace) { 1711 filter(node->child1(), structure); 1712 m_state.setFoundConstants(true); 1713 m_state.setHaveStructures(true); 1714 done = true; 1715 break; 1716 } 1717 1718 ASSERT(variant.kind() == PutByIdVariant::Transition); 1719 clobberStructures(clobberLimit); 1720 forNode(node->child1()).set(m_graph, variant.newStructure()); 1721 m_state.setFoundConstants(true); 1722 m_state.setHaveStructures(true); 1723 done = true; 1724 break; 1725 } 1726 if (done) 1727 break; 1728 } 1729 1730 clobberStructures(clobberLimit); 1731 1732 StructureSet newSet; 1733 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) { 1734 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i]; 1735 if (variant.kind() == PutByIdVariant::Replace) { 1736 if (value.m_currentKnownStructure.contains(variant.structure())) 1737 newSet.addAll(variant.structure()); 1738 continue; 1739 } 1740 ASSERT(variant.kind() == PutByIdVariant::Transition); 1741 if (value.m_currentKnownStructure.contains(variant.oldStructure())) 1742 newSet.addAll(variant.newStructure()); 1743 } 1744 1745 // Use filter(value, set) as a way of setting the structure set. This works because 1746 // we would have already made the set be TOP before this. Filtering top is another 1747 // way of setting. 1748 filter(node->child1(), newSet); 1749 break; 1750 } 1751 1752 case CheckFunction: { 1753 JSValue value = forNode(node->child1()).value(); 1754 if (value == node->function()) { 1755 m_state.setFoundConstants(true); 1756 ASSERT(value); 1757 break; 1758 } 1759 1760 node->setCanExit(true); // Lies! We can do better. 1761 filterByValue(node->child1(), node->function()); 1762 break; 1763 } 1764 1765 case CheckInBounds: { 1766 JSValue left = forNode(node->child1()).value(); 1767 JSValue right = forNode(node->child2()).value(); 1768 if (left && right && left.isInt32() && right.isInt32() 1769 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) { 1770 m_state.setFoundConstants(true); 1771 break; 1772 } 1773 1774 node->setCanExit(true); 1775 break; 1776 } 1777 1778 case PutById: 1779 case PutByIdFlush: 1780 case PutByIdDirect: 1781 node->setCanExit(true); 1782 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) { 1783 PutByIdStatus status = PutByIdStatus::computeFor( 1784 m_graph.m_vm, 1785 m_graph.globalObjectFor(node->origin.semantic), 1786 structure, 1787 m_graph.identifiers()[node->identifierNumber()], 1788 node->op() == PutByIdDirect); 1789 if (status.isSimple() && status.numVariants() == 1) { 1790 if (status[0].kind() == PutByIdVariant::Replace) { 1791 filter(node->child1(), structure); 1792 m_state.setFoundConstants(true); 1793 m_state.setHaveStructures(true); 1794 break; 1795 } 1796 if (status[0].kind() == PutByIdVariant::Transition) { 1797 clobberStructures(clobberLimit); 1798 forNode(node->child1()).set(m_graph, status[0].newStructure()); 1799 m_state.setHaveStructures(true); 1800 m_state.setFoundConstants(true); 1801 break; 1802 } 1803 } 1804 } 1805 clobberWorld(node->origin.semantic, clobberLimit); 1806 break; 1807 1808 case In: 1809 // FIXME: We can determine when the property definitely exists based on abstract 1810 // value information. 1811 clobberWorld(node->origin.semantic, clobberLimit); 1812 forNode(node).setType(SpecBoolean); 1813 break; 1814 1815 case GetGlobalVar: 1816 forNode(node).makeHeapTop(); 1817 break; 1818 1819 case VariableWatchpoint: 1820 case VarInjectionWatchpoint: 1821 node->setCanExit(true); 1822 break; 1823 1824 case PutGlobalVar: 1825 case NotifyWrite: 1826 break; 1827 1828 case CheckHasInstance: 1829 node->setCanExit(true); 1830 // Sadly, we don't propagate the fact that we've done CheckHasInstance 1831 break; 1832 1833 case InstanceOf: 1834 node->setCanExit(true); 1835 // Again, sadly, we don't propagate the fact that we've done InstanceOf 1836 forNode(node).setType(SpecBoolean); 1837 break; 1838 1839 case Phi: 1840 RELEASE_ASSERT(m_graph.m_form == SSA); 1841 // The state of this node would have already been decided. 1842 break; 1843 1844 case Upsilon: { 1845 m_state.createValueForNode(node->phi()); 1846 AbstractValue& value = forNode(node->child1()); 1847 forNode(node) = value; 1848 forNode(node->phi()) = value; 1849 break; 1850 } 1851 1852 case Flush: 1853 case PhantomLocal: 1854 break; 1855 1856 case Call: 1857 case Construct: 1858 node->setCanExit(true); 1859 clobberWorld(node->origin.semantic, clobberLimit); 1860 forNode(node).makeHeapTop(); 1861 break; 1862 1863 case ForceOSRExit: 1864 node->setCanExit(true); 1865 m_state.setIsValid(false); 1866 break; 1867 1868 case InvalidationPoint: 1869 node->setCanExit(true); 1870 break; 1871 1872 case CheckWatchdogTimer: 1873 node->setCanExit(true); 1874 break; 1875 1876 case Breakpoint: 1877 case ProfileWillCall: 1878 case ProfileDidCall: 1879 case Phantom: 1880 case HardPhantom: 1881 case Check: 1882 case CountExecution: 1883 case CheckTierUpInLoop: 1884 case CheckTierUpAtReturn: 1885 break; 1886 1887 case StoreBarrier: { 1888 filter(node->child1(), SpecCell); 1889 break; 1890 } 1891 1892 case StoreBarrierWithNullCheck: { 1893 break; 1894 } 1895 1896 case CheckTierUpAndOSREnter: 1897 case LoopHint: 1898 // We pretend that it can exit because it may want to get all state. 1899 node->setCanExit(true); 1900 break; 1901 1902 case ZombieHint: 1903 case Unreachable: 1904 case LastNodeType: 1905 case ArithIMul: 1906 case FiatInt52: 1907 RELEASE_ASSERT_NOT_REACHED(); 1908 break; 1909 } 1910 1911 return m_state.isValid(); 1912} 1913 1914template<typename AbstractStateType> 1915bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock) 1916{ 1917 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock)); 1918} 1919 1920template<typename AbstractStateType> 1921bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock) 1922{ 1923 Node* node = m_state.block()->at(indexInBlock); 1924 if (!startExecuting(node)) 1925 return true; 1926 1927 executeEdges(node); 1928 return executeEffects(indexInBlock, node); 1929} 1930 1931template<typename AbstractStateType> 1932bool AbstractInterpreter<AbstractStateType>::execute(Node* node) 1933{ 1934 if (!startExecuting(node)) 1935 return true; 1936 1937 executeEdges(node); 1938 return executeEffects(UINT_MAX, node); 1939} 1940 1941template<typename AbstractStateType> 1942void AbstractInterpreter<AbstractStateType>::clobberWorld( 1943 const CodeOrigin& codeOrigin, unsigned clobberLimit) 1944{ 1945 clobberCapturedVars(codeOrigin); 1946 clobberStructures(clobberLimit); 1947} 1948 1949template<typename AbstractStateType> 1950void AbstractInterpreter<AbstractStateType>::clobberCapturedVars(const CodeOrigin& codeOrigin) 1951{ 1952 if (codeOrigin.inlineCallFrame) { 1953 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars; 1954 for (size_t i = capturedVars.size(); i--;) { 1955 if (!capturedVars.quickGet(i)) 1956 continue; 1957 m_state.variables().local(i).makeHeapTop(); 1958 } 1959 } else { 1960 for (size_t i = m_codeBlock->m_numVars; i--;) { 1961 if (m_codeBlock->isCaptured(virtualRegisterForLocal(i))) 1962 m_state.variables().local(i).makeHeapTop(); 1963 } 1964 } 1965 1966 for (size_t i = m_state.variables().numberOfArguments(); i--;) { 1967 if (m_codeBlock->isCaptured(virtualRegisterForArgument(i))) 1968 m_state.variables().argument(i).makeHeapTop(); 1969 } 1970} 1971 1972template<typename AbstractStateType> 1973void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit) 1974{ 1975 if (!m_state.haveStructures()) 1976 return; 1977 if (clobberLimit >= m_state.block()->size()) 1978 clobberLimit = m_state.block()->size(); 1979 else 1980 clobberLimit++; 1981 ASSERT(clobberLimit <= m_state.block()->size()); 1982 for (size_t i = clobberLimit; i--;) 1983 forNode(m_state.block()->at(i)).clobberStructures(); 1984 if (m_graph.m_form == SSA) { 1985 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin(); 1986 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end(); 1987 for (; iter != end; ++iter) 1988 forNode(*iter).clobberStructures(); 1989 } 1990 for (size_t i = m_state.variables().numberOfArguments(); i--;) 1991 m_state.variables().argument(i).clobberStructures(); 1992 for (size_t i = m_state.variables().numberOfLocals(); i--;) 1993 m_state.variables().local(i).clobberStructures(); 1994 m_state.setHaveStructures(true); 1995 m_state.setDidClobber(true); 1996} 1997 1998template<typename AbstractStateType> 1999void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) 2000{ 2001 CommaPrinter comma(" "); 2002 if (m_graph.m_form == SSA) { 2003 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin(); 2004 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end(); 2005 for (; iter != end; ++iter) { 2006 Node* node = *iter; 2007 AbstractValue& value = forNode(node); 2008 if (value.isClear()) 2009 continue; 2010 out.print(comma, node, ":", value); 2011 } 2012 } 2013 for (size_t i = 0; i < m_state.block()->size(); ++i) { 2014 Node* node = m_state.block()->at(i); 2015 AbstractValue& value = forNode(node); 2016 if (value.isClear()) 2017 continue; 2018 out.print(comma, node, ":", value); 2019 } 2020} 2021 2022template<typename AbstractStateType> 2023FiltrationResult AbstractInterpreter<AbstractStateType>::filter( 2024 AbstractValue& value, const StructureSet& set) 2025{ 2026 if (value.filter(m_graph, set) == FiltrationOK) 2027 return FiltrationOK; 2028 m_state.setIsValid(false); 2029 return Contradiction; 2030} 2031 2032template<typename AbstractStateType> 2033FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes( 2034 AbstractValue& value, ArrayModes arrayModes) 2035{ 2036 if (value.filterArrayModes(arrayModes) == FiltrationOK) 2037 return FiltrationOK; 2038 m_state.setIsValid(false); 2039 return Contradiction; 2040} 2041 2042template<typename AbstractStateType> 2043FiltrationResult AbstractInterpreter<AbstractStateType>::filter( 2044 AbstractValue& value, SpeculatedType type) 2045{ 2046 if (value.filter(type) == FiltrationOK) 2047 return FiltrationOK; 2048 m_state.setIsValid(false); 2049 return Contradiction; 2050} 2051 2052template<typename AbstractStateType> 2053FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue( 2054 AbstractValue& abstractValue, JSValue concreteValue) 2055{ 2056 if (abstractValue.filterByValue(concreteValue) == FiltrationOK) 2057 return FiltrationOK; 2058 m_state.setIsValid(false); 2059 return Contradiction; 2060} 2061 2062} } // namespace JSC::DFG 2063 2064#endif // ENABLE(DFG_JIT) 2065 2066#endif // DFGAbstractInterpreterInlines_h 2067 2068