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-operator.h" 6 7 #include <limits> 8 9 #include "src/base/lazy-instance.h" 10 #include "src/compiler/opcodes.h" 11 #include "src/compiler/operator.h" 12 #include "src/handles-inl.h" 13 #include "src/type-feedback-vector.h" 14 15 namespace v8 { 16 namespace internal { 17 namespace compiler { 18 19 VectorSlotPair::VectorSlotPair() {} 20 21 22 int VectorSlotPair::index() const { 23 return vector_.is_null() ? -1 : vector_->GetIndex(slot_); 24 } 25 26 27 bool operator==(VectorSlotPair const& lhs, VectorSlotPair const& rhs) { 28 return lhs.slot() == rhs.slot() && 29 lhs.vector().location() == rhs.vector().location(); 30 } 31 32 33 bool operator!=(VectorSlotPair const& lhs, VectorSlotPair const& rhs) { 34 return !(lhs == rhs); 35 } 36 37 38 size_t hash_value(VectorSlotPair const& p) { 39 return base::hash_combine(p.slot(), p.vector().location()); 40 } 41 42 43 ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) { 44 DCHECK_EQ(IrOpcode::kJSConvertReceiver, op->opcode()); 45 return OpParameter<ConvertReceiverMode>(op); 46 } 47 48 49 ToBooleanHints ToBooleanHintsOf(Operator const* op) { 50 DCHECK_EQ(IrOpcode::kJSToBoolean, op->opcode()); 51 return OpParameter<ToBooleanHints>(op); 52 } 53 54 55 bool operator==(CallConstructParameters const& lhs, 56 CallConstructParameters const& rhs) { 57 return lhs.arity() == rhs.arity() && lhs.frequency() == rhs.frequency() && 58 lhs.feedback() == rhs.feedback(); 59 } 60 61 62 bool operator!=(CallConstructParameters const& lhs, 63 CallConstructParameters const& rhs) { 64 return !(lhs == rhs); 65 } 66 67 68 size_t hash_value(CallConstructParameters const& p) { 69 return base::hash_combine(p.arity(), p.frequency(), p.feedback()); 70 } 71 72 73 std::ostream& operator<<(std::ostream& os, CallConstructParameters const& p) { 74 return os << p.arity() << ", " << p.frequency(); 75 } 76 77 78 CallConstructParameters const& CallConstructParametersOf(Operator const* op) { 79 DCHECK_EQ(IrOpcode::kJSCallConstruct, op->opcode()); 80 return OpParameter<CallConstructParameters>(op); 81 } 82 83 84 std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) { 85 os << p.arity() << ", " << p.frequency() << ", " << p.convert_mode() << ", " 86 << p.tail_call_mode(); 87 return os; 88 } 89 90 91 const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) { 92 DCHECK_EQ(IrOpcode::kJSCallFunction, op->opcode()); 93 return OpParameter<CallFunctionParameters>(op); 94 } 95 96 97 bool operator==(CallRuntimeParameters const& lhs, 98 CallRuntimeParameters const& rhs) { 99 return lhs.id() == rhs.id() && lhs.arity() == rhs.arity(); 100 } 101 102 103 bool operator!=(CallRuntimeParameters const& lhs, 104 CallRuntimeParameters const& rhs) { 105 return !(lhs == rhs); 106 } 107 108 109 size_t hash_value(CallRuntimeParameters const& p) { 110 return base::hash_combine(p.id(), p.arity()); 111 } 112 113 114 std::ostream& operator<<(std::ostream& os, CallRuntimeParameters const& p) { 115 return os << p.id() << ", " << p.arity(); 116 } 117 118 119 const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) { 120 DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode()); 121 return OpParameter<CallRuntimeParameters>(op); 122 } 123 124 125 ContextAccess::ContextAccess(size_t depth, size_t index, bool immutable) 126 : immutable_(immutable), 127 depth_(static_cast<uint16_t>(depth)), 128 index_(static_cast<uint32_t>(index)) { 129 DCHECK(depth <= std::numeric_limits<uint16_t>::max()); 130 DCHECK(index <= std::numeric_limits<uint32_t>::max()); 131 } 132 133 134 bool operator==(ContextAccess const& lhs, ContextAccess const& rhs) { 135 return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() && 136 lhs.immutable() == rhs.immutable(); 137 } 138 139 140 bool operator!=(ContextAccess const& lhs, ContextAccess const& rhs) { 141 return !(lhs == rhs); 142 } 143 144 145 size_t hash_value(ContextAccess const& access) { 146 return base::hash_combine(access.depth(), access.index(), access.immutable()); 147 } 148 149 150 std::ostream& operator<<(std::ostream& os, ContextAccess const& access) { 151 return os << access.depth() << ", " << access.index() << ", " 152 << access.immutable(); 153 } 154 155 156 ContextAccess const& ContextAccessOf(Operator const* op) { 157 DCHECK(op->opcode() == IrOpcode::kJSLoadContext || 158 op->opcode() == IrOpcode::kJSStoreContext); 159 return OpParameter<ContextAccess>(op); 160 } 161 162 CreateCatchContextParameters::CreateCatchContextParameters( 163 Handle<String> catch_name, Handle<ScopeInfo> scope_info) 164 : catch_name_(catch_name), scope_info_(scope_info) {} 165 166 bool operator==(CreateCatchContextParameters const& lhs, 167 CreateCatchContextParameters const& rhs) { 168 return lhs.catch_name().location() == rhs.catch_name().location() && 169 lhs.scope_info().location() == rhs.scope_info().location(); 170 } 171 172 bool operator!=(CreateCatchContextParameters const& lhs, 173 CreateCatchContextParameters const& rhs) { 174 return !(lhs == rhs); 175 } 176 177 size_t hash_value(CreateCatchContextParameters const& parameters) { 178 return base::hash_combine(parameters.catch_name().location(), 179 parameters.scope_info().location()); 180 } 181 182 std::ostream& operator<<(std::ostream& os, 183 CreateCatchContextParameters const& parameters) { 184 return os << Brief(*parameters.catch_name()) << ", " 185 << Brief(*parameters.scope_info()); 186 } 187 188 CreateCatchContextParameters const& CreateCatchContextParametersOf( 189 Operator const* op) { 190 DCHECK_EQ(IrOpcode::kJSCreateCatchContext, op->opcode()); 191 return OpParameter<CreateCatchContextParameters>(op); 192 } 193 194 bool operator==(NamedAccess const& lhs, NamedAccess const& rhs) { 195 return lhs.name().location() == rhs.name().location() && 196 lhs.language_mode() == rhs.language_mode() && 197 lhs.feedback() == rhs.feedback(); 198 } 199 200 201 bool operator!=(NamedAccess const& lhs, NamedAccess const& rhs) { 202 return !(lhs == rhs); 203 } 204 205 206 size_t hash_value(NamedAccess const& p) { 207 return base::hash_combine(p.name().location(), p.language_mode(), 208 p.feedback()); 209 } 210 211 212 std::ostream& operator<<(std::ostream& os, NamedAccess const& p) { 213 return os << Brief(*p.name()) << ", " << p.language_mode(); 214 } 215 216 217 NamedAccess const& NamedAccessOf(const Operator* op) { 218 DCHECK(op->opcode() == IrOpcode::kJSLoadNamed || 219 op->opcode() == IrOpcode::kJSStoreNamed); 220 return OpParameter<NamedAccess>(op); 221 } 222 223 224 std::ostream& operator<<(std::ostream& os, PropertyAccess const& p) { 225 return os << p.language_mode(); 226 } 227 228 229 bool operator==(PropertyAccess const& lhs, PropertyAccess const& rhs) { 230 return lhs.language_mode() == rhs.language_mode() && 231 lhs.feedback() == rhs.feedback(); 232 } 233 234 235 bool operator!=(PropertyAccess const& lhs, PropertyAccess const& rhs) { 236 return !(lhs == rhs); 237 } 238 239 240 PropertyAccess const& PropertyAccessOf(const Operator* op) { 241 DCHECK(op->opcode() == IrOpcode::kJSLoadProperty || 242 op->opcode() == IrOpcode::kJSStoreProperty); 243 return OpParameter<PropertyAccess>(op); 244 } 245 246 247 size_t hash_value(PropertyAccess const& p) { 248 return base::hash_combine(p.language_mode(), p.feedback()); 249 } 250 251 252 bool operator==(LoadGlobalParameters const& lhs, 253 LoadGlobalParameters const& rhs) { 254 return lhs.name().location() == rhs.name().location() && 255 lhs.feedback() == rhs.feedback() && 256 lhs.typeof_mode() == rhs.typeof_mode(); 257 } 258 259 260 bool operator!=(LoadGlobalParameters const& lhs, 261 LoadGlobalParameters const& rhs) { 262 return !(lhs == rhs); 263 } 264 265 266 size_t hash_value(LoadGlobalParameters const& p) { 267 return base::hash_combine(p.name().location(), p.typeof_mode()); 268 } 269 270 271 std::ostream& operator<<(std::ostream& os, LoadGlobalParameters const& p) { 272 return os << Brief(*p.name()) << ", " << p.typeof_mode(); 273 } 274 275 276 const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op) { 277 DCHECK_EQ(IrOpcode::kJSLoadGlobal, op->opcode()); 278 return OpParameter<LoadGlobalParameters>(op); 279 } 280 281 282 bool operator==(StoreGlobalParameters const& lhs, 283 StoreGlobalParameters const& rhs) { 284 return lhs.language_mode() == rhs.language_mode() && 285 lhs.name().location() == rhs.name().location() && 286 lhs.feedback() == rhs.feedback(); 287 } 288 289 290 bool operator!=(StoreGlobalParameters const& lhs, 291 StoreGlobalParameters const& rhs) { 292 return !(lhs == rhs); 293 } 294 295 296 size_t hash_value(StoreGlobalParameters const& p) { 297 return base::hash_combine(p.language_mode(), p.name().location(), 298 p.feedback()); 299 } 300 301 302 std::ostream& operator<<(std::ostream& os, StoreGlobalParameters const& p) { 303 return os << p.language_mode() << ", " << Brief(*p.name()); 304 } 305 306 307 const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op) { 308 DCHECK_EQ(IrOpcode::kJSStoreGlobal, op->opcode()); 309 return OpParameter<StoreGlobalParameters>(op); 310 } 311 312 313 CreateArgumentsType const& CreateArgumentsTypeOf(const Operator* op) { 314 DCHECK_EQ(IrOpcode::kJSCreateArguments, op->opcode()); 315 return OpParameter<CreateArgumentsType>(op); 316 } 317 318 319 bool operator==(CreateArrayParameters const& lhs, 320 CreateArrayParameters const& rhs) { 321 return lhs.arity() == rhs.arity() && 322 lhs.site().location() == rhs.site().location(); 323 } 324 325 326 bool operator!=(CreateArrayParameters const& lhs, 327 CreateArrayParameters const& rhs) { 328 return !(lhs == rhs); 329 } 330 331 332 size_t hash_value(CreateArrayParameters const& p) { 333 return base::hash_combine(p.arity(), p.site().location()); 334 } 335 336 337 std::ostream& operator<<(std::ostream& os, CreateArrayParameters const& p) { 338 os << p.arity(); 339 if (!p.site().is_null()) os << ", " << Brief(*p.site()); 340 return os; 341 } 342 343 344 const CreateArrayParameters& CreateArrayParametersOf(const Operator* op) { 345 DCHECK_EQ(IrOpcode::kJSCreateArray, op->opcode()); 346 return OpParameter<CreateArrayParameters>(op); 347 } 348 349 350 bool operator==(CreateClosureParameters const& lhs, 351 CreateClosureParameters const& rhs) { 352 return lhs.pretenure() == rhs.pretenure() && 353 lhs.shared_info().location() == rhs.shared_info().location(); 354 } 355 356 357 bool operator!=(CreateClosureParameters const& lhs, 358 CreateClosureParameters const& rhs) { 359 return !(lhs == rhs); 360 } 361 362 363 size_t hash_value(CreateClosureParameters const& p) { 364 return base::hash_combine(p.pretenure(), p.shared_info().location()); 365 } 366 367 368 std::ostream& operator<<(std::ostream& os, CreateClosureParameters const& p) { 369 return os << p.pretenure() << ", " << Brief(*p.shared_info()); 370 } 371 372 373 const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) { 374 DCHECK_EQ(IrOpcode::kJSCreateClosure, op->opcode()); 375 return OpParameter<CreateClosureParameters>(op); 376 } 377 378 379 bool operator==(CreateLiteralParameters const& lhs, 380 CreateLiteralParameters const& rhs) { 381 return lhs.constant().location() == rhs.constant().location() && 382 lhs.length() == rhs.length() && lhs.flags() == rhs.flags() && 383 lhs.index() == rhs.index(); 384 } 385 386 387 bool operator!=(CreateLiteralParameters const& lhs, 388 CreateLiteralParameters const& rhs) { 389 return !(lhs == rhs); 390 } 391 392 393 size_t hash_value(CreateLiteralParameters const& p) { 394 return base::hash_combine(p.constant().location(), p.length(), p.flags(), 395 p.index()); 396 } 397 398 399 std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) { 400 return os << Brief(*p.constant()) << ", " << p.length() << ", " << p.flags() 401 << ", " << p.index(); 402 } 403 404 405 const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) { 406 DCHECK(op->opcode() == IrOpcode::kJSCreateLiteralArray || 407 op->opcode() == IrOpcode::kJSCreateLiteralObject || 408 op->opcode() == IrOpcode::kJSCreateLiteralRegExp); 409 return OpParameter<CreateLiteralParameters>(op); 410 } 411 412 BinaryOperationHint BinaryOperationHintOf(const Operator* op) { 413 DCHECK(op->opcode() == IrOpcode::kJSBitwiseOr || 414 op->opcode() == IrOpcode::kJSBitwiseXor || 415 op->opcode() == IrOpcode::kJSBitwiseAnd || 416 op->opcode() == IrOpcode::kJSShiftLeft || 417 op->opcode() == IrOpcode::kJSShiftRight || 418 op->opcode() == IrOpcode::kJSShiftRightLogical || 419 op->opcode() == IrOpcode::kJSAdd || 420 op->opcode() == IrOpcode::kJSSubtract || 421 op->opcode() == IrOpcode::kJSMultiply || 422 op->opcode() == IrOpcode::kJSDivide || 423 op->opcode() == IrOpcode::kJSModulus); 424 return OpParameter<BinaryOperationHint>(op); 425 } 426 427 CompareOperationHint CompareOperationHintOf(const Operator* op) { 428 DCHECK(op->opcode() == IrOpcode::kJSEqual || 429 op->opcode() == IrOpcode::kJSNotEqual || 430 op->opcode() == IrOpcode::kJSStrictEqual || 431 op->opcode() == IrOpcode::kJSStrictNotEqual || 432 op->opcode() == IrOpcode::kJSLessThan || 433 op->opcode() == IrOpcode::kJSGreaterThan || 434 op->opcode() == IrOpcode::kJSLessThanOrEqual || 435 op->opcode() == IrOpcode::kJSGreaterThanOrEqual); 436 return OpParameter<CompareOperationHint>(op); 437 } 438 439 #define CACHED_OP_LIST(V) \ 440 V(ToInteger, Operator::kNoProperties, 1, 1) \ 441 V(ToLength, Operator::kNoProperties, 1, 1) \ 442 V(ToName, Operator::kNoProperties, 1, 1) \ 443 V(ToNumber, Operator::kNoProperties, 1, 1) \ 444 V(ToObject, Operator::kFoldable, 1, 1) \ 445 V(ToString, Operator::kNoProperties, 1, 1) \ 446 V(Create, Operator::kEliminatable, 2, 1) \ 447 V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \ 448 V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \ 449 V(HasProperty, Operator::kNoProperties, 2, 1) \ 450 V(TypeOf, Operator::kPure, 1, 1) \ 451 V(InstanceOf, Operator::kNoProperties, 2, 1) \ 452 V(OrdinaryHasInstance, Operator::kNoProperties, 2, 1) \ 453 V(ForInNext, Operator::kNoProperties, 4, 1) \ 454 V(ForInPrepare, Operator::kNoProperties, 1, 3) \ 455 V(LoadMessage, Operator::kNoThrow, 0, 1) \ 456 V(StoreMessage, Operator::kNoThrow, 1, 0) \ 457 V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \ 458 V(StackCheck, Operator::kNoWrite, 0, 0) 459 460 #define BINARY_OP_LIST(V) \ 461 V(BitwiseOr) \ 462 V(BitwiseXor) \ 463 V(BitwiseAnd) \ 464 V(ShiftLeft) \ 465 V(ShiftRight) \ 466 V(ShiftRightLogical) \ 467 V(Add) \ 468 V(Subtract) \ 469 V(Multiply) \ 470 V(Divide) \ 471 V(Modulus) 472 473 #define COMPARE_OP_LIST(V) \ 474 V(Equal, Operator::kNoProperties) \ 475 V(NotEqual, Operator::kNoProperties) \ 476 V(StrictEqual, Operator::kPure) \ 477 V(StrictNotEqual, Operator::kPure) \ 478 V(LessThan, Operator::kNoProperties) \ 479 V(GreaterThan, Operator::kNoProperties) \ 480 V(LessThanOrEqual, Operator::kNoProperties) \ 481 V(GreaterThanOrEqual, Operator::kNoProperties) 482 483 struct JSOperatorGlobalCache final { 484 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \ 485 struct Name##Operator final : public Operator { \ 486 Name##Operator() \ 487 : Operator(IrOpcode::kJS##Name, properties, "JS" #Name, \ 488 value_input_count, Operator::ZeroIfPure(properties), \ 489 Operator::ZeroIfEliminatable(properties), \ 490 value_output_count, Operator::ZeroIfPure(properties), \ 491 Operator::ZeroIfNoThrow(properties)) {} \ 492 }; \ 493 Name##Operator k##Name##Operator; 494 CACHED_OP_LIST(CACHED_OP) 495 #undef CACHED_OP 496 497 #define BINARY_OP(Name) \ 498 template <BinaryOperationHint kHint> \ 499 struct Name##Operator final : public Operator1<BinaryOperationHint> { \ 500 Name##Operator() \ 501 : Operator1<BinaryOperationHint>(IrOpcode::kJS##Name, \ 502 Operator::kNoProperties, "JS" #Name, \ 503 2, 1, 1, 1, 1, 2, kHint) {} \ 504 }; \ 505 Name##Operator<BinaryOperationHint::kNone> k##Name##NoneOperator; \ 506 Name##Operator<BinaryOperationHint::kSignedSmall> \ 507 k##Name##SignedSmallOperator; \ 508 Name##Operator<BinaryOperationHint::kSigned32> k##Name##Signed32Operator; \ 509 Name##Operator<BinaryOperationHint::kNumberOrOddball> \ 510 k##Name##NumberOrOddballOperator; \ 511 Name##Operator<BinaryOperationHint::kString> k##Name##StringOperator; \ 512 Name##Operator<BinaryOperationHint::kAny> k##Name##AnyOperator; 513 BINARY_OP_LIST(BINARY_OP) 514 #undef BINARY_OP 515 516 #define COMPARE_OP(Name, properties) \ 517 template <CompareOperationHint kHint> \ 518 struct Name##Operator final : public Operator1<CompareOperationHint> { \ 519 Name##Operator() \ 520 : Operator1<CompareOperationHint>( \ 521 IrOpcode::kJS##Name, properties, "JS" #Name, 2, 1, 1, 1, 1, \ 522 Operator::ZeroIfNoThrow(properties), kHint) {} \ 523 }; \ 524 Name##Operator<CompareOperationHint::kNone> k##Name##NoneOperator; \ 525 Name##Operator<CompareOperationHint::kSignedSmall> \ 526 k##Name##SignedSmallOperator; \ 527 Name##Operator<CompareOperationHint::kNumber> k##Name##NumberOperator; \ 528 Name##Operator<CompareOperationHint::kNumberOrOddball> \ 529 k##Name##NumberOrOddballOperator; \ 530 Name##Operator<CompareOperationHint::kAny> k##Name##AnyOperator; 531 COMPARE_OP_LIST(COMPARE_OP) 532 #undef COMPARE_OP 533 }; 534 535 static base::LazyInstance<JSOperatorGlobalCache>::type kCache = 536 LAZY_INSTANCE_INITIALIZER; 537 538 JSOperatorBuilder::JSOperatorBuilder(Zone* zone) 539 : cache_(kCache.Get()), zone_(zone) {} 540 541 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \ 542 const Operator* JSOperatorBuilder::Name() { \ 543 return &cache_.k##Name##Operator; \ 544 } 545 CACHED_OP_LIST(CACHED_OP) 546 #undef CACHED_OP 547 548 #define BINARY_OP(Name) \ 549 const Operator* JSOperatorBuilder::Name(BinaryOperationHint hint) { \ 550 switch (hint) { \ 551 case BinaryOperationHint::kNone: \ 552 return &cache_.k##Name##NoneOperator; \ 553 case BinaryOperationHint::kSignedSmall: \ 554 return &cache_.k##Name##SignedSmallOperator; \ 555 case BinaryOperationHint::kSigned32: \ 556 return &cache_.k##Name##Signed32Operator; \ 557 case BinaryOperationHint::kNumberOrOddball: \ 558 return &cache_.k##Name##NumberOrOddballOperator; \ 559 case BinaryOperationHint::kString: \ 560 return &cache_.k##Name##StringOperator; \ 561 case BinaryOperationHint::kAny: \ 562 return &cache_.k##Name##AnyOperator; \ 563 } \ 564 UNREACHABLE(); \ 565 return nullptr; \ 566 } 567 BINARY_OP_LIST(BINARY_OP) 568 #undef BINARY_OP 569 570 #define COMPARE_OP(Name, ...) \ 571 const Operator* JSOperatorBuilder::Name(CompareOperationHint hint) { \ 572 switch (hint) { \ 573 case CompareOperationHint::kNone: \ 574 return &cache_.k##Name##NoneOperator; \ 575 case CompareOperationHint::kSignedSmall: \ 576 return &cache_.k##Name##SignedSmallOperator; \ 577 case CompareOperationHint::kNumber: \ 578 return &cache_.k##Name##NumberOperator; \ 579 case CompareOperationHint::kNumberOrOddball: \ 580 return &cache_.k##Name##NumberOrOddballOperator; \ 581 case CompareOperationHint::kAny: \ 582 return &cache_.k##Name##AnyOperator; \ 583 } \ 584 UNREACHABLE(); \ 585 return nullptr; \ 586 } 587 COMPARE_OP_LIST(COMPARE_OP) 588 #undef COMPARE_OP 589 590 const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) { 591 // TODO(turbofan): Cache most important versions of this operator. 592 return new (zone()) Operator1<ToBooleanHints>( //-- 593 IrOpcode::kJSToBoolean, Operator::kPure, // opcode 594 "JSToBoolean", // name 595 1, 0, 0, 1, 0, 0, // inputs/outputs 596 hints); // parameter 597 } 598 599 const Operator* JSOperatorBuilder::CallFunction( 600 size_t arity, float frequency, VectorSlotPair const& feedback, 601 ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) { 602 CallFunctionParameters parameters(arity, frequency, feedback, tail_call_mode, 603 convert_mode); 604 return new (zone()) Operator1<CallFunctionParameters>( // -- 605 IrOpcode::kJSCallFunction, Operator::kNoProperties, // opcode 606 "JSCallFunction", // name 607 parameters.arity(), 1, 1, 1, 1, 2, // inputs/outputs 608 parameters); // parameter 609 } 610 611 612 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id) { 613 const Runtime::Function* f = Runtime::FunctionForId(id); 614 return CallRuntime(f, f->nargs); 615 } 616 617 618 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id, 619 size_t arity) { 620 const Runtime::Function* f = Runtime::FunctionForId(id); 621 return CallRuntime(f, arity); 622 } 623 624 625 const Operator* JSOperatorBuilder::CallRuntime(const Runtime::Function* f, 626 size_t arity) { 627 CallRuntimeParameters parameters(f->function_id, arity); 628 DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity())); 629 return new (zone()) Operator1<CallRuntimeParameters>( // -- 630 IrOpcode::kJSCallRuntime, Operator::kNoProperties, // opcode 631 "JSCallRuntime", // name 632 parameters.arity(), 1, 1, f->result_size, 1, 2, // inputs/outputs 633 parameters); // parameter 634 } 635 636 const Operator* JSOperatorBuilder::CallConstruct( 637 uint32_t arity, float frequency, VectorSlotPair const& feedback) { 638 CallConstructParameters parameters(arity, frequency, feedback); 639 return new (zone()) Operator1<CallConstructParameters>( // -- 640 IrOpcode::kJSCallConstruct, Operator::kNoProperties, // opcode 641 "JSCallConstruct", // name 642 parameters.arity(), 1, 1, 1, 1, 2, // counts 643 parameters); // parameter 644 } 645 646 647 const Operator* JSOperatorBuilder::ConvertReceiver( 648 ConvertReceiverMode convert_mode) { 649 return new (zone()) Operator1<ConvertReceiverMode>( // -- 650 IrOpcode::kJSConvertReceiver, Operator::kEliminatable, // opcode 651 "JSConvertReceiver", // name 652 1, 1, 1, 1, 1, 0, // counts 653 convert_mode); // parameter 654 } 655 656 const Operator* JSOperatorBuilder::LoadNamed(Handle<Name> name, 657 const VectorSlotPair& feedback) { 658 NamedAccess access(SLOPPY, name, feedback); 659 return new (zone()) Operator1<NamedAccess>( // -- 660 IrOpcode::kJSLoadNamed, Operator::kNoProperties, // opcode 661 "JSLoadNamed", // name 662 2, 1, 1, 1, 1, 2, // counts 663 access); // parameter 664 } 665 666 const Operator* JSOperatorBuilder::LoadProperty( 667 VectorSlotPair const& feedback) { 668 PropertyAccess access(SLOPPY, feedback); 669 return new (zone()) Operator1<PropertyAccess>( // -- 670 IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode 671 "JSLoadProperty", // name 672 3, 1, 1, 1, 1, 2, // counts 673 access); // parameter 674 } 675 676 const Operator* JSOperatorBuilder::GeneratorStore(int register_count) { 677 return new (zone()) Operator1<int>( // -- 678 IrOpcode::kJSGeneratorStore, Operator::kNoThrow, // opcode 679 "JSGeneratorStore", // name 680 3 + register_count, 1, 1, 0, 1, 0, // counts 681 register_count); // parameter 682 } 683 684 const Operator* JSOperatorBuilder::GeneratorRestoreRegister(int index) { 685 return new (zone()) Operator1<int>( // -- 686 IrOpcode::kJSGeneratorRestoreRegister, Operator::kNoThrow, // opcode 687 "JSGeneratorRestoreRegister", // name 688 1, 1, 1, 1, 1, 0, // counts 689 index); // parameter 690 } 691 692 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode, 693 Handle<Name> name, 694 VectorSlotPair const& feedback) { 695 NamedAccess access(language_mode, name, feedback); 696 return new (zone()) Operator1<NamedAccess>( // -- 697 IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode 698 "JSStoreNamed", // name 699 3, 1, 1, 0, 1, 2, // counts 700 access); // parameter 701 } 702 703 704 const Operator* JSOperatorBuilder::StoreProperty( 705 LanguageMode language_mode, VectorSlotPair const& feedback) { 706 PropertyAccess access(language_mode, feedback); 707 return new (zone()) Operator1<PropertyAccess>( // -- 708 IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode 709 "JSStoreProperty", // name 710 4, 1, 1, 0, 1, 2, // counts 711 access); // parameter 712 } 713 714 715 const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) { 716 return new (zone()) Operator1<LanguageMode>( // -- 717 IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode 718 "JSDeleteProperty", // name 719 2, 1, 1, 1, 1, 2, // counts 720 language_mode); // parameter 721 } 722 723 724 const Operator* JSOperatorBuilder::LoadGlobal(const Handle<Name>& name, 725 const VectorSlotPair& feedback, 726 TypeofMode typeof_mode) { 727 LoadGlobalParameters parameters(name, feedback, typeof_mode); 728 return new (zone()) Operator1<LoadGlobalParameters>( // -- 729 IrOpcode::kJSLoadGlobal, Operator::kNoProperties, // opcode 730 "JSLoadGlobal", // name 731 1, 1, 1, 1, 1, 2, // counts 732 parameters); // parameter 733 } 734 735 736 const Operator* JSOperatorBuilder::StoreGlobal(LanguageMode language_mode, 737 const Handle<Name>& name, 738 const VectorSlotPair& feedback) { 739 StoreGlobalParameters parameters(language_mode, feedback, name); 740 return new (zone()) Operator1<StoreGlobalParameters>( // -- 741 IrOpcode::kJSStoreGlobal, Operator::kNoProperties, // opcode 742 "JSStoreGlobal", // name 743 2, 1, 1, 0, 1, 2, // counts 744 parameters); // parameter 745 } 746 747 748 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index, 749 bool immutable) { 750 ContextAccess access(depth, index, immutable); 751 return new (zone()) Operator1<ContextAccess>( // -- 752 IrOpcode::kJSLoadContext, // opcode 753 Operator::kNoWrite | Operator::kNoThrow, // flags 754 "JSLoadContext", // name 755 1, 1, 0, 1, 1, 0, // counts 756 access); // parameter 757 } 758 759 760 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) { 761 ContextAccess access(depth, index, false); 762 return new (zone()) Operator1<ContextAccess>( // -- 763 IrOpcode::kJSStoreContext, // opcode 764 Operator::kNoRead | Operator::kNoThrow, // flags 765 "JSStoreContext", // name 766 2, 1, 1, 0, 1, 0, // counts 767 access); // parameter 768 } 769 770 const Operator* JSOperatorBuilder::LoadModule(int32_t cell_index) { 771 return new (zone()) Operator1<int32_t>( // -- 772 IrOpcode::kJSLoadModule, // opcode 773 Operator::kNoWrite | Operator::kNoThrow, // flags 774 "JSLoadModule", // name 775 1, 1, 1, 1, 1, 0, // counts 776 cell_index); // parameter 777 } 778 779 const Operator* JSOperatorBuilder::StoreModule(int32_t cell_index) { 780 return new (zone()) Operator1<int32_t>( // -- 781 IrOpcode::kJSStoreModule, // opcode 782 Operator::kNoRead | Operator::kNoThrow, // flags 783 "JSStoreModule", // name 784 2, 1, 1, 0, 1, 0, // counts 785 cell_index); // parameter 786 } 787 788 const Operator* JSOperatorBuilder::CreateArguments(CreateArgumentsType type) { 789 return new (zone()) Operator1<CreateArgumentsType>( // -- 790 IrOpcode::kJSCreateArguments, Operator::kEliminatable, // opcode 791 "JSCreateArguments", // name 792 1, 1, 0, 1, 1, 0, // counts 793 type); // parameter 794 } 795 796 797 const Operator* JSOperatorBuilder::CreateArray(size_t arity, 798 Handle<AllocationSite> site) { 799 // constructor, new_target, arg1, ..., argN 800 int const value_input_count = static_cast<int>(arity) + 2; 801 CreateArrayParameters parameters(arity, site); 802 return new (zone()) Operator1<CreateArrayParameters>( // -- 803 IrOpcode::kJSCreateArray, Operator::kNoProperties, // opcode 804 "JSCreateArray", // name 805 value_input_count, 1, 1, 1, 1, 2, // counts 806 parameters); // parameter 807 } 808 809 810 const Operator* JSOperatorBuilder::CreateClosure( 811 Handle<SharedFunctionInfo> shared_info, PretenureFlag pretenure) { 812 CreateClosureParameters parameters(shared_info, pretenure); 813 return new (zone()) Operator1<CreateClosureParameters>( // -- 814 IrOpcode::kJSCreateClosure, Operator::kNoThrow, // opcode 815 "JSCreateClosure", // name 816 0, 1, 1, 1, 1, 0, // counts 817 parameters); // parameter 818 } 819 820 const Operator* JSOperatorBuilder::CreateLiteralArray( 821 Handle<FixedArray> constant_elements, int literal_flags, int literal_index, 822 int number_of_elements) { 823 CreateLiteralParameters parameters(constant_elements, number_of_elements, 824 literal_flags, literal_index); 825 return new (zone()) Operator1<CreateLiteralParameters>( // -- 826 IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties, // opcode 827 "JSCreateLiteralArray", // name 828 1, 1, 1, 1, 1, 2, // counts 829 parameters); // parameter 830 } 831 832 const Operator* JSOperatorBuilder::CreateLiteralObject( 833 Handle<FixedArray> constant_properties, int literal_flags, 834 int literal_index, int number_of_properties) { 835 CreateLiteralParameters parameters(constant_properties, number_of_properties, 836 literal_flags, literal_index); 837 return new (zone()) Operator1<CreateLiteralParameters>( // -- 838 IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties, // opcode 839 "JSCreateLiteralObject", // name 840 1, 1, 1, 1, 1, 2, // counts 841 parameters); // parameter 842 } 843 844 845 const Operator* JSOperatorBuilder::CreateLiteralRegExp( 846 Handle<String> constant_pattern, int literal_flags, int literal_index) { 847 CreateLiteralParameters parameters(constant_pattern, -1, literal_flags, 848 literal_index); 849 return new (zone()) Operator1<CreateLiteralParameters>( // -- 850 IrOpcode::kJSCreateLiteralRegExp, Operator::kNoProperties, // opcode 851 "JSCreateLiteralRegExp", // name 852 1, 1, 1, 1, 1, 2, // counts 853 parameters); // parameter 854 } 855 856 857 const Operator* JSOperatorBuilder::CreateFunctionContext(int slot_count) { 858 return new (zone()) Operator1<int>( // -- 859 IrOpcode::kJSCreateFunctionContext, Operator::kNoProperties, // opcode 860 "JSCreateFunctionContext", // name 861 1, 1, 1, 1, 1, 2, // counts 862 slot_count); // parameter 863 } 864 865 const Operator* JSOperatorBuilder::CreateCatchContext( 866 const Handle<String>& name, const Handle<ScopeInfo>& scope_info) { 867 CreateCatchContextParameters parameters(name, scope_info); 868 return new (zone()) Operator1<CreateCatchContextParameters>( 869 IrOpcode::kJSCreateCatchContext, Operator::kNoProperties, // opcode 870 "JSCreateCatchContext", // name 871 2, 1, 1, 1, 1, 2, // counts 872 parameters); // parameter 873 } 874 875 const Operator* JSOperatorBuilder::CreateWithContext( 876 const Handle<ScopeInfo>& scope_info) { 877 return new (zone()) Operator1<Handle<ScopeInfo>>( 878 IrOpcode::kJSCreateWithContext, Operator::kNoProperties, // opcode 879 "JSCreateWithContext", // name 880 2, 1, 1, 1, 1, 2, // counts 881 scope_info); // parameter 882 } 883 884 const Operator* JSOperatorBuilder::CreateBlockContext( 885 const Handle<ScopeInfo>& scpope_info) { 886 return new (zone()) Operator1<Handle<ScopeInfo>>( // -- 887 IrOpcode::kJSCreateBlockContext, Operator::kNoProperties, // opcode 888 "JSCreateBlockContext", // name 889 1, 1, 1, 1, 1, 2, // counts 890 scpope_info); // parameter 891 } 892 893 894 const Operator* JSOperatorBuilder::CreateScriptContext( 895 const Handle<ScopeInfo>& scpope_info) { 896 return new (zone()) Operator1<Handle<ScopeInfo>>( // -- 897 IrOpcode::kJSCreateScriptContext, Operator::kNoProperties, // opcode 898 "JSCreateScriptContext", // name 899 1, 1, 1, 1, 1, 2, // counts 900 scpope_info); // parameter 901 } 902 903 } // namespace compiler 904 } // namespace internal 905 } // namespace v8 906