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/js-generic-lowering.h" 6 7 #include "src/ast/ast.h" 8 #include "src/builtins/builtins-constructor.h" 9 #include "src/code-factory.h" 10 #include "src/code-stubs.h" 11 #include "src/compiler/common-operator.h" 12 #include "src/compiler/js-graph.h" 13 #include "src/compiler/machine-operator.h" 14 #include "src/compiler/node-matchers.h" 15 #include "src/compiler/node-properties.h" 16 #include "src/compiler/operator-properties.h" 17 #include "src/objects-inl.h" 18 19 namespace v8 { 20 namespace internal { 21 namespace compiler { 22 23 namespace { 24 25 CallDescriptor::Flags FrameStateFlagForCall(Node* node) { 26 return OperatorProperties::HasFrameStateInput(node->op()) 27 ? CallDescriptor::kNeedsFrameState 28 : CallDescriptor::kNoFlags; 29 } 30 31 } // namespace 32 33 JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {} 34 35 JSGenericLowering::~JSGenericLowering() {} 36 37 38 Reduction JSGenericLowering::Reduce(Node* node) { 39 switch (node->opcode()) { 40 #define DECLARE_CASE(x) \ 41 case IrOpcode::k##x: \ 42 Lower##x(node); \ 43 break; 44 JS_OP_LIST(DECLARE_CASE) 45 #undef DECLARE_CASE 46 default: 47 // Nothing to see. 48 return NoChange(); 49 } 50 return Changed(node); 51 } 52 53 #define REPLACE_STUB_CALL(Name) \ 54 void JSGenericLowering::LowerJS##Name(Node* node) { \ 55 CallDescriptor::Flags flags = FrameStateFlagForCall(node); \ 56 Callable callable = CodeFactory::Name(isolate()); \ 57 ReplaceWithStubCall(node, callable, flags); \ 58 } 59 REPLACE_STUB_CALL(Add) 60 REPLACE_STUB_CALL(Subtract) 61 REPLACE_STUB_CALL(Multiply) 62 REPLACE_STUB_CALL(Divide) 63 REPLACE_STUB_CALL(Modulus) 64 REPLACE_STUB_CALL(BitwiseAnd) 65 REPLACE_STUB_CALL(BitwiseOr) 66 REPLACE_STUB_CALL(BitwiseXor) 67 REPLACE_STUB_CALL(ShiftLeft) 68 REPLACE_STUB_CALL(ShiftRight) 69 REPLACE_STUB_CALL(ShiftRightLogical) 70 REPLACE_STUB_CALL(LessThan) 71 REPLACE_STUB_CALL(LessThanOrEqual) 72 REPLACE_STUB_CALL(GreaterThan) 73 REPLACE_STUB_CALL(GreaterThanOrEqual) 74 REPLACE_STUB_CALL(HasProperty) 75 REPLACE_STUB_CALL(Equal) 76 REPLACE_STUB_CALL(NotEqual) 77 REPLACE_STUB_CALL(ToInteger) 78 REPLACE_STUB_CALL(ToLength) 79 REPLACE_STUB_CALL(ToNumber) 80 REPLACE_STUB_CALL(ToName) 81 REPLACE_STUB_CALL(ToObject) 82 REPLACE_STUB_CALL(ToString) 83 #undef REPLACE_STUB_CALL 84 85 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, 86 CallDescriptor::Flags flags) { 87 ReplaceWithStubCall(node, callable, flags, node->op()->properties()); 88 } 89 90 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, 91 CallDescriptor::Flags flags, 92 Operator::Properties properties, 93 int result_size) { 94 const CallInterfaceDescriptor& descriptor = callable.descriptor(); 95 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 96 isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags, 97 properties, MachineType::AnyTagged(), result_size); 98 Node* stub_code = jsgraph()->HeapConstant(callable.code()); 99 node->InsertInput(zone(), 0, stub_code); 100 NodeProperties::ChangeOp(node, common()->Call(desc)); 101 } 102 103 104 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, 105 Runtime::FunctionId f, 106 int nargs_override) { 107 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 108 Operator::Properties properties = node->op()->properties(); 109 const Runtime::Function* fun = Runtime::FunctionForId(f); 110 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override; 111 CallDescriptor* desc = 112 Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags); 113 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate())); 114 Node* arity = jsgraph()->Int32Constant(nargs); 115 node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size)); 116 node->InsertInput(zone(), nargs + 1, ref); 117 node->InsertInput(zone(), nargs + 2, arity); 118 NodeProperties::ChangeOp(node, common()->Call(desc)); 119 } 120 121 void JSGenericLowering::LowerJSStrictEqual(Node* node) { 122 // The === operator doesn't need the current context. 123 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); 124 Callable callable = CodeFactory::StrictEqual(isolate()); 125 node->RemoveInput(4); // control 126 ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags, 127 Operator::kEliminatable); 128 } 129 130 void JSGenericLowering::LowerJSStrictNotEqual(Node* node) { 131 // The !== operator doesn't need the current context. 132 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); 133 Callable callable = CodeFactory::StrictNotEqual(isolate()); 134 node->RemoveInput(4); // control 135 ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags, 136 Operator::kEliminatable); 137 } 138 139 void JSGenericLowering::LowerJSToBoolean(Node* node) { 140 // The ToBoolean conversion doesn't need the current context. 141 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); 142 Callable callable = CodeFactory::ToBoolean(isolate()); 143 node->AppendInput(zone(), graph()->start()); 144 ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate, 145 Operator::kEliminatable); 146 } 147 148 void JSGenericLowering::LowerJSClassOf(Node* node) { 149 // The %_ClassOf intrinsic doesn't need the current context. 150 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); 151 Callable callable = CodeFactory::ClassOf(isolate()); 152 node->AppendInput(zone(), graph()->start()); 153 ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate, 154 Operator::kEliminatable); 155 } 156 157 void JSGenericLowering::LowerJSTypeOf(Node* node) { 158 // The typeof operator doesn't need the current context. 159 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); 160 Callable callable = CodeFactory::Typeof(isolate()); 161 node->AppendInput(zone(), graph()->start()); 162 ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate, 163 Operator::kEliminatable); 164 } 165 166 167 void JSGenericLowering::LowerJSLoadProperty(Node* node) { 168 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 169 const PropertyAccess& p = PropertyAccessOf(node->op()); 170 Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate()); 171 Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); 172 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index())); 173 node->InsertInput(zone(), 3, vector); 174 ReplaceWithStubCall(node, callable, flags); 175 } 176 177 178 void JSGenericLowering::LowerJSLoadNamed(Node* node) { 179 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 180 NamedAccess const& p = NamedAccessOf(node->op()); 181 Callable callable = CodeFactory::LoadICInOptimizedCode(isolate()); 182 Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); 183 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name())); 184 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index())); 185 node->InsertInput(zone(), 3, vector); 186 ReplaceWithStubCall(node, callable, flags); 187 } 188 189 190 void JSGenericLowering::LowerJSLoadGlobal(Node* node) { 191 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 192 const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op()); 193 Callable callable = 194 CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode()); 195 Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); 196 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.name())); 197 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index())); 198 node->InsertInput(zone(), 2, vector); 199 ReplaceWithStubCall(node, callable, flags); 200 } 201 202 203 void JSGenericLowering::LowerJSStoreProperty(Node* node) { 204 Node* receiver = NodeProperties::GetValueInput(node, 0); 205 Node* key = NodeProperties::GetValueInput(node, 1); 206 Node* value = NodeProperties::GetValueInput(node, 2); 207 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 208 PropertyAccess const& p = PropertyAccessOf(node->op()); 209 Callable callable = 210 CodeFactory::KeyedStoreICInOptimizedCode(isolate(), p.language_mode()); 211 Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); 212 typedef StoreWithVectorDescriptor Descriptor; 213 node->InsertInputs(zone(), 0, 2); 214 node->ReplaceInput(Descriptor::kReceiver, receiver); 215 node->ReplaceInput(Descriptor::kName, key); 216 node->ReplaceInput(Descriptor::kValue, value); 217 node->ReplaceInput(Descriptor::kSlot, 218 jsgraph()->SmiConstant(p.feedback().index())); 219 node->ReplaceInput(Descriptor::kVector, vector); 220 ReplaceWithStubCall(node, callable, flags); 221 } 222 223 224 void JSGenericLowering::LowerJSStoreNamed(Node* node) { 225 Node* receiver = NodeProperties::GetValueInput(node, 0); 226 Node* value = NodeProperties::GetValueInput(node, 1); 227 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 228 NamedAccess const& p = NamedAccessOf(node->op()); 229 Callable callable = 230 CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode()); 231 Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); 232 typedef StoreWithVectorDescriptor Descriptor; 233 node->InsertInputs(zone(), 0, 3); 234 node->ReplaceInput(Descriptor::kReceiver, receiver); 235 node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name())); 236 node->ReplaceInput(Descriptor::kValue, value); 237 node->ReplaceInput(Descriptor::kSlot, 238 jsgraph()->SmiConstant(p.feedback().index())); 239 node->ReplaceInput(Descriptor::kVector, vector); 240 ReplaceWithStubCall(node, callable, flags); 241 } 242 243 void JSGenericLowering::LowerJSStoreNamedOwn(Node* node) { 244 Node* receiver = NodeProperties::GetValueInput(node, 0); 245 Node* value = NodeProperties::GetValueInput(node, 1); 246 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 247 StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op()); 248 Callable callable = CodeFactory::StoreOwnICInOptimizedCode(isolate()); 249 Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); 250 typedef StoreWithVectorDescriptor Descriptor; 251 node->InsertInputs(zone(), 0, 3); 252 node->ReplaceInput(Descriptor::kReceiver, receiver); 253 node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name())); 254 node->ReplaceInput(Descriptor::kValue, value); 255 node->ReplaceInput(Descriptor::kSlot, 256 jsgraph()->SmiConstant(p.feedback().index())); 257 node->ReplaceInput(Descriptor::kVector, vector); 258 ReplaceWithStubCall(node, callable, flags); 259 } 260 261 void JSGenericLowering::LowerJSStoreGlobal(Node* node) { 262 Node* value = NodeProperties::GetValueInput(node, 0); 263 Node* context = NodeProperties::GetContextInput(node); 264 Node* effect = NodeProperties::GetEffectInput(node); 265 Node* control = NodeProperties::GetControlInput(node); 266 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 267 const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op()); 268 Callable callable = 269 CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode()); 270 Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); 271 // Load global object from the context. 272 Node* native_context = effect = 273 graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context, 274 jsgraph()->IntPtrConstant( 275 Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)), 276 effect, control); 277 Node* global = effect = graph()->NewNode( 278 machine()->Load(MachineType::AnyTagged()), native_context, 279 jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)), 280 effect, control); 281 typedef StoreWithVectorDescriptor Descriptor; 282 node->InsertInputs(zone(), 0, 4); 283 node->ReplaceInput(Descriptor::kReceiver, global); 284 node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name())); 285 node->ReplaceInput(Descriptor::kValue, value); 286 node->ReplaceInput(Descriptor::kSlot, 287 jsgraph()->SmiConstant(p.feedback().index())); 288 node->ReplaceInput(Descriptor::kVector, vector); 289 node->ReplaceInput(7, effect); 290 ReplaceWithStubCall(node, callable, flags); 291 } 292 293 void JSGenericLowering::LowerJSStoreDataPropertyInLiteral(Node* node) { 294 DataPropertyParameters const& p = DataPropertyParametersOf(node->op()); 295 node->InsertInputs(zone(), 4, 2); 296 node->ReplaceInput(4, jsgraph()->HeapConstant(p.feedback().vector())); 297 node->ReplaceInput(5, jsgraph()->SmiConstant(p.feedback().index())); 298 ReplaceWithRuntimeCall(node, Runtime::kDefineDataPropertyInLiteral); 299 } 300 301 void JSGenericLowering::LowerJSDeleteProperty(Node* node) { 302 LanguageMode language_mode = OpParameter<LanguageMode>(node); 303 ReplaceWithRuntimeCall(node, is_strict(language_mode) 304 ? Runtime::kDeleteProperty_Strict 305 : Runtime::kDeleteProperty_Sloppy); 306 } 307 308 void JSGenericLowering::LowerJSGetSuperConstructor(Node* node) { 309 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 310 Callable callable = CodeFactory::GetSuperConstructor(isolate()); 311 ReplaceWithStubCall(node, callable, flags); 312 } 313 314 void JSGenericLowering::LowerJSInstanceOf(Node* node) { 315 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 316 Callable callable = CodeFactory::InstanceOf(isolate()); 317 ReplaceWithStubCall(node, callable, flags); 318 } 319 320 void JSGenericLowering::LowerJSOrdinaryHasInstance(Node* node) { 321 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 322 Callable callable = CodeFactory::OrdinaryHasInstance(isolate()); 323 ReplaceWithStubCall(node, callable, flags); 324 } 325 326 void JSGenericLowering::LowerJSLoadContext(Node* node) { 327 UNREACHABLE(); // Eliminated in typed lowering. 328 } 329 330 331 void JSGenericLowering::LowerJSStoreContext(Node* node) { 332 UNREACHABLE(); // Eliminated in typed lowering. 333 } 334 335 336 void JSGenericLowering::LowerJSCreate(Node* node) { 337 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 338 Callable callable = CodeFactory::FastNewObject(isolate()); 339 ReplaceWithStubCall(node, callable, flags); 340 } 341 342 343 void JSGenericLowering::LowerJSCreateArguments(Node* node) { 344 CreateArgumentsType const type = CreateArgumentsTypeOf(node->op()); 345 switch (type) { 346 case CreateArgumentsType::kMappedArguments: 347 ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic); 348 break; 349 case CreateArgumentsType::kUnmappedArguments: 350 ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments); 351 break; 352 case CreateArgumentsType::kRestParameter: 353 ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter); 354 break; 355 } 356 } 357 358 359 void JSGenericLowering::LowerJSCreateArray(Node* node) { 360 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); 361 int const arity = static_cast<int>(p.arity()); 362 Handle<AllocationSite> const site = p.site(); 363 Node* new_target = node->InputAt(1); 364 Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant() 365 : jsgraph()->HeapConstant(site); 366 node->RemoveInput(1); 367 node->InsertInput(zone(), 1 + arity, new_target); 368 node->InsertInput(zone(), 2 + arity, type_info); 369 ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3); 370 } 371 372 373 void JSGenericLowering::LowerJSCreateClosure(Node* node) { 374 CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); 375 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 376 Handle<SharedFunctionInfo> const shared_info = p.shared_info(); 377 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info)); 378 379 // Use the FastNewClosurebuiltin only for functions allocated in new 380 // space. 381 if (p.pretenure() == NOT_TENURED) { 382 Callable callable = CodeFactory::FastNewClosure(isolate()); 383 node->InsertInput(zone(), 1, 384 jsgraph()->HeapConstant(p.feedback().vector())); 385 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index())); 386 ReplaceWithStubCall(node, callable, flags); 387 } else { 388 node->InsertInput(zone(), 1, 389 jsgraph()->HeapConstant(p.feedback().vector())); 390 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index())); 391 ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED) 392 ? Runtime::kNewClosure_Tenured 393 : Runtime::kNewClosure); 394 } 395 } 396 397 398 void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) { 399 const CreateFunctionContextParameters& parameters = 400 CreateFunctionContextParametersOf(node->op()); 401 int slot_count = parameters.slot_count(); 402 ScopeType scope_type = parameters.scope_type(); 403 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 404 405 if (slot_count <= 406 ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) { 407 Callable callable = 408 CodeFactory::FastNewFunctionContext(isolate(), scope_type); 409 node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count)); 410 ReplaceWithStubCall(node, callable, flags); 411 } else { 412 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(scope_type)); 413 ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext); 414 } 415 } 416 417 418 void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) { 419 ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject); 420 } 421 422 void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) { 423 ReplaceWithRuntimeCall(node, Runtime::kCreateKeyValueArray); 424 } 425 426 void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) { 427 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op()); 428 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 429 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index())); 430 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant())); 431 432 // Use the FastCloneShallowArray builtin only for shallow boilerplates without 433 // properties up to the number of elements that the stubs can handle. 434 if ((p.flags() & ArrayLiteral::kShallowElements) != 0 && 435 p.length() < 436 ConstructorBuiltinsAssembler::kMaximumClonedShallowArrayElements) { 437 Callable callable = CodeFactory::FastCloneShallowArray( 438 isolate(), DONT_TRACK_ALLOCATION_SITE); 439 ReplaceWithStubCall(node, callable, flags); 440 } else { 441 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags())); 442 ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral); 443 } 444 } 445 446 447 void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) { 448 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op()); 449 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 450 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index())); 451 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant())); 452 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags())); 453 454 // Use the FastCloneShallowObject builtin only for shallow boilerplates 455 // without elements up to the number of properties that the stubs can handle. 456 if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 && 457 p.length() <= 458 ConstructorBuiltinsAssembler::kMaximumClonedShallowObjectProperties) { 459 Callable callable = 460 CodeFactory::FastCloneShallowObject(isolate(), p.length()); 461 ReplaceWithStubCall(node, callable, flags); 462 } else { 463 ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral); 464 } 465 } 466 467 468 void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) { 469 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op()); 470 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 471 Callable callable = CodeFactory::FastCloneRegExp(isolate()); 472 Node* literal_index = jsgraph()->SmiConstant(p.index()); 473 Node* literal_flags = jsgraph()->SmiConstant(p.flags()); 474 Node* pattern = jsgraph()->HeapConstant(p.constant()); 475 node->InsertInput(graph()->zone(), 1, literal_index); 476 node->InsertInput(graph()->zone(), 2, pattern); 477 node->InsertInput(graph()->zone(), 3, literal_flags); 478 ReplaceWithStubCall(node, callable, flags); 479 } 480 481 482 void JSGenericLowering::LowerJSCreateCatchContext(Node* node) { 483 const CreateCatchContextParameters& parameters = 484 CreateCatchContextParametersOf(node->op()); 485 node->InsertInput(zone(), 0, 486 jsgraph()->HeapConstant(parameters.catch_name())); 487 node->InsertInput(zone(), 2, 488 jsgraph()->HeapConstant(parameters.scope_info())); 489 ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext); 490 } 491 492 void JSGenericLowering::LowerJSCreateWithContext(Node* node) { 493 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); 494 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info)); 495 ReplaceWithRuntimeCall(node, Runtime::kPushWithContext); 496 } 497 498 void JSGenericLowering::LowerJSCreateBlockContext(Node* node) { 499 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); 500 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info)); 501 ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext); 502 } 503 504 505 void JSGenericLowering::LowerJSCreateScriptContext(Node* node) { 506 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); 507 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info)); 508 ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext); 509 } 510 511 void JSGenericLowering::LowerJSConstruct(Node* node) { 512 ConstructParameters const& p = ConstructParametersOf(node->op()); 513 int const arg_count = static_cast<int>(p.arity() - 2); 514 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 515 Callable callable = CodeFactory::Construct(isolate()); 516 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 517 isolate(), zone(), callable.descriptor(), arg_count + 1, flags); 518 Node* stub_code = jsgraph()->HeapConstant(callable.code()); 519 Node* stub_arity = jsgraph()->Int32Constant(arg_count); 520 Node* new_target = node->InputAt(arg_count + 1); 521 Node* receiver = jsgraph()->UndefinedConstant(); 522 node->RemoveInput(arg_count + 1); // Drop new target. 523 node->InsertInput(zone(), 0, stub_code); 524 node->InsertInput(zone(), 2, new_target); 525 node->InsertInput(zone(), 3, stub_arity); 526 node->InsertInput(zone(), 4, receiver); 527 NodeProperties::ChangeOp(node, common()->Call(desc)); 528 } 529 530 void JSGenericLowering::LowerJSConstructWithSpread(Node* node) { 531 ConstructWithSpreadParameters const& p = 532 ConstructWithSpreadParametersOf(node->op()); 533 int const arg_count = static_cast<int>(p.arity() - 2); 534 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 535 Callable callable = CodeFactory::ConstructWithSpread(isolate()); 536 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 537 isolate(), zone(), callable.descriptor(), arg_count + 1, flags); 538 Node* stub_code = jsgraph()->HeapConstant(callable.code()); 539 Node* stub_arity = jsgraph()->Int32Constant(arg_count); 540 Node* new_target = node->InputAt(arg_count + 1); 541 Node* receiver = jsgraph()->UndefinedConstant(); 542 node->RemoveInput(arg_count + 1); // Drop new target. 543 node->InsertInput(zone(), 0, stub_code); 544 node->InsertInput(zone(), 2, new_target); 545 node->InsertInput(zone(), 3, stub_arity); 546 node->InsertInput(zone(), 4, receiver); 547 NodeProperties::ChangeOp(node, common()->Call(desc)); 548 } 549 550 void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) { 551 CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op()); 552 Callable callable = CodeFactory::CallForwardVarargs(isolate()); 553 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 554 if (p.tail_call_mode() == TailCallMode::kAllow) { 555 flags |= CallDescriptor::kSupportsTailCalls; 556 } 557 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 558 isolate(), zone(), callable.descriptor(), 1, flags); 559 Node* stub_code = jsgraph()->HeapConstant(callable.code()); 560 Node* start_index = jsgraph()->Uint32Constant(p.start_index()); 561 node->InsertInput(zone(), 0, stub_code); 562 node->InsertInput(zone(), 2, start_index); 563 NodeProperties::ChangeOp(node, common()->Call(desc)); 564 } 565 566 void JSGenericLowering::LowerJSCall(Node* node) { 567 CallParameters const& p = CallParametersOf(node->op()); 568 int const arg_count = static_cast<int>(p.arity() - 2); 569 ConvertReceiverMode const mode = p.convert_mode(); 570 Callable callable = CodeFactory::Call(isolate(), mode); 571 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 572 if (p.tail_call_mode() == TailCallMode::kAllow) { 573 flags |= CallDescriptor::kSupportsTailCalls; 574 } 575 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 576 isolate(), zone(), callable.descriptor(), arg_count + 1, flags); 577 Node* stub_code = jsgraph()->HeapConstant(callable.code()); 578 Node* stub_arity = jsgraph()->Int32Constant(arg_count); 579 node->InsertInput(zone(), 0, stub_code); 580 node->InsertInput(zone(), 2, stub_arity); 581 NodeProperties::ChangeOp(node, common()->Call(desc)); 582 } 583 584 void JSGenericLowering::LowerJSCallWithSpread(Node* node) { 585 CallWithSpreadParameters const& p = CallWithSpreadParametersOf(node->op()); 586 int const arg_count = static_cast<int>(p.arity() - 2); 587 Callable callable = CodeFactory::CallWithSpread(isolate()); 588 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 589 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 590 isolate(), zone(), callable.descriptor(), arg_count + 1, flags); 591 Node* stub_code = jsgraph()->HeapConstant(callable.code()); 592 Node* stub_arity = jsgraph()->Int32Constant(arg_count); 593 node->InsertInput(zone(), 0, stub_code); 594 node->InsertInput(zone(), 2, stub_arity); 595 NodeProperties::ChangeOp(node, common()->Call(desc)); 596 } 597 598 void JSGenericLowering::LowerJSCallRuntime(Node* node) { 599 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op()); 600 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity())); 601 } 602 603 void JSGenericLowering::LowerJSConvertReceiver(Node* node) { 604 ReplaceWithRuntimeCall(node, Runtime::kConvertReceiver); 605 } 606 607 void JSGenericLowering::LowerJSForInNext(Node* node) { 608 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 609 Callable callable = CodeFactory::ForInNext(isolate()); 610 ReplaceWithStubCall(node, callable, flags); 611 } 612 613 void JSGenericLowering::LowerJSForInPrepare(Node* node) { 614 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 615 Callable callable = CodeFactory::ForInPrepare(isolate()); 616 ReplaceWithStubCall(node, callable, flags, node->op()->properties(), 3); 617 } 618 619 void JSGenericLowering::LowerJSLoadMessage(Node* node) { 620 UNREACHABLE(); // Eliminated in typed lowering. 621 } 622 623 624 void JSGenericLowering::LowerJSStoreMessage(Node* node) { 625 UNREACHABLE(); // Eliminated in typed lowering. 626 } 627 628 void JSGenericLowering::LowerJSLoadModule(Node* node) { 629 UNREACHABLE(); // Eliminated in typed lowering. 630 } 631 632 void JSGenericLowering::LowerJSStoreModule(Node* node) { 633 UNREACHABLE(); // Eliminated in typed lowering. 634 } 635 636 void JSGenericLowering::LowerJSGeneratorStore(Node* node) { 637 UNREACHABLE(); // Eliminated in typed lowering. 638 } 639 640 void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) { 641 UNREACHABLE(); // Eliminated in typed lowering. 642 } 643 644 void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) { 645 UNREACHABLE(); // Eliminated in typed lowering. 646 } 647 648 void JSGenericLowering::LowerJSStackCheck(Node* node) { 649 Node* effect = NodeProperties::GetEffectInput(node); 650 Node* control = NodeProperties::GetControlInput(node); 651 652 Node* limit = graph()->NewNode( 653 machine()->Load(MachineType::Pointer()), 654 jsgraph()->ExternalConstant( 655 ExternalReference::address_of_stack_limit(isolate())), 656 jsgraph()->IntPtrConstant(0), effect, control); 657 Node* pointer = graph()->NewNode(machine()->LoadStackPointer()); 658 659 Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer); 660 Node* branch = 661 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); 662 663 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 664 Node* etrue = effect; 665 666 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 667 NodeProperties::ReplaceControlInput(node, if_false); 668 Node* efalse = node; 669 670 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 671 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); 672 673 // Wire the new diamond into the graph, {node} can still throw. 674 NodeProperties::ReplaceUses(node, node, ephi, node, node); 675 NodeProperties::ReplaceEffectInput(ephi, efalse, 1); 676 677 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from 678 // the node and places it inside the diamond. Come up with a helper method! 679 for (Node* use : node->uses()) { 680 if (use->opcode() == IrOpcode::kIfSuccess) { 681 use->ReplaceUses(merge); 682 merge->ReplaceInput(1, use); 683 } 684 } 685 686 // Turn the stack check into a runtime call. 687 ReplaceWithRuntimeCall(node, Runtime::kStackGuard); 688 } 689 690 void JSGenericLowering::LowerJSDebugger(Node* node) { 691 CallDescriptor::Flags flags = FrameStateFlagForCall(node); 692 Callable callable = CodeFactory::HandleDebuggerStatement(isolate()); 693 ReplaceWithStubCall(node, callable, flags); 694 } 695 696 Zone* JSGenericLowering::zone() const { return graph()->zone(); } 697 698 699 Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); } 700 701 702 Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); } 703 704 705 CommonOperatorBuilder* JSGenericLowering::common() const { 706 return jsgraph()->common(); 707 } 708 709 710 MachineOperatorBuilder* JSGenericLowering::machine() const { 711 return jsgraph()->machine(); 712 } 713 714 } // namespace compiler 715 } // namespace internal 716 } // namespace v8 717