1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/compiler/js-intrinsic-lowering.h" 6 7 #include <stack> 8 9 #include "src/code-factory.h" 10 #include "src/compiler/access-builder.h" 11 #include "src/compiler/js-graph.h" 12 #include "src/compiler/linkage.h" 13 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/node-properties.h" 15 #include "src/compiler/operator-properties.h" 16 #include "src/counters.h" 17 #include "src/objects-inl.h" 18 #include "src/type-cache.h" 19 20 namespace v8 { 21 namespace internal { 22 namespace compiler { 23 24 JSIntrinsicLowering::JSIntrinsicLowering(Editor* editor, JSGraph* jsgraph, 25 DeoptimizationMode mode) 26 : AdvancedReducer(editor), 27 jsgraph_(jsgraph), 28 mode_(mode), 29 type_cache_(TypeCache::Get()) {} 30 31 32 Reduction JSIntrinsicLowering::Reduce(Node* node) { 33 if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange(); 34 const Runtime::Function* const f = 35 Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).id()); 36 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange(); 37 switch (f->function_id) { 38 case Runtime::kInlineConstructDouble: 39 return ReduceConstructDouble(node); 40 case Runtime::kInlineCreateIterResultObject: 41 return ReduceCreateIterResultObject(node); 42 case Runtime::kInlineDeoptimizeNow: 43 return ReduceDeoptimizeNow(node); 44 case Runtime::kInlineDoubleHi: 45 return ReduceDoubleHi(node); 46 case Runtime::kInlineDoubleLo: 47 return ReduceDoubleLo(node); 48 case Runtime::kInlineIncrementStatsCounter: 49 return ReduceIncrementStatsCounter(node); 50 case Runtime::kInlineIsArray: 51 return ReduceIsInstanceType(node, JS_ARRAY_TYPE); 52 case Runtime::kInlineIsDate: 53 return ReduceIsInstanceType(node, JS_DATE_TYPE); 54 case Runtime::kInlineIsTypedArray: 55 return ReduceIsInstanceType(node, JS_TYPED_ARRAY_TYPE); 56 case Runtime::kInlineIsFunction: 57 return ReduceIsFunction(node); 58 case Runtime::kInlineIsRegExp: 59 return ReduceIsInstanceType(node, JS_REGEXP_TYPE); 60 case Runtime::kInlineIsJSReceiver: 61 return ReduceIsJSReceiver(node); 62 case Runtime::kInlineIsSmi: 63 return ReduceIsSmi(node); 64 case Runtime::kInlineJSValueGetValue: 65 return ReduceJSValueGetValue(node); 66 case Runtime::kInlineMathClz32: 67 return ReduceMathClz32(node); 68 case Runtime::kInlineMathFloor: 69 return ReduceMathFloor(node); 70 case Runtime::kInlineMathSqrt: 71 return ReduceMathSqrt(node); 72 case Runtime::kInlineValueOf: 73 return ReduceValueOf(node); 74 case Runtime::kInlineIsMinusZero: 75 return ReduceIsMinusZero(node); 76 case Runtime::kInlineFixedArrayGet: 77 return ReduceFixedArrayGet(node); 78 case Runtime::kInlineFixedArraySet: 79 return ReduceFixedArraySet(node); 80 case Runtime::kInlineRegExpConstructResult: 81 return ReduceRegExpConstructResult(node); 82 case Runtime::kInlineRegExpExec: 83 return ReduceRegExpExec(node); 84 case Runtime::kInlineRegExpFlags: 85 return ReduceRegExpFlags(node); 86 case Runtime::kInlineRegExpSource: 87 return ReduceRegExpSource(node); 88 case Runtime::kInlineSubString: 89 return ReduceSubString(node); 90 case Runtime::kInlineToInteger: 91 return ReduceToInteger(node); 92 case Runtime::kInlineToLength: 93 return ReduceToLength(node); 94 case Runtime::kInlineToName: 95 return ReduceToName(node); 96 case Runtime::kInlineToNumber: 97 return ReduceToNumber(node); 98 case Runtime::kInlineToObject: 99 return ReduceToObject(node); 100 case Runtime::kInlineToPrimitive: 101 return ReduceToPrimitive(node); 102 case Runtime::kInlineToString: 103 return ReduceToString(node); 104 case Runtime::kInlineCall: 105 return ReduceCall(node); 106 case Runtime::kInlineTailCall: 107 return ReduceTailCall(node); 108 case Runtime::kInlineGetSuperConstructor: 109 return ReduceGetSuperConstructor(node); 110 default: 111 break; 112 } 113 return NoChange(); 114 } 115 116 117 Reduction JSIntrinsicLowering::ReduceCreateIterResultObject(Node* node) { 118 Node* const value = NodeProperties::GetValueInput(node, 0); 119 Node* const done = NodeProperties::GetValueInput(node, 1); 120 Node* const context = NodeProperties::GetContextInput(node); 121 Node* const effect = NodeProperties::GetEffectInput(node); 122 return Change(node, javascript()->CreateIterResultObject(), value, done, 123 context, effect); 124 } 125 126 127 Reduction JSIntrinsicLowering::ReduceConstructDouble(Node* node) { 128 Node* high = NodeProperties::GetValueInput(node, 0); 129 Node* low = NodeProperties::GetValueInput(node, 1); 130 Node* value = 131 graph()->NewNode(machine()->Float64InsertHighWord32(), 132 graph()->NewNode(machine()->Float64InsertLowWord32(), 133 jsgraph()->Constant(0), low), 134 high); 135 ReplaceWithValue(node, value); 136 return Replace(value); 137 } 138 139 140 Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) { 141 if (mode() != kDeoptimizationEnabled) return NoChange(); 142 Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0); 143 Node* const effect = NodeProperties::GetEffectInput(node); 144 Node* const control = NodeProperties::GetControlInput(node); 145 146 // TODO(bmeurer): Move MergeControlToEnd() to the AdvancedReducer. 147 Node* deoptimize = 148 graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager), 149 frame_state, effect, control); 150 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); 151 152 node->TrimInputCount(0); 153 NodeProperties::ChangeOp(node, common()->Dead()); 154 return Changed(node); 155 } 156 157 158 Reduction JSIntrinsicLowering::ReduceDoubleHi(Node* node) { 159 return Change(node, machine()->Float64ExtractHighWord32()); 160 } 161 162 163 Reduction JSIntrinsicLowering::ReduceDoubleLo(Node* node) { 164 return Change(node, machine()->Float64ExtractLowWord32()); 165 } 166 167 168 Reduction JSIntrinsicLowering::ReduceIncrementStatsCounter(Node* node) { 169 if (!FLAG_native_code_counters) return ChangeToUndefined(node); 170 HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0)); 171 if (!m.HasValue() || !m.Value()->IsString()) { 172 return ChangeToUndefined(node); 173 } 174 base::SmartArrayPointer<char> name = 175 Handle<String>::cast(m.Value())->ToCString(); 176 StatsCounter counter(jsgraph()->isolate(), name.get()); 177 if (!counter.Enabled()) return ChangeToUndefined(node); 178 179 Node* effect = NodeProperties::GetEffectInput(node); 180 Node* control = NodeProperties::GetControlInput(node); 181 FieldAccess access = AccessBuilder::ForStatsCounter(); 182 Node* cnt = jsgraph()->ExternalConstant(ExternalReference(&counter)); 183 Node* load = 184 graph()->NewNode(simplified()->LoadField(access), cnt, effect, control); 185 Node* inc = 186 graph()->NewNode(machine()->Int32Add(), load, jsgraph()->OneConstant()); 187 Node* store = graph()->NewNode(simplified()->StoreField(access), cnt, inc, 188 load, control); 189 return ChangeToUndefined(node, store); 190 } 191 192 193 Reduction JSIntrinsicLowering::ReduceIsInstanceType( 194 Node* node, InstanceType instance_type) { 195 // if (%_IsSmi(value)) { 196 // return false; 197 // } else { 198 // return %_GetInstanceType(%_GetMap(value)) == instance_type; 199 // } 200 Node* value = NodeProperties::GetValueInput(node, 0); 201 Node* effect = NodeProperties::GetEffectInput(node); 202 Node* control = NodeProperties::GetControlInput(node); 203 204 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); 205 Node* branch = graph()->NewNode(common()->Branch(), check, control); 206 207 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 208 Node* etrue = effect; 209 Node* vtrue = jsgraph()->FalseConstant(); 210 211 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 212 Node* efalse = graph()->NewNode( 213 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), 214 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value, 215 effect, if_false), 216 effect, if_false); 217 Node* vfalse = graph()->NewNode(machine()->Word32Equal(), efalse, 218 jsgraph()->Int32Constant(instance_type)); 219 220 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 221 222 // Replace all effect uses of {node} with the {ephi}. 223 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); 224 ReplaceWithValue(node, node, ephi); 225 226 // Turn the {node} into a Phi. 227 return Change(node, common()->Phi(MachineRepresentation::kTagged, 2), vtrue, 228 vfalse, merge); 229 } 230 231 232 Reduction JSIntrinsicLowering::ReduceIsFunction(Node* node) { 233 Node* value = NodeProperties::GetValueInput(node, 0); 234 Type* value_type = NodeProperties::GetType(value); 235 Node* effect = NodeProperties::GetEffectInput(node); 236 Node* control = NodeProperties::GetControlInput(node); 237 if (value_type->Is(Type::Function())) { 238 value = jsgraph()->TrueConstant(); 239 } else { 240 // if (%_IsSmi(value)) { 241 // return false; 242 // } else { 243 // return FIRST_FUNCTION_TYPE <= %_GetInstanceType(%_GetMap(value)) 244 // } 245 STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE); 246 247 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); 248 Node* branch = graph()->NewNode(common()->Branch(), check, control); 249 250 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 251 Node* etrue = effect; 252 Node* vtrue = jsgraph()->FalseConstant(); 253 254 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 255 Node* efalse = graph()->NewNode( 256 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), 257 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 258 value, effect, if_false), 259 effect, if_false); 260 Node* vfalse = 261 graph()->NewNode(machine()->Uint32LessThanOrEqual(), 262 jsgraph()->Int32Constant(FIRST_FUNCTION_TYPE), efalse); 263 264 control = graph()->NewNode(common()->Merge(2), if_true, if_false); 265 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); 266 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), 267 vtrue, vfalse, control); 268 } 269 ReplaceWithValue(node, node, effect, control); 270 return Replace(value); 271 } 272 273 274 Reduction JSIntrinsicLowering::ReduceIsJSReceiver(Node* node) { 275 Node* value = NodeProperties::GetValueInput(node, 0); 276 Type* value_type = NodeProperties::GetType(value); 277 Node* effect = NodeProperties::GetEffectInput(node); 278 Node* control = NodeProperties::GetControlInput(node); 279 if (value_type->Is(Type::Receiver())) { 280 value = jsgraph()->TrueConstant(); 281 } else if (!value_type->Maybe(Type::Receiver())) { 282 value = jsgraph()->FalseConstant(); 283 } else { 284 // if (%_IsSmi(value)) { 285 // return false; 286 // } else { 287 // return FIRST_JS_RECEIVER_TYPE <= %_GetInstanceType(%_GetMap(value)) 288 // } 289 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 290 291 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); 292 Node* branch = graph()->NewNode(common()->Branch(), check, control); 293 294 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 295 Node* etrue = effect; 296 Node* vtrue = jsgraph()->FalseConstant(); 297 298 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 299 Node* efalse = graph()->NewNode( 300 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), 301 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 302 value, effect, if_false), 303 effect, if_false); 304 Node* vfalse = graph()->NewNode( 305 machine()->Uint32LessThanOrEqual(), 306 jsgraph()->Int32Constant(FIRST_JS_RECEIVER_TYPE), efalse); 307 308 control = graph()->NewNode(common()->Merge(2), if_true, if_false); 309 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); 310 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), 311 vtrue, vfalse, control); 312 } 313 ReplaceWithValue(node, node, effect, control); 314 return Replace(value); 315 } 316 317 318 Reduction JSIntrinsicLowering::ReduceIsSmi(Node* node) { 319 return Change(node, simplified()->ObjectIsSmi()); 320 } 321 322 323 Reduction JSIntrinsicLowering::ReduceJSValueGetValue(Node* node) { 324 Node* value = NodeProperties::GetValueInput(node, 0); 325 Node* effect = NodeProperties::GetEffectInput(node); 326 Node* control = NodeProperties::GetControlInput(node); 327 return Change(node, simplified()->LoadField(AccessBuilder::ForValue()), value, 328 effect, control); 329 } 330 331 332 Reduction JSIntrinsicLowering::ReduceMathClz32(Node* node) { 333 return Change(node, machine()->Word32Clz()); 334 } 335 336 337 Reduction JSIntrinsicLowering::ReduceMathFloor(Node* node) { 338 if (!machine()->Float64RoundDown().IsSupported()) return NoChange(); 339 return Change(node, machine()->Float64RoundDown().op()); 340 } 341 342 343 Reduction JSIntrinsicLowering::ReduceMathSqrt(Node* node) { 344 return Change(node, machine()->Float64Sqrt()); 345 } 346 347 348 Reduction JSIntrinsicLowering::ReduceValueOf(Node* node) { 349 // if (%_IsSmi(value)) { 350 // return value; 351 // } else if (%_GetInstanceType(%_GetMap(value)) == JS_VALUE_TYPE) { 352 // return %_GetValue(value); 353 // } else { 354 // return value; 355 // } 356 const Operator* const merge_op = common()->Merge(2); 357 const Operator* const ephi_op = common()->EffectPhi(2); 358 const Operator* const phi_op = 359 common()->Phi(MachineRepresentation::kTagged, 2); 360 361 Node* value = NodeProperties::GetValueInput(node, 0); 362 Node* effect = NodeProperties::GetEffectInput(node); 363 Node* control = NodeProperties::GetControlInput(node); 364 365 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); 366 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); 367 368 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 369 Node* etrue0 = effect; 370 Node* vtrue0 = value; 371 372 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 373 Node* efalse0; 374 Node* vfalse0; 375 { 376 Node* check1 = graph()->NewNode( 377 machine()->Word32Equal(), 378 graph()->NewNode( 379 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), 380 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 381 value, effect, if_false0), 382 effect, if_false0), 383 jsgraph()->Int32Constant(JS_VALUE_TYPE)); 384 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 385 386 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 387 Node* etrue1 = 388 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForValue()), 389 value, effect, if_true1); 390 Node* vtrue1 = etrue1; 391 392 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 393 Node* efalse1 = effect; 394 Node* vfalse1 = value; 395 396 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1); 397 efalse0 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1); 398 vfalse0 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1); 399 } 400 401 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); 402 403 // Replace all effect uses of {node} with the {ephi0}. 404 Node* ephi0 = graph()->NewNode(ephi_op, etrue0, efalse0, merge0); 405 ReplaceWithValue(node, node, ephi0); 406 407 // Turn the {node} into a Phi. 408 return Change(node, phi_op, vtrue0, vfalse0, merge0); 409 } 410 411 412 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op) { 413 // Replace all effect uses of {node} with the effect dependency. 414 RelaxEffectsAndControls(node); 415 // Remove the inputs corresponding to context, effect and control. 416 NodeProperties::RemoveNonValueInputs(node); 417 // Finally update the operator to the new one. 418 NodeProperties::ChangeOp(node, op); 419 return Changed(node); 420 } 421 422 423 Reduction JSIntrinsicLowering::ReduceIsMinusZero(Node* node) { 424 Node* value = NodeProperties::GetValueInput(node, 0); 425 Node* effect = NodeProperties::GetEffectInput(node); 426 427 Node* double_lo = 428 graph()->NewNode(machine()->Float64ExtractLowWord32(), value); 429 Node* check1 = graph()->NewNode(machine()->Word32Equal(), double_lo, 430 jsgraph()->ZeroConstant()); 431 432 Node* double_hi = 433 graph()->NewNode(machine()->Float64ExtractHighWord32(), value); 434 Node* check2 = graph()->NewNode( 435 machine()->Word32Equal(), double_hi, 436 jsgraph()->Int32Constant(static_cast<int32_t>(0x80000000))); 437 438 ReplaceWithValue(node, node, effect); 439 440 Node* and_result = graph()->NewNode(machine()->Word32And(), check1, check2); 441 442 return Change(node, machine()->Word32Equal(), and_result, 443 jsgraph()->Int32Constant(1)); 444 } 445 446 447 Reduction JSIntrinsicLowering::ReduceFixedArrayGet(Node* node) { 448 Node* base = node->InputAt(0); 449 Node* index = node->InputAt(1); 450 Node* effect = NodeProperties::GetEffectInput(node); 451 Node* control = NodeProperties::GetControlInput(node); 452 return Change( 453 node, simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), 454 base, index, effect, control); 455 } 456 457 458 Reduction JSIntrinsicLowering::ReduceFixedArraySet(Node* node) { 459 Node* base = node->InputAt(0); 460 Node* index = node->InputAt(1); 461 Node* value = node->InputAt(2); 462 Node* effect = NodeProperties::GetEffectInput(node); 463 Node* control = NodeProperties::GetControlInput(node); 464 Node* store = (graph()->NewNode( 465 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()), base, 466 index, value, effect, control)); 467 ReplaceWithValue(node, value, store); 468 return Changed(store); 469 } 470 471 472 Reduction JSIntrinsicLowering::ReduceRegExpConstructResult(Node* node) { 473 // TODO(bmeurer): Introduce JSCreateRegExpResult? 474 return Change(node, CodeFactory::RegExpConstructResult(isolate()), 0); 475 } 476 477 478 Reduction JSIntrinsicLowering::ReduceRegExpExec(Node* node) { 479 return Change(node, CodeFactory::RegExpExec(isolate()), 4); 480 } 481 482 483 Reduction JSIntrinsicLowering::ReduceRegExpFlags(Node* node) { 484 Node* const receiver = NodeProperties::GetValueInput(node, 0); 485 Node* const effect = NodeProperties::GetEffectInput(node); 486 Node* const control = NodeProperties::GetControlInput(node); 487 Operator const* const op = 488 simplified()->LoadField(AccessBuilder::ForJSRegExpFlags()); 489 return Change(node, op, receiver, effect, control); 490 } 491 492 493 Reduction JSIntrinsicLowering::ReduceRegExpSource(Node* node) { 494 Node* const receiver = NodeProperties::GetValueInput(node, 0); 495 Node* const effect = NodeProperties::GetEffectInput(node); 496 Node* const control = NodeProperties::GetControlInput(node); 497 Operator const* const op = 498 simplified()->LoadField(AccessBuilder::ForJSRegExpSource()); 499 return Change(node, op, receiver, effect, control); 500 } 501 502 503 Reduction JSIntrinsicLowering::ReduceSubString(Node* node) { 504 return Change(node, CodeFactory::SubString(isolate()), 3); 505 } 506 507 508 Reduction JSIntrinsicLowering::ReduceToInteger(Node* node) { 509 Node* value = NodeProperties::GetValueInput(node, 0); 510 Type* value_type = NodeProperties::GetType(value); 511 if (value_type->Is(type_cache().kIntegerOrMinusZero)) { 512 ReplaceWithValue(node, value); 513 return Replace(value); 514 } 515 return NoChange(); 516 } 517 518 519 Reduction JSIntrinsicLowering::ReduceToName(Node* node) { 520 NodeProperties::ChangeOp(node, javascript()->ToName()); 521 return Changed(node); 522 } 523 524 525 Reduction JSIntrinsicLowering::ReduceToNumber(Node* node) { 526 NodeProperties::ChangeOp(node, javascript()->ToNumber()); 527 return Changed(node); 528 } 529 530 531 Reduction JSIntrinsicLowering::ReduceToLength(Node* node) { 532 Node* value = NodeProperties::GetValueInput(node, 0); 533 Type* value_type = NodeProperties::GetType(value); 534 if (value_type->Is(type_cache().kIntegerOrMinusZero)) { 535 if (value_type->Max() <= 0.0) { 536 value = jsgraph()->ZeroConstant(); 537 } else if (value_type->Min() >= kMaxSafeInteger) { 538 value = jsgraph()->Constant(kMaxSafeInteger); 539 } else { 540 if (value_type->Min() <= 0.0) { 541 value = graph()->NewNode( 542 common()->Select(MachineRepresentation::kTagged), 543 graph()->NewNode(simplified()->NumberLessThanOrEqual(), value, 544 jsgraph()->ZeroConstant()), 545 jsgraph()->ZeroConstant(), value); 546 value_type = Type::Range(0.0, value_type->Max(), graph()->zone()); 547 NodeProperties::SetType(value, value_type); 548 } 549 if (value_type->Max() > kMaxSafeInteger) { 550 value = graph()->NewNode( 551 common()->Select(MachineRepresentation::kTagged), 552 graph()->NewNode(simplified()->NumberLessThanOrEqual(), 553 jsgraph()->Constant(kMaxSafeInteger), value), 554 jsgraph()->Constant(kMaxSafeInteger), value); 555 value_type = 556 Type::Range(value_type->Min(), kMaxSafeInteger, graph()->zone()); 557 NodeProperties::SetType(value, value_type); 558 } 559 } 560 ReplaceWithValue(node, value); 561 return Replace(value); 562 } 563 return Change(node, CodeFactory::ToLength(isolate()), 0); 564 } 565 566 567 Reduction JSIntrinsicLowering::ReduceToObject(Node* node) { 568 NodeProperties::ChangeOp(node, javascript()->ToObject()); 569 return Changed(node); 570 } 571 572 573 Reduction JSIntrinsicLowering::ReduceToPrimitive(Node* node) { 574 Node* value = NodeProperties::GetValueInput(node, 0); 575 Type* value_type = NodeProperties::GetType(value); 576 if (value_type->Is(Type::Primitive())) { 577 ReplaceWithValue(node, value); 578 return Replace(value); 579 } 580 return NoChange(); 581 } 582 583 584 Reduction JSIntrinsicLowering::ReduceToString(Node* node) { 585 NodeProperties::ChangeOp(node, javascript()->ToString()); 586 return Changed(node); 587 } 588 589 590 Reduction JSIntrinsicLowering::ReduceCall(Node* node) { 591 size_t const arity = CallRuntimeParametersOf(node->op()).arity(); 592 NodeProperties::ChangeOp( 593 node, javascript()->CallFunction(arity, STRICT, VectorSlotPair(), 594 ConvertReceiverMode::kAny, 595 TailCallMode::kDisallow)); 596 return Changed(node); 597 } 598 599 600 Reduction JSIntrinsicLowering::ReduceTailCall(Node* node) { 601 size_t const arity = CallRuntimeParametersOf(node->op()).arity(); 602 NodeProperties::ChangeOp( 603 node, javascript()->CallFunction(arity, STRICT, VectorSlotPair(), 604 ConvertReceiverMode::kAny, 605 TailCallMode::kAllow)); 606 return Changed(node); 607 } 608 609 610 Reduction JSIntrinsicLowering::ReduceGetSuperConstructor(Node* node) { 611 Node* active_function = NodeProperties::GetValueInput(node, 0); 612 Node* effect = NodeProperties::GetEffectInput(node); 613 Node* control = NodeProperties::GetControlInput(node); 614 Node* active_function_map = effect = 615 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 616 active_function, effect, control); 617 return Change(node, simplified()->LoadField(AccessBuilder::ForMapPrototype()), 618 active_function_map, effect, control); 619 } 620 621 622 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a, 623 Node* b) { 624 RelaxControls(node); 625 node->ReplaceInput(0, a); 626 node->ReplaceInput(1, b); 627 node->TrimInputCount(2); 628 NodeProperties::ChangeOp(node, op); 629 return Changed(node); 630 } 631 632 633 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a, 634 Node* b, Node* c) { 635 RelaxControls(node); 636 node->ReplaceInput(0, a); 637 node->ReplaceInput(1, b); 638 node->ReplaceInput(2, c); 639 node->TrimInputCount(3); 640 NodeProperties::ChangeOp(node, op); 641 return Changed(node); 642 } 643 644 645 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a, 646 Node* b, Node* c, Node* d) { 647 RelaxControls(node); 648 node->ReplaceInput(0, a); 649 node->ReplaceInput(1, b); 650 node->ReplaceInput(2, c); 651 node->ReplaceInput(3, d); 652 node->TrimInputCount(4); 653 NodeProperties::ChangeOp(node, op); 654 return Changed(node); 655 } 656 657 658 Reduction JSIntrinsicLowering::ChangeToUndefined(Node* node, Node* effect) { 659 ReplaceWithValue(node, jsgraph()->UndefinedConstant(), effect); 660 return Changed(node); 661 } 662 663 664 Reduction JSIntrinsicLowering::Change(Node* node, Callable const& callable, 665 int stack_parameter_count) { 666 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( 667 isolate(), graph()->zone(), callable.descriptor(), stack_parameter_count, 668 CallDescriptor::kNeedsFrameState, node->op()->properties()); 669 node->InsertInput(graph()->zone(), 0, 670 jsgraph()->HeapConstant(callable.code())); 671 NodeProperties::ChangeOp(node, common()->Call(desc)); 672 return Changed(node); 673 } 674 675 676 Graph* JSIntrinsicLowering::graph() const { return jsgraph()->graph(); } 677 678 679 Isolate* JSIntrinsicLowering::isolate() const { return jsgraph()->isolate(); } 680 681 682 CommonOperatorBuilder* JSIntrinsicLowering::common() const { 683 return jsgraph()->common(); 684 } 685 686 JSOperatorBuilder* JSIntrinsicLowering::javascript() const { 687 return jsgraph_->javascript(); 688 } 689 690 691 MachineOperatorBuilder* JSIntrinsicLowering::machine() const { 692 return jsgraph()->machine(); 693 } 694 695 696 SimplifiedOperatorBuilder* JSIntrinsicLowering::simplified() const { 697 return jsgraph()->simplified(); 698 } 699 700 } // namespace compiler 701 } // namespace internal 702 } // namespace v8 703