1 // Copyright 2014 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/change-lowering.h" 6 7 #include "src/address-map.h" 8 #include "src/code-factory.h" 9 #include "src/compiler/js-graph.h" 10 #include "src/compiler/linkage.h" 11 #include "src/compiler/machine-operator.h" 12 #include "src/compiler/node-properties.h" 13 #include "src/compiler/operator-properties.h" 14 #include "src/compiler/simplified-operator.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace compiler { 19 20 ChangeLowering::~ChangeLowering() {} 21 22 23 Reduction ChangeLowering::Reduce(Node* node) { 24 Node* control = graph()->start(); 25 switch (node->opcode()) { 26 case IrOpcode::kChangeBitToBool: 27 return ChangeBitToBool(node->InputAt(0), control); 28 case IrOpcode::kChangeBoolToBit: 29 return ChangeBoolToBit(node->InputAt(0)); 30 case IrOpcode::kChangeFloat64ToTagged: 31 return ChangeFloat64ToTagged(node->InputAt(0), control); 32 case IrOpcode::kChangeInt32ToTagged: 33 return ChangeInt32ToTagged(node->InputAt(0), control); 34 case IrOpcode::kChangeTaggedToFloat64: 35 return ChangeTaggedToFloat64(node->InputAt(0), control); 36 case IrOpcode::kChangeTaggedToInt32: 37 return ChangeTaggedToUI32(node->InputAt(0), control, kSigned); 38 case IrOpcode::kChangeTaggedToUint32: 39 return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned); 40 case IrOpcode::kChangeUint32ToTagged: 41 return ChangeUint32ToTagged(node->InputAt(0), control); 42 case IrOpcode::kLoadField: 43 return LoadField(node); 44 case IrOpcode::kStoreField: 45 return StoreField(node); 46 case IrOpcode::kLoadElement: 47 return LoadElement(node); 48 case IrOpcode::kStoreElement: 49 return StoreElement(node); 50 case IrOpcode::kAllocate: 51 return Allocate(node); 52 default: 53 return NoChange(); 54 } 55 UNREACHABLE(); 56 return NoChange(); 57 } 58 59 60 Node* ChangeLowering::HeapNumberValueIndexConstant() { 61 return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag); 62 } 63 64 65 Node* ChangeLowering::SmiMaxValueConstant() { 66 return jsgraph()->Int32Constant(Smi::kMaxValue); 67 } 68 69 70 Node* ChangeLowering::SmiShiftBitsConstant() { 71 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize); 72 } 73 74 75 Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) { 76 // The AllocateHeapNumberStub does not use the context, so we can safely pass 77 // in Smi zero here. 78 Callable callable = CodeFactory::AllocateHeapNumber(isolate()); 79 Node* target = jsgraph()->HeapConstant(callable.code()); 80 Node* context = jsgraph()->NoContextConstant(); 81 Node* effect = graph()->NewNode(common()->BeginRegion(), graph()->start()); 82 if (!allocate_heap_number_operator_.is_set()) { 83 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( 84 isolate(), jsgraph()->zone(), callable.descriptor(), 0, 85 CallDescriptor::kNoFlags, Operator::kNoThrow); 86 allocate_heap_number_operator_.set(common()->Call(descriptor)); 87 } 88 Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(), 89 target, context, effect, control); 90 Node* store = graph()->NewNode( 91 machine()->Store(StoreRepresentation(MachineRepresentation::kFloat64, 92 kNoWriteBarrier)), 93 heap_number, HeapNumberValueIndexConstant(), value, heap_number, control); 94 return graph()->NewNode(common()->FinishRegion(), heap_number, store); 95 } 96 97 98 Node* ChangeLowering::ChangeInt32ToFloat64(Node* value) { 99 return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value); 100 } 101 102 103 Node* ChangeLowering::ChangeInt32ToSmi(Node* value) { 104 if (machine()->Is64()) { 105 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value); 106 } 107 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); 108 } 109 110 111 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) { 112 return ChangeInt32ToFloat64(ChangeSmiToInt32(value)); 113 } 114 115 116 Node* ChangeLowering::ChangeSmiToInt32(Node* value) { 117 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); 118 if (machine()->Is64()) { 119 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); 120 } 121 return value; 122 } 123 124 125 Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) { 126 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value); 127 } 128 129 130 Node* ChangeLowering::ChangeUint32ToSmi(Node* value) { 131 if (machine()->Is64()) { 132 value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value); 133 } 134 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); 135 } 136 137 138 Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) { 139 return graph()->NewNode(machine()->Load(MachineType::Float64()), value, 140 HeapNumberValueIndexConstant(), graph()->start(), 141 control); 142 } 143 144 145 Node* ChangeLowering::TestNotSmi(Node* value) { 146 STATIC_ASSERT(kSmiTag == 0); 147 STATIC_ASSERT(kSmiTagMask == 1); 148 return graph()->NewNode(machine()->WordAnd(), value, 149 jsgraph()->IntPtrConstant(kSmiTagMask)); 150 } 151 152 153 Reduction ChangeLowering::ChangeBitToBool(Node* value, Node* control) { 154 return Replace( 155 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), value, 156 jsgraph()->TrueConstant(), jsgraph()->FalseConstant())); 157 } 158 159 160 Reduction ChangeLowering::ChangeBoolToBit(Node* value) { 161 return Replace(graph()->NewNode(machine()->WordEqual(), value, 162 jsgraph()->TrueConstant())); 163 } 164 165 166 Reduction ChangeLowering::ChangeFloat64ToTagged(Node* value, Node* control) { 167 Type* const value_type = NodeProperties::GetType(value); 168 Node* const value32 = graph()->NewNode( 169 machine()->TruncateFloat64ToInt32(TruncationMode::kRoundToZero), value); 170 // TODO(bmeurer): This fast case must be disabled until we kill the asm.js 171 // support in the generic JavaScript pipeline, because LoadBuffer is lying 172 // about its result. 173 // if (value_type->Is(Type::Signed32())) { 174 // return ChangeInt32ToTagged(value32, control); 175 // } 176 Node* check_same = graph()->NewNode( 177 machine()->Float64Equal(), value, 178 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32)); 179 Node* branch_same = graph()->NewNode(common()->Branch(), check_same, control); 180 181 Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_same); 182 Node* vsmi; 183 Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same); 184 Node* vbox; 185 186 // We only need to check for -0 if the {value} can potentially contain -0. 187 if (value_type->Maybe(Type::MinusZero())) { 188 Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32, 189 jsgraph()->Int32Constant(0)); 190 Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse), 191 check_zero, if_smi); 192 193 Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero); 194 Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero); 195 196 // In case of 0, we need to check the high bits for the IEEE -0 pattern. 197 Node* check_negative = graph()->NewNode( 198 machine()->Int32LessThan(), 199 graph()->NewNode(machine()->Float64ExtractHighWord32(), value), 200 jsgraph()->Int32Constant(0)); 201 Node* branch_negative = graph()->NewNode( 202 common()->Branch(BranchHint::kFalse), check_negative, if_zero); 203 204 Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative); 205 Node* if_notnegative = 206 graph()->NewNode(common()->IfFalse(), branch_negative); 207 208 // We need to create a box for negative 0. 209 if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative); 210 if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative); 211 } 212 213 // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit 214 // machines we need to deal with potential overflow and fallback to boxing. 215 if (machine()->Is64() || value_type->Is(Type::SignedSmall())) { 216 vsmi = ChangeInt32ToSmi(value32); 217 } else { 218 Node* smi_tag = 219 graph()->NewNode(machine()->Int32AddWithOverflow(), value32, value32); 220 221 Node* check_ovf = graph()->NewNode(common()->Projection(1), smi_tag); 222 Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse), 223 check_ovf, if_smi); 224 225 Node* if_ovf = graph()->NewNode(common()->IfTrue(), branch_ovf); 226 if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box); 227 228 if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf); 229 vsmi = graph()->NewNode(common()->Projection(0), smi_tag); 230 } 231 232 // Allocate the box for the {value}. 233 vbox = AllocateHeapNumberWithValue(value, if_box); 234 235 control = graph()->NewNode(common()->Merge(2), if_smi, if_box); 236 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), 237 vsmi, vbox, control); 238 return Replace(value); 239 } 240 241 242 Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) { 243 if (machine()->Is64() || 244 NodeProperties::GetType(value)->Is(Type::SignedSmall())) { 245 return Replace(ChangeInt32ToSmi(value)); 246 } 247 248 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value); 249 250 Node* ovf = graph()->NewNode(common()->Projection(1), add); 251 Node* branch = 252 graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control); 253 254 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 255 Node* vtrue = 256 AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), if_true); 257 258 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 259 Node* vfalse = graph()->NewNode(common()->Projection(0), add); 260 261 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 262 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), 263 vtrue, vfalse, merge); 264 265 return Replace(phi); 266 } 267 268 269 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, 270 Signedness signedness) { 271 if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) { 272 return Replace(ChangeSmiToInt32(value)); 273 } 274 275 const Operator* op = (signedness == kSigned) 276 ? machine()->ChangeFloat64ToInt32() 277 : machine()->ChangeFloat64ToUint32(); 278 279 if (NodeProperties::GetType(value)->Is(Type::TaggedPointer())) { 280 return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control))); 281 } 282 283 Node* check = TestNotSmi(value); 284 Node* branch = 285 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); 286 287 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 288 Node* vtrue = graph()->NewNode(op, LoadHeapNumberValue(value, if_true)); 289 290 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 291 Node* vfalse = ChangeSmiToInt32(value); 292 293 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 294 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), 295 vtrue, vfalse, merge); 296 297 return Replace(phi); 298 } 299 300 301 namespace { 302 303 bool CanCover(Node* value, IrOpcode::Value opcode) { 304 if (value->opcode() != opcode) return false; 305 bool first = true; 306 for (Edge const edge : value->use_edges()) { 307 if (NodeProperties::IsControlEdge(edge)) continue; 308 if (NodeProperties::IsEffectEdge(edge)) continue; 309 DCHECK(NodeProperties::IsValueEdge(edge)); 310 if (!first) return false; 311 first = false; 312 } 313 return true; 314 } 315 316 } // namespace 317 318 319 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) { 320 if (CanCover(value, IrOpcode::kJSToNumber)) { 321 // ChangeTaggedToFloat64(JSToNumber(x)) => 322 // if IsSmi(x) then ChangeSmiToFloat64(x) 323 // else let y = JSToNumber(x) in 324 // if IsSmi(y) then ChangeSmiToFloat64(y) 325 // else LoadHeapNumberValue(y) 326 Node* const object = NodeProperties::GetValueInput(value, 0); 327 Node* const context = NodeProperties::GetContextInput(value); 328 Node* const frame_state = NodeProperties::GetFrameStateInput(value, 0); 329 Node* const effect = NodeProperties::GetEffectInput(value); 330 Node* const control = NodeProperties::GetControlInput(value); 331 332 const Operator* merge_op = common()->Merge(2); 333 const Operator* ephi_op = common()->EffectPhi(2); 334 const Operator* phi_op = common()->Phi(MachineRepresentation::kFloat64, 2); 335 336 Node* check1 = TestNotSmi(object); 337 Node* branch1 = 338 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control); 339 340 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 341 Node* vtrue1 = graph()->NewNode(value->op(), object, context, frame_state, 342 effect, if_true1); 343 Node* etrue1 = vtrue1; 344 345 Node* check2 = TestNotSmi(vtrue1); 346 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_true1); 347 348 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); 349 Node* vtrue2 = LoadHeapNumberValue(vtrue1, if_true2); 350 351 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); 352 Node* vfalse2 = ChangeSmiToFloat64(vtrue1); 353 354 if_true1 = graph()->NewNode(merge_op, if_true2, if_false2); 355 vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1); 356 357 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 358 Node* vfalse1 = ChangeSmiToFloat64(object); 359 Node* efalse1 = effect; 360 361 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1); 362 Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1); 363 Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1); 364 365 // Wire the new diamond into the graph, {JSToNumber} can still throw. 366 NodeProperties::ReplaceUses(value, phi1, ephi1, etrue1, etrue1); 367 368 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from 369 // the node and places it inside the diamond. Come up with a helper method! 370 for (Node* use : etrue1->uses()) { 371 if (use->opcode() == IrOpcode::kIfSuccess) { 372 use->ReplaceUses(merge1); 373 NodeProperties::ReplaceControlInput(branch2, use); 374 } 375 } 376 377 return Replace(phi1); 378 } 379 380 Node* check = TestNotSmi(value); 381 Node* branch = 382 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); 383 384 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 385 Node* vtrue = LoadHeapNumberValue(value, if_true); 386 387 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 388 Node* vfalse = ChangeSmiToFloat64(value); 389 390 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 391 Node* phi = graph()->NewNode( 392 common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge); 393 394 return Replace(phi); 395 } 396 397 398 Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) { 399 if (NodeProperties::GetType(value)->Is(Type::UnsignedSmall())) { 400 return Replace(ChangeUint32ToSmi(value)); 401 } 402 403 Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, 404 SmiMaxValueConstant()); 405 Node* branch = 406 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); 407 408 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 409 Node* vtrue = ChangeUint32ToSmi(value); 410 411 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 412 Node* vfalse = 413 AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), if_false); 414 415 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 416 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), 417 vtrue, vfalse, merge); 418 419 return Replace(phi); 420 } 421 422 423 namespace { 424 425 WriteBarrierKind ComputeWriteBarrierKind(BaseTaggedness base_is_tagged, 426 MachineRepresentation representation, 427 Type* field_type, Type* input_type) { 428 if (field_type->Is(Type::TaggedSigned()) || 429 input_type->Is(Type::TaggedSigned())) { 430 // Write barriers are only for writes of heap objects. 431 return kNoWriteBarrier; 432 } 433 if (input_type->Is(Type::BooleanOrNullOrUndefined())) { 434 // Write barriers are not necessary when storing true, false, null or 435 // undefined, because these special oddballs are always in the root set. 436 return kNoWriteBarrier; 437 } 438 if (base_is_tagged == kTaggedBase && 439 representation == MachineRepresentation::kTagged) { 440 if (input_type->IsConstant() && 441 input_type->AsConstant()->Value()->IsHeapObject()) { 442 Handle<HeapObject> input = 443 Handle<HeapObject>::cast(input_type->AsConstant()->Value()); 444 if (input->IsMap()) { 445 // Write barriers for storing maps are cheaper. 446 return kMapWriteBarrier; 447 } 448 Isolate* const isolate = input->GetIsolate(); 449 RootIndexMap root_index_map(isolate); 450 int root_index = root_index_map.Lookup(*input); 451 if (root_index != RootIndexMap::kInvalidRootIndex && 452 isolate->heap()->RootIsImmortalImmovable(root_index)) { 453 // Write barriers are unnecessary for immortal immovable roots. 454 return kNoWriteBarrier; 455 } 456 } 457 if (field_type->Is(Type::TaggedPointer()) || 458 input_type->Is(Type::TaggedPointer())) { 459 // Write barriers for heap objects don't need a Smi check. 460 return kPointerWriteBarrier; 461 } 462 // Write barriers are only for writes into heap objects (i.e. tagged base). 463 return kFullWriteBarrier; 464 } 465 return kNoWriteBarrier; 466 } 467 468 469 WriteBarrierKind ComputeWriteBarrierKind(BaseTaggedness base_is_tagged, 470 MachineRepresentation representation, 471 int field_offset, Type* field_type, 472 Type* input_type) { 473 if (base_is_tagged == kTaggedBase && field_offset == HeapObject::kMapOffset) { 474 // Write barriers for storing maps are cheaper. 475 return kMapWriteBarrier; 476 } 477 return ComputeWriteBarrierKind(base_is_tagged, representation, field_type, 478 input_type); 479 } 480 481 } // namespace 482 483 484 Reduction ChangeLowering::LoadField(Node* node) { 485 const FieldAccess& access = FieldAccessOf(node->op()); 486 Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); 487 node->InsertInput(graph()->zone(), 1, offset); 488 NodeProperties::ChangeOp(node, machine()->Load(access.machine_type)); 489 return Changed(node); 490 } 491 492 493 Reduction ChangeLowering::StoreField(Node* node) { 494 const FieldAccess& access = FieldAccessOf(node->op()); 495 Type* type = NodeProperties::GetType(node->InputAt(1)); 496 WriteBarrierKind kind = ComputeWriteBarrierKind( 497 access.base_is_tagged, access.machine_type.representation(), 498 access.offset, access.type, type); 499 Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); 500 node->InsertInput(graph()->zone(), 1, offset); 501 NodeProperties::ChangeOp(node, 502 machine()->Store(StoreRepresentation( 503 access.machine_type.representation(), kind))); 504 return Changed(node); 505 } 506 507 508 Node* ChangeLowering::ComputeIndex(const ElementAccess& access, 509 Node* const key) { 510 Node* index = key; 511 const int element_size_shift = 512 ElementSizeLog2Of(access.machine_type.representation()); 513 if (element_size_shift) { 514 index = graph()->NewNode(machine()->Word32Shl(), index, 515 jsgraph()->Int32Constant(element_size_shift)); 516 } 517 const int fixed_offset = access.header_size - access.tag(); 518 if (fixed_offset) { 519 index = graph()->NewNode(machine()->Int32Add(), index, 520 jsgraph()->Int32Constant(fixed_offset)); 521 } 522 if (machine()->Is64()) { 523 // TODO(turbofan): This is probably only correct for typed arrays, and only 524 // if the typed arrays are at most 2GiB in size, which happens to match 525 // exactly our current situation. 526 index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index); 527 } 528 return index; 529 } 530 531 532 Reduction ChangeLowering::LoadElement(Node* node) { 533 const ElementAccess& access = ElementAccessOf(node->op()); 534 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); 535 NodeProperties::ChangeOp(node, machine()->Load(access.machine_type)); 536 return Changed(node); 537 } 538 539 540 Reduction ChangeLowering::StoreElement(Node* node) { 541 const ElementAccess& access = ElementAccessOf(node->op()); 542 Type* type = NodeProperties::GetType(node->InputAt(2)); 543 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); 544 NodeProperties::ChangeOp( 545 node, machine()->Store(StoreRepresentation( 546 access.machine_type.representation(), 547 ComputeWriteBarrierKind(access.base_is_tagged, 548 access.machine_type.representation(), 549 access.type, type)))); 550 return Changed(node); 551 } 552 553 554 Reduction ChangeLowering::Allocate(Node* node) { 555 PretenureFlag pretenure = OpParameter<PretenureFlag>(node->op()); 556 if (pretenure == NOT_TENURED) { 557 Callable callable = CodeFactory::AllocateInNewSpace(isolate()); 558 Node* target = jsgraph()->HeapConstant(callable.code()); 559 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( 560 isolate(), jsgraph()->zone(), callable.descriptor(), 0, 561 CallDescriptor::kNoFlags, Operator::kNoThrow); 562 const Operator* op = common()->Call(descriptor); 563 node->InsertInput(graph()->zone(), 0, target); 564 node->InsertInput(graph()->zone(), 2, jsgraph()->NoContextConstant()); 565 NodeProperties::ChangeOp(node, op); 566 } else { 567 DCHECK_EQ(TENURED, pretenure); 568 AllocationSpace space = OLD_SPACE; 569 Runtime::FunctionId f = Runtime::kAllocateInTargetSpace; 570 Operator::Properties props = node->op()->properties(); 571 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( 572 jsgraph()->zone(), f, 2, props, CallDescriptor::kNeedsFrameState); 573 ExternalReference ref(f, jsgraph()->isolate()); 574 int32_t flags = AllocateTargetSpace::encode(space); 575 node->InsertInput(graph()->zone(), 0, jsgraph()->CEntryStubConstant(1)); 576 node->InsertInput(graph()->zone(), 2, jsgraph()->SmiConstant(flags)); 577 node->InsertInput(graph()->zone(), 3, jsgraph()->ExternalConstant(ref)); 578 node->InsertInput(graph()->zone(), 4, jsgraph()->Int32Constant(2)); 579 node->InsertInput(graph()->zone(), 5, jsgraph()->NoContextConstant()); 580 NodeProperties::ChangeOp(node, common()->Call(desc)); 581 } 582 return Changed(node); 583 } 584 585 586 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } 587 588 589 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); } 590 591 592 CommonOperatorBuilder* ChangeLowering::common() const { 593 return jsgraph()->common(); 594 } 595 596 597 MachineOperatorBuilder* ChangeLowering::machine() const { 598 return jsgraph()->machine(); 599 } 600 601 } // namespace compiler 602 } // namespace internal 603 } // namespace v8 604