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/bytecode-graph-builder.h" 6 7#include "src/ast/ast.h" 8#include "src/base/platform/wrappers.h" 9#include "src/codegen/source-position-table.h" 10#include "src/codegen/tick-counter.h" 11#include "src/common/assert-scope.h" 12#include "src/compiler/access-builder.h" 13#include "src/compiler/bytecode-analysis.h" 14#include "src/compiler/common-operator.h" 15#include "src/compiler/compiler-source-position-table.h" 16#include "src/compiler/js-heap-broker.h" 17#include "src/compiler/linkage.h" 18#include "src/compiler/node-matchers.h" 19#include "src/compiler/node-observer.h" 20#include "src/compiler/operator-properties.h" 21#include "src/compiler/simplified-operator.h" 22#include "src/compiler/state-values-utils.h" 23#include "src/interpreter/bytecode-array-iterator.h" 24#include "src/interpreter/bytecode-flags.h" 25#include "src/interpreter/bytecodes.h" 26#include "src/objects/js-array-inl.h" 27#include "src/objects/js-generator.h" 28#include "src/objects/literal-objects-inl.h" 29#include "src/objects/objects-inl.h" 30#include "src/objects/smi.h" 31#include "src/objects/template-objects-inl.h" 32 33namespace v8 { 34namespace internal { 35namespace compiler { 36 37class BytecodeGraphBuilder { 38 public: 39 BytecodeGraphBuilder(JSHeapBroker* broker, Zone* local_zone, 40 NativeContextRef const& native_context, 41 SharedFunctionInfoRef const& shared_info, 42 FeedbackCellRef const& feedback_cell, 43 BytecodeOffset osr_offset, JSGraph* jsgraph, 44 CallFrequency const& invocation_frequency, 45 SourcePositionTable* source_positions, int inlining_id, 46 CodeKind code_kind, BytecodeGraphBuilderFlags flags, 47 TickCounter* tick_counter, 48 ObserveNodeInfo const& observe_node_info); 49 50 BytecodeGraphBuilder(const BytecodeGraphBuilder&) = delete; 51 BytecodeGraphBuilder& operator=(const BytecodeGraphBuilder&) = delete; 52 53 // Creates a graph by visiting bytecodes. 54 void CreateGraph(); 55 56 private: 57 class Environment; 58 class OsrIteratorState; 59 struct SubEnvironment; 60 61 void RemoveMergeEnvironmentsBeforeOffset(int limit_offset); 62 void AdvanceToOsrEntryAndPeelLoops(); 63 64 // Advance {bytecode_iterator} to the given offset. If possible, also advance 65 // {source_position_iterator} while updating the source position table. 66 void AdvanceIteratorsTo(int bytecode_offset); 67 68 void VisitSingleBytecode(); 69 void VisitBytecodes(); 70 71 // Get or create the node that represents the outer function closure. 72 Node* GetFunctionClosure(); 73 74 // Get or create the node for this parameter index. If such a node is 75 // already cached, it is returned directly and the {debug_name_hint} is 76 // ignored. 77 Node* GetParameter(int index, const char* debug_name_hint = nullptr); 78 79 CodeKind code_kind() const { return code_kind_; } 80 81 // The node representing the current feedback vector is generated once prior 82 // to visiting bytecodes, and is later passed as input to other nodes that 83 // may need it. 84 // TODO(jgruber): Remove feedback_vector() and rename feedback_vector_node() 85 // to feedback_vector() once all uses of the direct heap object reference 86 // have been replaced with a Node* reference. 87 void CreateFeedbackVectorNode(); 88 Node* feedback_vector_node() const { 89 DCHECK_NOT_NULL(feedback_vector_node_); 90 return feedback_vector_node_; 91 } 92 93 // Same as above for the feedback vector node. 94 void CreateNativeContextNode(); 95 Node* native_context_node() const { 96 DCHECK_NOT_NULL(native_context_node_); 97 return native_context_node_; 98 } 99 100 Node* BuildLoadFeedbackCell(int index); 101 102 // Builder for loading a native context field. 103 Node* BuildLoadNativeContextField(int index); 104 105 // Helper function for creating a feedback source containing type feedback 106 // vector and a feedback slot. 107 FeedbackSource CreateFeedbackSource(int slot_id); 108 FeedbackSource CreateFeedbackSource(FeedbackSlot slot); 109 110 void set_environment(Environment* env) { environment_ = env; } 111 const Environment* environment() const { return environment_; } 112 Environment* environment() { return environment_; } 113 114 // Node creation helpers 115 Node* NewNode(const Operator* op, bool incomplete = false) { 116 return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete); 117 } 118 119 template <class... Args> 120 Node* NewNode(const Operator* op, Node* n0, Args... nodes) { 121 Node* buffer[] = {n0, nodes...}; 122 return MakeNode(op, arraysize(buffer), buffer); 123 } 124 125 // Helpers to create new control nodes. 126 Node* NewIfTrue() { return NewNode(common()->IfTrue()); } 127 Node* NewIfFalse() { return NewNode(common()->IfFalse()); } 128 Node* NewIfValue(int32_t value) { return NewNode(common()->IfValue(value)); } 129 Node* NewIfDefault() { return NewNode(common()->IfDefault()); } 130 Node* NewMerge() { return NewNode(common()->Merge(1), true); } 131 Node* NewLoop() { return NewNode(common()->Loop(1), true); } 132 Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) { 133 return NewNode(common()->Branch(hint), condition); 134 } 135 Node* NewSwitch(Node* condition, int control_output_count) { 136 return NewNode(common()->Switch(control_output_count), condition); 137 } 138 139 // Creates a new Phi node having {count} input values. 140 Node* NewPhi(int count, Node* input, Node* control); 141 Node* NewEffectPhi(int count, Node* input, Node* control); 142 143 // Helpers for merging control, effect or value dependencies. 144 Node* MergeControl(Node* control, Node* other); 145 Node* MergeEffect(Node* effect, Node* other_effect, Node* control); 146 Node* MergeValue(Node* value, Node* other_value, Node* control); 147 148 // The main node creation chokepoint. Adds context, frame state, effect, 149 // and control dependencies depending on the operator. 150 Node* MakeNode(const Operator* op, int value_input_count, 151 Node* const* value_inputs, bool incomplete = false); 152 153 Node** EnsureInputBufferSize(int size); 154 155 Node* const* GetCallArgumentsFromRegisters(Node* callee, Node* receiver, 156 interpreter::Register first_arg, 157 int arg_count); 158 Node* const* ProcessCallVarArgs(ConvertReceiverMode receiver_mode, 159 Node* callee, interpreter::Register first_reg, 160 int arg_count); 161 Node* const* GetConstructArgumentsFromRegister( 162 Node* target, Node* new_target, interpreter::Register first_arg, 163 int arg_count); 164 Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op, 165 interpreter::Register receiver, 166 size_t reg_count); 167 168 // Prepare information for eager deoptimization. This information is carried 169 // by dedicated {Checkpoint} nodes that are wired into the effect chain. 170 // Conceptually this frame state is "before" a given operation. 171 void PrepareEagerCheckpoint(); 172 173 // Prepare information for lazy deoptimization. This information is attached 174 // to the given node and the output value produced by the node is combined. 175 // 176 // The low-level chokepoint - use the variants below instead. 177 void PrepareFrameState(Node* node, OutputFrameStateCombine combine, 178 BytecodeOffset bailout_id, 179 const BytecodeLivenessState* liveness); 180 181 // In the common case, frame states are conceptually "after" a given 182 // operation and at the current bytecode offset. 183 void PrepareFrameState(Node* node, OutputFrameStateCombine combine) { 184 if (!OperatorProperties::HasFrameStateInput(node->op())) return; 185 const int offset = bytecode_iterator().current_offset(); 186 return PrepareFrameState(node, combine, BytecodeOffset(offset), 187 bytecode_analysis().GetOutLivenessFor(offset)); 188 } 189 190 // For function-entry stack checks, they're conceptually "before" the first 191 // bytecode and at a special marker bytecode offset. 192 // In the case of FE stack checks, the current bytecode is also the first 193 // bytecode, so we use a special marker bytecode offset to signify a virtual 194 // bytecode before the first physical bytecode. 195 void PrepareFrameStateForFunctionEntryStackCheck(Node* node) { 196 DCHECK_EQ(bytecode_iterator().current_offset(), 0); 197 DCHECK(OperatorProperties::HasFrameStateInput(node->op())); 198 DCHECK(node->opcode() == IrOpcode::kJSStackCheck); 199 return PrepareFrameState(node, OutputFrameStateCombine::Ignore(), 200 BytecodeOffset(kFunctionEntryBytecodeOffset), 201 bytecode_analysis().GetInLivenessFor(0)); 202 } 203 204 // For OSR-entry stack checks, they're conceptually "before" the first 205 // bytecode of the current loop. We implement this in a similar manner to 206 // function-entry (FE) stack checks above, i.e. we deopt at the predecessor 207 // of the current bytecode. 208 // In the case of OSR-entry stack checks, a physical predecessor bytecode 209 // exists: the JumpLoop bytecode. We attach to JumpLoop by using 210 // `bytecode_analysis().osr_bailout_id()` instead of current_offset (the 211 // former points at JumpLoop, the latter at the loop header, i.e. the target 212 // of JumpLoop). 213 void PrepareFrameStateForOSREntryStackCheck(Node* node) { 214 DCHECK(OperatorProperties::HasFrameStateInput(node->op())); 215 DCHECK(node->opcode() == IrOpcode::kJSStackCheck); 216 const int offset = bytecode_analysis().osr_bailout_id().ToInt(); 217 return PrepareFrameState(node, OutputFrameStateCombine::Ignore(), 218 BytecodeOffset(offset), 219 bytecode_analysis().GetOutLivenessFor(offset)); 220 } 221 222 void BuildCreateArguments(CreateArgumentsType type); 223 Node* BuildLoadGlobal(NameRef name, uint32_t feedback_slot_index, 224 TypeofMode typeof_mode); 225 226 enum class NamedStoreMode { 227 // Check the prototype chain before storing. 228 kSet, 229 // Define value to the receiver without checking the prototype chain. 230 kDefineOwn, 231 }; 232 void BuildNamedStore(NamedStoreMode store_mode); 233 void BuildLdaLookupSlot(TypeofMode typeof_mode); 234 void BuildLdaLookupContextSlot(TypeofMode typeof_mode); 235 void BuildLdaLookupGlobalSlot(TypeofMode typeof_mode); 236 void BuildCallVarArgs(ConvertReceiverMode receiver_mode); 237 void BuildCall(ConvertReceiverMode receiver_mode, Node* const* args, 238 size_t arg_count, int slot_id); 239 void BuildCall(ConvertReceiverMode receiver_mode, 240 std::initializer_list<Node*> args, int slot_id) { 241 BuildCall(receiver_mode, args.begin(), args.size(), slot_id); 242 } 243 void BuildUnaryOp(const Operator* op); 244 void BuildBinaryOp(const Operator* op); 245 void BuildBinaryOpWithImmediate(const Operator* op); 246 void BuildCompareOp(const Operator* op); 247 void BuildDelete(LanguageMode language_mode); 248 void BuildCastOperator(const Operator* op); 249 void BuildHoleCheckAndThrow(Node* condition, Runtime::FunctionId runtime_id, 250 Node* name = nullptr); 251 252 // Optional early lowering to the simplified operator level. Note that 253 // the result has already been wired into the environment just like 254 // any other invocation of {NewNode} would do. 255 JSTypeHintLowering::LoweringResult TryBuildSimplifiedUnaryOp( 256 const Operator* op, Node* operand, FeedbackSlot slot); 257 JSTypeHintLowering::LoweringResult TryBuildSimplifiedBinaryOp( 258 const Operator* op, Node* left, Node* right, FeedbackSlot slot); 259 JSTypeHintLowering::LoweringResult TryBuildSimplifiedForInNext( 260 Node* receiver, Node* cache_array, Node* cache_type, Node* index, 261 FeedbackSlot slot); 262 JSTypeHintLowering::LoweringResult TryBuildSimplifiedForInPrepare( 263 Node* receiver, FeedbackSlot slot); 264 JSTypeHintLowering::LoweringResult TryBuildSimplifiedToNumber( 265 Node* input, FeedbackSlot slot); 266 JSTypeHintLowering::LoweringResult TryBuildSimplifiedCall(const Operator* op, 267 Node* const* args, 268 int arg_count, 269 FeedbackSlot slot); 270 JSTypeHintLowering::LoweringResult TryBuildSimplifiedConstruct( 271 const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot); 272 JSTypeHintLowering::LoweringResult TryBuildSimplifiedGetIterator( 273 const Operator* op, Node* receiver, FeedbackSlot load_slot, 274 FeedbackSlot call_slot); 275 JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadNamed( 276 const Operator* op, FeedbackSlot slot); 277 JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadKeyed( 278 const Operator* op, Node* receiver, Node* key, FeedbackSlot slot); 279 JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreNamed( 280 const Operator* op, Node* receiver, Node* value, FeedbackSlot slot); 281 JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreKeyed( 282 const Operator* op, Node* receiver, Node* key, Node* value, 283 FeedbackSlot slot); 284 285 // Applies the given early reduction onto the current environment. 286 void ApplyEarlyReduction(JSTypeHintLowering::LoweringResult reduction); 287 288 // Check the context chain for extensions, for lookup fast paths. 289 Environment* CheckContextExtensions(uint32_t depth); 290 // Slow path taken when we cannot figure out the current scope info. 291 Environment* CheckContextExtensionsSlowPath(uint32_t depth); 292 // Helper function that tries to get the current scope info. 293 base::Optional<ScopeInfoRef> TryGetScopeInfo(); 294 // Helper function to create a context extension check. 295 Environment* CheckContextExtensionAtDepth(Environment* slow_environment, 296 uint32_t depth); 297 298 // Helper function to create for-in mode from the recorded type feedback. 299 ForInMode GetForInMode(FeedbackSlot slot); 300 301 // Helper function to compute call frequency from the recorded type 302 // feedback. Returns unknown if invocation count is unknown. Returns 0 if 303 // feedback is insufficient. 304 CallFrequency ComputeCallFrequency(int slot_id) const; 305 306 // Helper function to extract the speculation mode from the recorded type 307 // feedback. Returns kDisallowSpeculation if feedback is insufficient. 308 SpeculationMode GetSpeculationMode(int slot_id) const; 309 310 // Helper function to determine the call feedback relation from the recorded 311 // type feedback. Returns kUnrelated if feedback is insufficient. 312 CallFeedbackRelation ComputeCallFeedbackRelation(int slot_id) const; 313 314 // Helpers for building the implicit FunctionEntry and IterationBody 315 // StackChecks. 316 void BuildFunctionEntryStackCheck(); 317 void BuildIterationBodyStackCheck(); 318 void BuildOSREntryStackCheck(); 319 320 // Control flow plumbing. 321 void BuildJump(); 322 void BuildJumpIf(Node* condition); 323 void BuildJumpIfNot(Node* condition); 324 void BuildJumpIfEqual(Node* comperand); 325 void BuildJumpIfNotEqual(Node* comperand); 326 void BuildJumpIfTrue(); 327 void BuildJumpIfFalse(); 328 void BuildJumpIfToBooleanTrue(); 329 void BuildJumpIfToBooleanFalse(); 330 void BuildJumpIfNotHole(); 331 void BuildJumpIfJSReceiver(); 332 333 void BuildSwitchOnSmi(Node* condition); 334 void BuildSwitchOnGeneratorState( 335 const ZoneVector<ResumeJumpTarget>& resume_jump_targets, 336 bool allow_fallthrough_on_executing); 337 338 // Simulates control flow by forward-propagating environments. 339 void MergeIntoSuccessorEnvironment(int target_offset); 340 void BuildLoopHeaderEnvironment(int current_offset); 341 void SwitchToMergeEnvironment(int current_offset); 342 343 // Simulates control flow that exits the function body. 344 void MergeControlToLeaveFunction(Node* exit); 345 346 // Builds loop exit nodes for every exited loop between the current bytecode 347 // offset and {target_offset}. 348 void BuildLoopExitsForBranch(int target_offset); 349 void BuildLoopExitsForFunctionExit(const BytecodeLivenessState* liveness); 350 void BuildLoopExitsUntilLoop(int loop_offset, 351 const BytecodeLivenessState* liveness); 352 353 // Helper for building a return (from an actual return or a suspend). 354 void BuildReturn(const BytecodeLivenessState* liveness); 355 356 // Simulates entry and exit of exception handlers. 357 void ExitThenEnterExceptionHandlers(int current_offset); 358 359 // Update the current position of the {SourcePositionTable} to that of the 360 // bytecode at {offset}, if any. 361 void UpdateSourcePosition(int offset); 362 363 // Growth increment for the temporary buffer used to construct input lists to 364 // new nodes. 365 static const int kInputBufferSizeIncrement = 64; 366 367 // An abstract representation for an exception handler that is being 368 // entered and exited while the graph builder is iterating over the 369 // underlying bytecode. The exception handlers within the bytecode are 370 // well scoped, hence will form a stack during iteration. 371 struct ExceptionHandler { 372 int start_offset_; // Start offset of the handled area in the bytecode. 373 int end_offset_; // End offset of the handled area in the bytecode. 374 int handler_offset_; // Handler entry offset within the bytecode. 375 int context_register_; // Index of register holding handler context. 376 }; 377 378 template <class T = Object> 379 typename ref_traits<T>::ref_type MakeRefForConstantForIndexOperand( 380 int operand_index) { 381 // The BytecodeArray itself was fetched by using a barrier so all reads 382 // from the constant pool are safe. 383 return MakeRefAssumeMemoryFence( 384 broker(), broker()->CanonicalPersistentHandle(Handle<T>::cast( 385 bytecode_iterator().GetConstantForIndexOperand( 386 operand_index, local_isolate_)))); 387 } 388 389 Graph* graph() const { return jsgraph_->graph(); } 390 CommonOperatorBuilder* common() const { return jsgraph_->common(); } 391 Zone* graph_zone() const { return graph()->zone(); } 392 JSGraph* jsgraph() const { return jsgraph_; } 393 Isolate* isolate() const { return jsgraph_->isolate(); } 394 JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); } 395 SimplifiedOperatorBuilder* simplified() const { 396 return jsgraph_->simplified(); 397 } 398 Zone* local_zone() const { return local_zone_; } 399 BytecodeArrayRef bytecode_array() const { return bytecode_array_; } 400 FeedbackVectorRef const& feedback_vector() const { return feedback_vector_; } 401 const JSTypeHintLowering& type_hint_lowering() const { 402 return type_hint_lowering_; 403 } 404 const FrameStateFunctionInfo* frame_state_function_info() const { 405 return frame_state_function_info_; 406 } 407 SourcePositionTableIterator& source_position_iterator() { 408 return *source_position_iterator_.get(); 409 } 410 interpreter::BytecodeArrayIterator const& bytecode_iterator() const { 411 return bytecode_iterator_; 412 } 413 interpreter::BytecodeArrayIterator& bytecode_iterator() { 414 return bytecode_iterator_; 415 } 416 BytecodeAnalysis const& bytecode_analysis() const { 417 return bytecode_analysis_; 418 } 419 int currently_peeled_loop_offset() const { 420 return currently_peeled_loop_offset_; 421 } 422 void set_currently_peeled_loop_offset(int offset) { 423 currently_peeled_loop_offset_ = offset; 424 } 425 bool skip_first_stack_check() const { 426 return skip_first_stack_and_tierup_check_; 427 } 428 bool skip_tierup_check() const { 429 return skip_first_stack_and_tierup_check_ || osr_; 430 } 431 int current_exception_handler() const { return current_exception_handler_; } 432 void set_current_exception_handler(int index) { 433 current_exception_handler_ = index; 434 } 435 bool needs_eager_checkpoint() const { return needs_eager_checkpoint_; } 436 void mark_as_needing_eager_checkpoint(bool value) { 437 needs_eager_checkpoint_ = value; 438 } 439 JSHeapBroker* broker() const { return broker_; } 440 NativeContextRef native_context() const { return native_context_; } 441 SharedFunctionInfoRef shared_info() const { return shared_info_; } 442 443#define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name(); 444 BYTECODE_LIST(DECLARE_VISIT_BYTECODE) 445#undef DECLARE_VISIT_BYTECODE 446 447 JSHeapBroker* const broker_; 448 LocalIsolate* const local_isolate_; 449 Zone* const local_zone_; 450 JSGraph* const jsgraph_; 451 // The native context for which we optimize. 452 NativeContextRef const native_context_; 453 SharedFunctionInfoRef const shared_info_; 454 BytecodeArrayRef const bytecode_array_; 455 FeedbackCellRef const feedback_cell_; 456 FeedbackVectorRef const feedback_vector_; 457 CallFrequency const invocation_frequency_; 458 JSTypeHintLowering const type_hint_lowering_; 459 const FrameStateFunctionInfo* const frame_state_function_info_; 460 std::unique_ptr<SourcePositionTableIterator> source_position_iterator_; 461 interpreter::BytecodeArrayIterator bytecode_iterator_; 462 BytecodeAnalysis const bytecode_analysis_; 463 Environment* environment_; 464 bool const osr_; 465 int currently_peeled_loop_offset_; 466 467 const bool skip_first_stack_and_tierup_check_; 468 469 // Merge environments are snapshots of the environment at points where the 470 // control flow merges. This models a forward data flow propagation of all 471 // values from all predecessors of the merge in question. They are indexed by 472 // the bytecode offset 473 ZoneMap<int, Environment*> merge_environments_; 474 475 // Generator merge environments are snapshots of the current resume 476 // environment, tracing back through loop headers to the resume switch of a 477 // generator. They allow us to model a single resume jump as several switch 478 // statements across loop headers, keeping those loop headers reducible, 479 // without having to merge the "executing" environments of the generator into 480 // the "resuming" ones. They are indexed by the suspend id of the resume. 481 ZoneMap<int, Environment*> generator_merge_environments_; 482 483 ZoneVector<Node*> cached_parameters_; 484 485 // Exception handlers currently entered by the iteration. 486 ZoneStack<ExceptionHandler> exception_handlers_; 487 int current_exception_handler_; 488 489 // Temporary storage for building node input lists. 490 int input_buffer_size_; 491 Node** input_buffer_; 492 493 const CodeKind code_kind_; 494 Node* feedback_vector_node_; 495 Node* native_context_node_; 496 497 // Optimization to only create checkpoints when the current position in the 498 // control-flow is not effect-dominated by another checkpoint already. All 499 // operations that do not have observable side-effects can be re-evaluated. 500 bool needs_eager_checkpoint_; 501 502 // Nodes representing values in the activation record. 503 SetOncePointer<Node> function_closure_; 504 505 // Control nodes that exit the function body. 506 ZoneVector<Node*> exit_controls_; 507 508 StateValuesCache state_values_cache_; 509 510 // The source position table, to be populated. 511 SourcePositionTable* const source_positions_; 512 513 SourcePosition const start_position_; 514 515 TickCounter* const tick_counter_; 516 517 ObserveNodeInfo const observe_node_info_; 518 519 static constexpr int kBinaryOperationHintIndex = 1; 520 static constexpr int kBinaryOperationSmiHintIndex = 1; 521 static constexpr int kCompareOperationHintIndex = 1; 522 static constexpr int kCountOperationHintIndex = 0; 523 static constexpr int kUnaryOperationHintIndex = 0; 524}; 525 526// The abstract execution environment simulates the content of the interpreter 527// register file. The environment performs SSA-renaming of all tracked nodes at 528// split and merge points in the control flow. 529class BytecodeGraphBuilder::Environment : public ZoneObject { 530 public: 531 Environment(BytecodeGraphBuilder* builder, int register_count, 532 int parameter_count, 533 interpreter::Register incoming_new_target_or_generator, 534 Node* control_dependency); 535 536 // Specifies whether environment binding methods should attach frame state 537 // inputs to nodes representing the value being bound. This is done because 538 // the {OutputFrameStateCombine} is closely related to the binding method. 539 enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState }; 540 541 int parameter_count() const { return parameter_count_; } 542 int register_count() const { return register_count_; } 543 544 Node* LookupAccumulator() const; 545 Node* LookupRegister(interpreter::Register the_register) const; 546 Node* LookupGeneratorState() const; 547 548 void BindAccumulator(Node* node, 549 FrameStateAttachmentMode mode = kDontAttachFrameState); 550 void BindRegister(interpreter::Register the_register, Node* node, 551 FrameStateAttachmentMode mode = kDontAttachFrameState); 552 void BindRegistersToProjections( 553 interpreter::Register first_reg, Node* node, 554 FrameStateAttachmentMode mode = kDontAttachFrameState); 555 void BindGeneratorState(Node* node); 556 void RecordAfterState(Node* node, 557 FrameStateAttachmentMode mode = kDontAttachFrameState); 558 559 // Effect dependency tracked by this environment. 560 Node* GetEffectDependency() { return effect_dependency_; } 561 void UpdateEffectDependency(Node* dependency) { 562 effect_dependency_ = dependency; 563 } 564 565 // Preserve a checkpoint of the environment for the IR graph. Any 566 // further mutation of the environment will not affect checkpoints. 567 Node* Checkpoint(BytecodeOffset bytecode_offset, 568 OutputFrameStateCombine combine, 569 const BytecodeLivenessState* liveness); 570 571 // Control dependency tracked by this environment. 572 Node* GetControlDependency() const { return control_dependency_; } 573 void UpdateControlDependency(Node* dependency) { 574 control_dependency_ = dependency; 575 } 576 577 Node* Context() const { return context_; } 578 void SetContext(Node* new_context) { context_ = new_context; } 579 580 Environment* Copy(); 581 void Merge(Environment* other, const BytecodeLivenessState* liveness); 582 583 void FillWithOsrValues(); 584 void PrepareForLoop(const BytecodeLoopAssignments& assignments, 585 const BytecodeLivenessState* liveness); 586 void PrepareForLoopExit(Node* loop, 587 const BytecodeLoopAssignments& assignments, 588 const BytecodeLivenessState* liveness); 589 590 private: 591 friend Zone; 592 593 explicit Environment(const Environment* copy); 594 595 bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); 596 void UpdateStateValues(Node** state_values, Node** values, int count); 597 Node* GetStateValuesFromCache(Node** values, int count, 598 const BytecodeLivenessState* liveness); 599 600 int RegisterToValuesIndex(interpreter::Register the_register) const; 601 602 Zone* zone() const { return builder_->local_zone(); } 603 Graph* graph() const { return builder_->graph(); } 604 CommonOperatorBuilder* common() const { return builder_->common(); } 605 BytecodeGraphBuilder* builder() const { return builder_; } 606 const NodeVector* values() const { return &values_; } 607 NodeVector* values() { return &values_; } 608 int register_base() const { return register_base_; } 609 int accumulator_base() const { return accumulator_base_; } 610 611 BytecodeGraphBuilder* builder_; 612 int register_count_; 613 int parameter_count_; 614 Node* context_; 615 Node* control_dependency_; 616 Node* effect_dependency_; 617 NodeVector values_; 618 Node* parameters_state_values_; 619 Node* generator_state_; 620 int register_base_; 621 int accumulator_base_; 622}; 623 624// A helper for creating a temporary sub-environment for simple branches. 625struct BytecodeGraphBuilder::SubEnvironment final { 626 public: 627 explicit SubEnvironment(BytecodeGraphBuilder* builder) 628 : builder_(builder), parent_(builder->environment()->Copy()) {} 629 630 ~SubEnvironment() { builder_->set_environment(parent_); } 631 632 private: 633 BytecodeGraphBuilder* builder_; 634 BytecodeGraphBuilder::Environment* parent_; 635}; 636 637// Issues: 638// - Scopes - intimately tied to AST. Need to eval what is needed. 639// - Need to resolve closure parameter treatment. 640BytecodeGraphBuilder::Environment::Environment( 641 BytecodeGraphBuilder* builder, int register_count, int parameter_count, 642 interpreter::Register incoming_new_target_or_generator, 643 Node* control_dependency) 644 : builder_(builder), 645 register_count_(register_count), 646 parameter_count_(parameter_count), 647 control_dependency_(control_dependency), 648 effect_dependency_(control_dependency), 649 values_(builder->local_zone()), 650 parameters_state_values_(nullptr), 651 generator_state_(nullptr) { 652 // The layout of values_ is: 653 // 654 // [receiver] [parameters] [registers] [accumulator] 655 // 656 // parameter[0] is the receiver (this), parameters 1..N are the 657 // parameters supplied to the method (arg0..argN-1). The accumulator 658 // is stored separately. 659 660 // Parameters including the receiver 661 for (int i = 0; i < parameter_count; i++) { 662 const char* debug_name = (i == 0) ? "%this" : nullptr; 663 Node* parameter = builder->GetParameter(i, debug_name); 664 values()->push_back(parameter); 665 } 666 667 // Registers 668 register_base_ = static_cast<int>(values()->size()); 669 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 670 values()->insert(values()->end(), register_count, undefined_constant); 671 672 // Accumulator 673 accumulator_base_ = static_cast<int>(values()->size()); 674 values()->push_back(undefined_constant); 675 676 // Context 677 int context_index = Linkage::GetJSCallContextParamIndex(parameter_count); 678 context_ = builder->GetParameter(context_index, "%context"); 679 680 // Incoming new.target or generator register 681 if (incoming_new_target_or_generator.is_valid()) { 682 int new_target_index = 683 Linkage::GetJSCallNewTargetParamIndex(parameter_count); 684 Node* new_target_node = 685 builder->GetParameter(new_target_index, "%new.target"); 686 687 int values_index = RegisterToValuesIndex(incoming_new_target_or_generator); 688 values()->at(values_index) = new_target_node; 689 } 690} 691 692BytecodeGraphBuilder::Environment::Environment( 693 const BytecodeGraphBuilder::Environment* other) 694 : builder_(other->builder_), 695 register_count_(other->register_count_), 696 parameter_count_(other->parameter_count_), 697 context_(other->context_), 698 control_dependency_(other->control_dependency_), 699 effect_dependency_(other->effect_dependency_), 700 values_(other->zone()), 701 parameters_state_values_(other->parameters_state_values_), 702 generator_state_(other->generator_state_), 703 register_base_(other->register_base_), 704 accumulator_base_(other->accumulator_base_) { 705 values_ = other->values_; 706} 707 708 709int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( 710 interpreter::Register the_register) const { 711 if (the_register.is_parameter()) { 712 return the_register.ToParameterIndex(); 713 } else { 714 return the_register.index() + register_base(); 715 } 716} 717 718Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { 719 return values()->at(accumulator_base_); 720} 721 722Node* BytecodeGraphBuilder::Environment::LookupGeneratorState() const { 723 DCHECK_NOT_NULL(generator_state_); 724 return generator_state_; 725} 726 727Node* BytecodeGraphBuilder::Environment::LookupRegister( 728 interpreter::Register the_register) const { 729 if (the_register.is_current_context()) { 730 return Context(); 731 } else if (the_register.is_function_closure()) { 732 return builder()->GetFunctionClosure(); 733 } else { 734 int values_index = RegisterToValuesIndex(the_register); 735 return values()->at(values_index); 736 } 737} 738 739void BytecodeGraphBuilder::Environment::BindAccumulator( 740 Node* node, FrameStateAttachmentMode mode) { 741 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 742 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0)); 743 } 744 values()->at(accumulator_base_) = node; 745} 746 747void BytecodeGraphBuilder::Environment::BindGeneratorState(Node* node) { 748 generator_state_ = node; 749} 750 751void BytecodeGraphBuilder::Environment::BindRegister( 752 interpreter::Register the_register, Node* node, 753 FrameStateAttachmentMode mode) { 754 int values_index = RegisterToValuesIndex(the_register); 755 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 756 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 757 accumulator_base_ - values_index)); 758 } 759 values()->at(values_index) = node; 760} 761 762void BytecodeGraphBuilder::Environment::BindRegistersToProjections( 763 interpreter::Register first_reg, Node* node, 764 FrameStateAttachmentMode mode) { 765 int values_index = RegisterToValuesIndex(first_reg); 766 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 767 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 768 accumulator_base_ - values_index)); 769 } 770 for (int i = 0; i < node->op()->ValueOutputCount(); i++) { 771 values()->at(values_index + i) = 772 builder()->NewNode(common()->Projection(i), node); 773 } 774} 775 776void BytecodeGraphBuilder::Environment::RecordAfterState( 777 Node* node, FrameStateAttachmentMode mode) { 778 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 779 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); 780 } 781} 782 783BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() { 784 return zone()->New<Environment>(this); 785} 786 787void BytecodeGraphBuilder::Environment::Merge( 788 BytecodeGraphBuilder::Environment* other, 789 const BytecodeLivenessState* liveness) { 790 // Create a merge of the control dependencies of both environments and update 791 // the current environment's control dependency accordingly. 792 Node* control = builder()->MergeControl(GetControlDependency(), 793 other->GetControlDependency()); 794 UpdateControlDependency(control); 795 796 // Create a merge of the effect dependencies of both environments and update 797 // the current environment's effect dependency accordingly. 798 Node* effect = builder()->MergeEffect(GetEffectDependency(), 799 other->GetEffectDependency(), control); 800 UpdateEffectDependency(effect); 801 802 // Introduce Phi nodes for values that are live and have differing inputs at 803 // the merge point, potentially extending an existing Phi node if possible. 804 context_ = builder()->MergeValue(context_, other->context_, control); 805 for (int i = 0; i < parameter_count(); i++) { 806 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); 807 } 808 for (int i = 0; i < register_count(); i++) { 809 int index = register_base() + i; 810 if (liveness == nullptr || liveness->RegisterIsLive(i)) { 811#if DEBUG 812 // We only do these DCHECKs when we are not in the resume path of a 813 // generator -- this is, when either there is no generator state at all, 814 // or the generator state is not the constant "executing" value. 815 if (generator_state_ == nullptr || 816 NumberMatcher(generator_state_) 817 .Is(JSGeneratorObject::kGeneratorExecuting)) { 818 DCHECK_NE(values_[index], builder()->jsgraph()->OptimizedOutConstant()); 819 DCHECK_NE(other->values_[index], 820 builder()->jsgraph()->OptimizedOutConstant()); 821 } 822#endif 823 824 values_[index] = 825 builder()->MergeValue(values_[index], other->values_[index], control); 826 827 } else { 828 values_[index] = builder()->jsgraph()->OptimizedOutConstant(); 829 } 830 } 831 832 if (liveness == nullptr || liveness->AccumulatorIsLive()) { 833 DCHECK_NE(values_[accumulator_base()], 834 builder()->jsgraph()->OptimizedOutConstant()); 835 DCHECK_NE(other->values_[accumulator_base()], 836 builder()->jsgraph()->OptimizedOutConstant()); 837 838 values_[accumulator_base()] = 839 builder()->MergeValue(values_[accumulator_base()], 840 other->values_[accumulator_base()], control); 841 } else { 842 values_[accumulator_base()] = builder()->jsgraph()->OptimizedOutConstant(); 843 } 844 845 if (generator_state_ != nullptr) { 846 DCHECK_NOT_NULL(other->generator_state_); 847 generator_state_ = builder()->MergeValue(generator_state_, 848 other->generator_state_, control); 849 } 850} 851 852void BytecodeGraphBuilder::Environment::PrepareForLoop( 853 const BytecodeLoopAssignments& assignments, 854 const BytecodeLivenessState* liveness) { 855 // Create a control node for the loop header. 856 Node* control = builder()->NewLoop(); 857 858 // Create a Phi for external effects. 859 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); 860 UpdateEffectDependency(effect); 861 862 // Create Phis for any values that are live on entry to the loop and may be 863 // updated by the end of the loop. 864 context_ = builder()->NewPhi(1, context_, control); 865 for (int i = 0; i < parameter_count(); i++) { 866 if (assignments.ContainsParameter(i)) { 867 values_[i] = builder()->NewPhi(1, values_[i], control); 868 } 869 } 870 for (int i = 0; i < register_count(); i++) { 871 if (assignments.ContainsLocal(i) && 872 (liveness == nullptr || liveness->RegisterIsLive(i))) { 873 int index = register_base() + i; 874 values_[index] = builder()->NewPhi(1, values_[index], control); 875 } 876 } 877 // The accumulator should not be live on entry. 878 DCHECK_IMPLIES(liveness != nullptr, !liveness->AccumulatorIsLive()); 879 880 if (generator_state_ != nullptr) { 881 generator_state_ = builder()->NewPhi(1, generator_state_, control); 882 } 883 884 // Connect to the loop end. 885 Node* terminate = builder()->graph()->NewNode( 886 builder()->common()->Terminate(), effect, control); 887 builder()->exit_controls_.push_back(terminate); 888} 889 890void BytecodeGraphBuilder::Environment::FillWithOsrValues() { 891 Node* start = graph()->start(); 892 893 // Create OSR values for each environment value. 894 SetContext(graph()->NewNode( 895 common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), start)); 896 int size = static_cast<int>(values()->size()); 897 for (int i = 0; i < size; i++) { 898 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. 899 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; 900 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; 901 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), start); 902 } 903} 904 905bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( 906 Node** state_values, Node** values, int count) { 907 if (*state_values == nullptr) { 908 return true; 909 } 910 Node::Inputs inputs = (*state_values)->inputs(); 911 if (inputs.count() != count) return true; 912 for (int i = 0; i < count; i++) { 913 if (inputs[i] != values[i]) { 914 return true; 915 } 916 } 917 return false; 918} 919 920void BytecodeGraphBuilder::Environment::PrepareForLoopExit( 921 Node* loop, const BytecodeLoopAssignments& assignments, 922 const BytecodeLivenessState* liveness) { 923 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); 924 925 Node* control = GetControlDependency(); 926 927 // Create the loop exit node. 928 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); 929 UpdateControlDependency(loop_exit); 930 931 // Rename the effect. 932 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), 933 GetEffectDependency(), loop_exit); 934 UpdateEffectDependency(effect_rename); 935 936 // TODO(jarin) We should also rename context here. However, unconditional 937 // renaming confuses global object and native context specialization. 938 // We should only rename if the context is assigned in the loop. 939 940 // Rename the environment values if they were assigned in the loop and are 941 // live after exiting the loop. 942 for (int i = 0; i < parameter_count(); i++) { 943 if (assignments.ContainsParameter(i)) { 944 Node* rename = graph()->NewNode( 945 common()->LoopExitValue(MachineRepresentation::kTagged), values_[i], 946 loop_exit); 947 values_[i] = rename; 948 } 949 } 950 for (int i = 0; i < register_count(); i++) { 951 if (assignments.ContainsLocal(i) && 952 (liveness == nullptr || liveness->RegisterIsLive(i))) { 953 Node* rename = graph()->NewNode( 954 common()->LoopExitValue(MachineRepresentation::kTagged), 955 values_[register_base() + i], loop_exit); 956 values_[register_base() + i] = rename; 957 } 958 } 959 if (liveness == nullptr || liveness->AccumulatorIsLive()) { 960 Node* rename = graph()->NewNode( 961 common()->LoopExitValue(MachineRepresentation::kTagged), 962 values_[accumulator_base()], loop_exit); 963 values_[accumulator_base()] = rename; 964 } 965 966 if (generator_state_ != nullptr) { 967 generator_state_ = graph()->NewNode( 968 common()->LoopExitValue(MachineRepresentation::kTagged), 969 generator_state_, loop_exit); 970 } 971} 972 973void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 974 Node** values, 975 int count) { 976 if (StateValuesRequireUpdate(state_values, values, count)) { 977 const Operator* op = common()->StateValues(count, SparseInputMask::Dense()); 978 (*state_values) = graph()->NewNode(op, count, values); 979 } 980} 981 982Node* BytecodeGraphBuilder::Environment::GetStateValuesFromCache( 983 Node** values, int count, const BytecodeLivenessState* liveness) { 984 return builder_->state_values_cache_.GetNodeForValues( 985 values, static_cast<size_t>(count), liveness); 986} 987 988Node* BytecodeGraphBuilder::Environment::Checkpoint( 989 BytecodeOffset bailout_id, OutputFrameStateCombine combine, 990 const BytecodeLivenessState* liveness) { 991 if (parameter_count() == register_count()) { 992 // Re-use the state-value cache if the number of local registers happens 993 // to match the parameter count. 994 parameters_state_values_ = 995 GetStateValuesFromCache(&values()->at(0), parameter_count(), nullptr); 996 } else { 997 UpdateStateValues(¶meters_state_values_, &values()->at(0), 998 parameter_count()); 999 } 1000 1001 Node* registers_state_values = GetStateValuesFromCache( 1002 &values()->at(register_base()), register_count(), liveness); 1003 1004 bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive(); 1005 Node* accumulator_state_value = 1006 accumulator_is_live && combine != OutputFrameStateCombine::PokeAt(0) 1007 ? values()->at(accumulator_base()) 1008 : builder()->jsgraph()->OptimizedOutConstant(); 1009 1010 const Operator* op = common()->FrameState( 1011 bailout_id, combine, builder()->frame_state_function_info()); 1012 Node* result = graph()->NewNode( 1013 op, parameters_state_values_, registers_state_values, 1014 accumulator_state_value, Context(), builder()->GetFunctionClosure(), 1015 builder()->graph()->start()); 1016 1017 return result; 1018} 1019 1020BytecodeGraphBuilder::BytecodeGraphBuilder( 1021 JSHeapBroker* broker, Zone* local_zone, 1022 NativeContextRef const& native_context, 1023 SharedFunctionInfoRef const& shared_info, 1024 FeedbackCellRef const& feedback_cell, BytecodeOffset osr_offset, 1025 JSGraph* jsgraph, CallFrequency const& invocation_frequency, 1026 SourcePositionTable* source_positions, int inlining_id, CodeKind code_kind, 1027 BytecodeGraphBuilderFlags flags, TickCounter* tick_counter, 1028 ObserveNodeInfo const& observe_node_info) 1029 : broker_(broker), 1030 local_isolate_(broker_->local_isolate() 1031 ? broker_->local_isolate() 1032 : broker_->isolate()->AsLocalIsolate()), 1033 local_zone_(local_zone), 1034 jsgraph_(jsgraph), 1035 native_context_(native_context), 1036 shared_info_(shared_info), 1037 bytecode_array_(shared_info.GetBytecodeArray()), 1038 feedback_cell_(feedback_cell), 1039 feedback_vector_(feedback_cell.feedback_vector().value()), 1040 invocation_frequency_(invocation_frequency), 1041 type_hint_lowering_( 1042 broker, jsgraph, feedback_vector_, 1043 (flags & BytecodeGraphBuilderFlag::kBailoutOnUninitialized) 1044 ? JSTypeHintLowering::kBailoutOnUninitialized 1045 : JSTypeHintLowering::kNoFlags), 1046 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( 1047 FrameStateType::kUnoptimizedFunction, 1048 bytecode_array().parameter_count(), bytecode_array().register_count(), 1049 shared_info.object())), 1050 source_position_iterator_(std::make_unique<SourcePositionTableIterator>( 1051 bytecode_array().SourcePositionTable())), 1052 bytecode_iterator_(bytecode_array().object()), 1053 bytecode_analysis_( 1054 bytecode_array().object(), local_zone, osr_offset, 1055 flags & BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness), 1056 environment_(nullptr), 1057 osr_(!osr_offset.IsNone()), 1058 currently_peeled_loop_offset_(-1), 1059 skip_first_stack_and_tierup_check_( 1060 flags & BytecodeGraphBuilderFlag::kSkipFirstStackAndTierupCheck), 1061 merge_environments_(local_zone), 1062 generator_merge_environments_(local_zone), 1063 cached_parameters_(local_zone), 1064 exception_handlers_(local_zone), 1065 current_exception_handler_(0), 1066 input_buffer_size_(0), 1067 input_buffer_(nullptr), 1068 code_kind_(code_kind), 1069 feedback_vector_node_(nullptr), 1070 native_context_node_(nullptr), 1071 needs_eager_checkpoint_(true), 1072 exit_controls_(local_zone), 1073 state_values_cache_(jsgraph), 1074 source_positions_(source_positions), 1075 start_position_(shared_info.StartPosition(), inlining_id), 1076 tick_counter_(tick_counter), 1077 observe_node_info_(observe_node_info) {} 1078 1079Node* BytecodeGraphBuilder::GetFunctionClosure() { 1080 if (!function_closure_.is_set()) { 1081 int index = Linkage::kJSCallClosureParamIndex; 1082 Node* node = GetParameter(index, "%closure"); 1083 function_closure_.set(node); 1084 } 1085 return function_closure_.get(); 1086} 1087 1088Node* BytecodeGraphBuilder::GetParameter(int parameter_index, 1089 const char* debug_name_hint) { 1090 // We use negative indices for some parameters. 1091 DCHECK_LE(ParameterInfo::kMinIndex, parameter_index); 1092 const size_t index = 1093 static_cast<size_t>(parameter_index - ParameterInfo::kMinIndex); 1094 1095 if (cached_parameters_.size() <= index) { 1096 cached_parameters_.resize(index + 1, nullptr); 1097 } 1098 1099 if (cached_parameters_[index] == nullptr) { 1100 cached_parameters_[index] = 1101 NewNode(common()->Parameter(parameter_index, debug_name_hint), 1102 graph()->start()); 1103 } 1104 1105 return cached_parameters_[index]; 1106} 1107 1108void BytecodeGraphBuilder::CreateFeedbackVectorNode() { 1109 DCHECK_NULL(feedback_vector_node_); 1110 feedback_vector_node_ = jsgraph()->Constant(feedback_vector()); 1111} 1112 1113Node* BytecodeGraphBuilder::BuildLoadFeedbackCell(int index) { 1114 return jsgraph()->Constant(feedback_vector().GetClosureFeedbackCell(index)); 1115} 1116 1117void BytecodeGraphBuilder::CreateNativeContextNode() { 1118 DCHECK_NULL(native_context_node_); 1119 native_context_node_ = jsgraph()->Constant(native_context()); 1120} 1121 1122Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) { 1123 Node* result = NewNode(javascript()->LoadContext(0, index, true)); 1124 NodeProperties::ReplaceContextInput(result, native_context_node()); 1125 return result; 1126} 1127 1128FeedbackSource BytecodeGraphBuilder::CreateFeedbackSource(int slot_id) { 1129 return CreateFeedbackSource(FeedbackVector::ToSlot(slot_id)); 1130} 1131 1132FeedbackSource BytecodeGraphBuilder::CreateFeedbackSource(FeedbackSlot slot) { 1133 return FeedbackSource(feedback_vector(), slot); 1134} 1135 1136void BytecodeGraphBuilder::CreateGraph() { 1137 SourcePositionTable::Scope pos_scope(source_positions_, start_position_); 1138 1139 // Set up the basic structure of the graph. Outputs for {Start} are the formal 1140 // parameters (including the receiver) plus new target, number of arguments, 1141 // context and closure. 1142 int start_output_arity = StartNode::OutputArityForFormalParameterCount( 1143 bytecode_array().parameter_count()); 1144 graph()->SetStart(graph()->NewNode(common()->Start(start_output_arity))); 1145 1146 Environment env(this, bytecode_array().register_count(), 1147 bytecode_array().parameter_count(), 1148 bytecode_array().incoming_new_target_or_generator_register(), 1149 graph()->start()); 1150 set_environment(&env); 1151 1152 CreateFeedbackVectorNode(); 1153 CreateNativeContextNode(); 1154 1155 VisitBytecodes(); 1156 1157 // Finish the basic structure of the graph. 1158 DCHECK_NE(0u, exit_controls_.size()); 1159 int const input_count = static_cast<int>(exit_controls_.size()); 1160 Node** const inputs = &exit_controls_.front(); 1161 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 1162 graph()->SetEnd(end); 1163} 1164 1165void BytecodeGraphBuilder::PrepareEagerCheckpoint() { 1166 if (needs_eager_checkpoint()) { 1167 // Create an explicit checkpoint node for before the operation. This only 1168 // needs to happen if we aren't effect-dominated by a {Checkpoint} already. 1169 mark_as_needing_eager_checkpoint(false); 1170 Node* node = NewNode(common()->Checkpoint()); 1171 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 1172 DCHECK_EQ(IrOpcode::kDead, 1173 NodeProperties::GetFrameStateInput(node)->opcode()); 1174 BytecodeOffset bailout_id(bytecode_iterator().current_offset()); 1175 1176 const BytecodeLivenessState* liveness_before = 1177 bytecode_analysis().GetInLivenessFor( 1178 bytecode_iterator().current_offset()); 1179 1180 Node* frame_state_before = environment()->Checkpoint( 1181 bailout_id, OutputFrameStateCombine::Ignore(), liveness_before); 1182 NodeProperties::ReplaceFrameStateInput(node, frame_state_before); 1183#ifdef DEBUG 1184 } else { 1185 // In case we skipped checkpoint creation above, we must be able to find an 1186 // existing checkpoint that effect-dominates the nodes about to be created. 1187 // Starting a search from the current effect-dependency has to succeed. 1188 Node* effect = environment()->GetEffectDependency(); 1189 while (effect->opcode() != IrOpcode::kCheckpoint) { 1190 DCHECK(effect->op()->HasProperty(Operator::kNoWrite)); 1191 DCHECK_EQ(1, effect->op()->EffectInputCount()); 1192 effect = NodeProperties::GetEffectInput(effect); 1193 } 1194 } 1195#else 1196 } 1197#endif // DEBUG 1198} 1199 1200void BytecodeGraphBuilder::PrepareFrameState( 1201 Node* node, OutputFrameStateCombine combine, BytecodeOffset bailout_id, 1202 const BytecodeLivenessState* liveness) { 1203 if (OperatorProperties::HasFrameStateInput(node->op())) { 1204 // Add the frame state for after the operation. The node in question has 1205 // already been created and had a {Dead} frame state input up until now. 1206 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 1207 DCHECK_EQ(IrOpcode::kDead, 1208 NodeProperties::GetFrameStateInput(node)->opcode()); 1209 1210 Node* frame_state_after = 1211 environment()->Checkpoint(bailout_id, combine, liveness); 1212 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); 1213 } 1214} 1215 1216void BytecodeGraphBuilder::AdvanceIteratorsTo(int bytecode_offset) { 1217 for (; bytecode_iterator().current_offset() != bytecode_offset; 1218 bytecode_iterator().Advance()) { 1219 UpdateSourcePosition(bytecode_iterator().current_offset()); 1220 } 1221} 1222 1223// Stores the state of the SourcePosition iterator, and the index to the 1224// current exception handlers stack. We need, during the OSR graph generation, 1225// to backup the states of these iterators at the LoopHeader offset of each 1226// outer loop which contains the OSR loop. The iterators are then restored when 1227// peeling the loops, so that both exception handling and synchronisation with 1228// the source position can be achieved. 1229class BytecodeGraphBuilder::OsrIteratorState { 1230 public: 1231 explicit OsrIteratorState(BytecodeGraphBuilder* graph_builder) 1232 : graph_builder_(graph_builder), 1233 saved_states_(graph_builder->local_zone()) {} 1234 1235 void ProcessOsrPrelude() { 1236 ZoneVector<int> outer_loop_offsets(graph_builder_->local_zone()); 1237 int osr_entry = graph_builder_->bytecode_analysis().osr_entry_point(); 1238 1239 // We find here the outermost loop which contains the OSR loop. 1240 int outermost_loop_offset = osr_entry; 1241 while ((outermost_loop_offset = graph_builder_->bytecode_analysis() 1242 .GetLoopInfoFor(outermost_loop_offset) 1243 .parent_offset()) != -1) { 1244 outer_loop_offsets.push_back(outermost_loop_offset); 1245 } 1246 outermost_loop_offset = 1247 outer_loop_offsets.empty() ? osr_entry : outer_loop_offsets.back(); 1248 graph_builder_->AdvanceIteratorsTo(outermost_loop_offset); 1249 1250 // We save some iterators states at the offsets of the loop headers of the 1251 // outer loops (the ones containing the OSR loop). They will be used for 1252 // jumping back in the bytecode. 1253 for (ZoneVector<int>::const_reverse_iterator it = 1254 outer_loop_offsets.crbegin(); 1255 it != outer_loop_offsets.crend(); ++it) { 1256 graph_builder_->AdvanceIteratorsTo(*it); 1257 graph_builder_->ExitThenEnterExceptionHandlers( 1258 graph_builder_->bytecode_iterator().current_offset()); 1259 saved_states_.push(IteratorsStates( 1260 graph_builder_->current_exception_handler(), 1261 graph_builder_->source_position_iterator().GetState())); 1262 } 1263 1264 // Finishing by advancing to the OSR entry 1265 graph_builder_->AdvanceIteratorsTo(osr_entry); 1266 1267 // Enters all remaining exception handler which end before the OSR loop 1268 // so that on next call of VisitSingleBytecode they will get popped from 1269 // the exception handlers stack. 1270 graph_builder_->ExitThenEnterExceptionHandlers(osr_entry); 1271 graph_builder_->set_currently_peeled_loop_offset( 1272 graph_builder_->bytecode_analysis() 1273 .GetLoopInfoFor(osr_entry) 1274 .parent_offset()); 1275 } 1276 1277 void RestoreState(int target_offset, int new_parent_offset) { 1278 graph_builder_->bytecode_iterator().SetOffset(target_offset); 1279 // In case of a return, we must not build loop exits for 1280 // not-yet-built outer loops. 1281 graph_builder_->set_currently_peeled_loop_offset(new_parent_offset); 1282 IteratorsStates saved_state = saved_states_.top(); 1283 graph_builder_->source_position_iterator().RestoreState( 1284 saved_state.source_iterator_state_); 1285 graph_builder_->set_current_exception_handler( 1286 saved_state.exception_handler_index_); 1287 saved_states_.pop(); 1288 } 1289 1290 private: 1291 struct IteratorsStates { 1292 int exception_handler_index_; 1293 SourcePositionTableIterator::IndexAndPositionState source_iterator_state_; 1294 1295 IteratorsStates(int exception_handler_index, 1296 SourcePositionTableIterator::IndexAndPositionState 1297 source_iterator_state) 1298 : exception_handler_index_(exception_handler_index), 1299 source_iterator_state_(source_iterator_state) {} 1300 }; 1301 1302 BytecodeGraphBuilder* graph_builder_; 1303 ZoneStack<IteratorsStates> saved_states_; 1304}; 1305 1306void BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset( 1307 int limit_offset) { 1308 if (!merge_environments_.empty()) { 1309 ZoneMap<int, Environment*>::iterator it = merge_environments_.begin(); 1310 ZoneMap<int, Environment*>::iterator stop_it = merge_environments_.end(); 1311 while (it != stop_it && it->first <= limit_offset) { 1312 it = merge_environments_.erase(it); 1313 } 1314 } 1315} 1316 1317void BytecodeGraphBuilder::BuildFunctionEntryStackCheck() { 1318 if (!skip_first_stack_check()) { 1319 DCHECK(exception_handlers_.empty()); 1320 Node* node = 1321 NewNode(javascript()->StackCheck(StackCheckKind::kJSFunctionEntry)); 1322 PrepareFrameStateForFunctionEntryStackCheck(node); 1323 } 1324} 1325 1326void BytecodeGraphBuilder::BuildIterationBodyStackCheck() { 1327 Node* node = 1328 NewNode(javascript()->StackCheck(StackCheckKind::kJSIterationBody)); 1329 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1330} 1331 1332void BytecodeGraphBuilder::BuildOSREntryStackCheck() { 1333 DCHECK(exception_handlers_.empty()); 1334 Node* node = 1335 NewNode(javascript()->StackCheck(StackCheckKind::kJSFunctionEntry)); 1336 PrepareFrameStateForOSREntryStackCheck(node); 1337} 1338 1339// We will iterate through the OSR loop, then its parent, and so on 1340// until we have reached the outmost loop containing the OSR loop. We do 1341// not generate nodes for anything before the outermost loop. 1342void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops() { 1343 environment()->FillWithOsrValues(); 1344 1345 // The entry stack check has to happen *before* initialising the OSR prelude; 1346 // it has to happen before setting up exception handlers, so that the 1347 // optimized code can't accidentally catch a failingstack with a OSR-ed loop 1348 // inside a try-catch, e.g. 1349 // 1350 // try { 1351 // loop { OSR(); } 1352 // } catch { 1353 // // Ignore failed stack check. 1354 // } 1355 BuildOSREntryStackCheck(); 1356 1357 OsrIteratorState iterator_states(this); 1358 iterator_states.ProcessOsrPrelude(); 1359 int osr_entry = bytecode_analysis().osr_entry_point(); 1360 DCHECK_EQ(bytecode_iterator().current_offset(), osr_entry); 1361 1362 // Suppose we have n nested loops, loop_0 being the outermost one, and 1363 // loop_n being the OSR loop. We start iterating the bytecode at the header 1364 // of loop_n (the OSR loop), and then we peel the part of the the body of 1365 // loop_{n-1} following the end of loop_n. We then rewind the iterator to 1366 // the header of loop_{n-1}, and so on until we have partly peeled loop 0. 1367 // The full loop_0 body will be generating with the rest of the function, 1368 // outside the OSR generation. 1369 1370 // To do so, if we are visiting a loop, we continue to visit what's left 1371 // of its parent, and then when reaching the parent's JumpLoop, we do not 1372 // create any jump for that but rewind the bytecode iterator to visit the 1373 // parent loop entirely, and so on. 1374 1375 int current_parent_offset = 1376 bytecode_analysis().GetLoopInfoFor(osr_entry).parent_offset(); 1377 while (current_parent_offset != -1) { 1378 const LoopInfo& current_parent_loop = 1379 bytecode_analysis().GetLoopInfoFor(current_parent_offset); 1380 // We iterate until the back edge of the parent loop, which we detect by 1381 // the offset that the JumpLoop targets. 1382 for (; !bytecode_iterator().done(); bytecode_iterator().Advance()) { 1383 if (bytecode_iterator().current_bytecode() == 1384 interpreter::Bytecode::kJumpLoop && 1385 bytecode_iterator().GetJumpTargetOffset() == current_parent_offset) { 1386 // Reached the end of the current parent loop. 1387 break; 1388 } 1389 VisitSingleBytecode(); 1390 } 1391 DCHECK(!bytecode_iterator() 1392 .done()); // Should have found the loop's jump target. 1393 1394 // We also need to take care of the merge environments and exceptions 1395 // handlers here because the omitted JumpLoop bytecode can still be the 1396 // target of jumps or the first bytecode after a try block. 1397 ExitThenEnterExceptionHandlers(bytecode_iterator().current_offset()); 1398 SwitchToMergeEnvironment(bytecode_iterator().current_offset()); 1399 1400 // This jump is the jump of our parent loop, which is not yet created. 1401 // So we do not build the jump nodes, but restore the bytecode and the 1402 // SourcePosition iterators to the values they had when we were visiting 1403 // the offset pointed at by the JumpLoop we've just reached. 1404 // We have already built nodes for inner loops, but now we will 1405 // iterate again over them and build new nodes corresponding to the same 1406 // bytecode offsets. Any jump or reference to this inner loops must now 1407 // point to the new nodes we will build, hence we clear the relevant part 1408 // of the environment. 1409 // Completely clearing the environment is not possible because merge 1410 // environments for forward jumps out of the loop need to be preserved 1411 // (e.g. a return or a labeled break in the middle of a loop). 1412 RemoveMergeEnvironmentsBeforeOffset(bytecode_iterator().current_offset()); 1413 iterator_states.RestoreState(current_parent_offset, 1414 current_parent_loop.parent_offset()); 1415 current_parent_offset = current_parent_loop.parent_offset(); 1416 } 1417} 1418 1419void BytecodeGraphBuilder::VisitSingleBytecode() { 1420 tick_counter_->TickAndMaybeEnterSafepoint(); 1421 int current_offset = bytecode_iterator().current_offset(); 1422 UpdateSourcePosition(current_offset); 1423 ExitThenEnterExceptionHandlers(current_offset); 1424 DCHECK_GE(exception_handlers_.empty() ? current_offset 1425 : exception_handlers_.top().end_offset_, 1426 current_offset); 1427 SwitchToMergeEnvironment(current_offset); 1428 1429 if (environment() != nullptr) { 1430 BuildLoopHeaderEnvironment(current_offset); 1431 1432 switch (bytecode_iterator().current_bytecode()) { 1433#define BYTECODE_CASE(name, ...) \ 1434 case interpreter::Bytecode::k##name: \ 1435 Visit##name(); \ 1436 break; 1437 BYTECODE_LIST(BYTECODE_CASE) 1438#undef BYTECODE_CASE 1439 } 1440 } 1441} 1442 1443void BytecodeGraphBuilder::VisitBytecodes() { 1444 if (!bytecode_analysis().resume_jump_targets().empty()) { 1445 environment()->BindGeneratorState( 1446 jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting)); 1447 } 1448 1449 if (osr_) { 1450 // We peel the OSR loop and any outer loop containing it except that we 1451 // leave the nodes corresponding to the whole outermost loop (including 1452 // the last copies of the loops it contains) to be generated by the normal 1453 // bytecode iteration below. 1454 AdvanceToOsrEntryAndPeelLoops(); 1455 } else { 1456 BuildFunctionEntryStackCheck(); 1457 } 1458 1459 for (; !bytecode_iterator().done(); bytecode_iterator().Advance()) { 1460 VisitSingleBytecode(); 1461 } 1462 1463 DCHECK(exception_handlers_.empty()); 1464} 1465 1466void BytecodeGraphBuilder::VisitLdaZero() { 1467 Node* node = jsgraph()->ZeroConstant(); 1468 environment()->BindAccumulator(node); 1469} 1470 1471void BytecodeGraphBuilder::VisitLdaSmi() { 1472 Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 1473 environment()->BindAccumulator(node); 1474} 1475 1476void BytecodeGraphBuilder::VisitLdaConstant() { 1477 ObjectRef object = MakeRefForConstantForIndexOperand(0); 1478 Node* node = jsgraph()->Constant(object); 1479 environment()->BindAccumulator(node); 1480} 1481 1482void BytecodeGraphBuilder::VisitLdaUndefined() { 1483 Node* node = jsgraph()->UndefinedConstant(); 1484 environment()->BindAccumulator(node); 1485} 1486 1487void BytecodeGraphBuilder::VisitLdaNull() { 1488 Node* node = jsgraph()->NullConstant(); 1489 environment()->BindAccumulator(node); 1490} 1491 1492void BytecodeGraphBuilder::VisitLdaTheHole() { 1493 Node* node = jsgraph()->TheHoleConstant(); 1494 environment()->BindAccumulator(node); 1495} 1496 1497void BytecodeGraphBuilder::VisitLdaTrue() { 1498 Node* node = jsgraph()->TrueConstant(); 1499 environment()->BindAccumulator(node); 1500} 1501 1502void BytecodeGraphBuilder::VisitLdaFalse() { 1503 Node* node = jsgraph()->FalseConstant(); 1504 environment()->BindAccumulator(node); 1505} 1506 1507void BytecodeGraphBuilder::VisitLdar() { 1508 Node* value = 1509 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1510 environment()->BindAccumulator(value); 1511} 1512 1513void BytecodeGraphBuilder::VisitStar() { 1514 Node* value = environment()->LookupAccumulator(); 1515 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value); 1516} 1517 1518#define SHORT_STAR_VISITOR(Name, ...) \ 1519 void BytecodeGraphBuilder::Visit##Name() { \ 1520 Node* value = environment()->LookupAccumulator(); \ 1521 environment()->BindRegister( \ 1522 interpreter::Register::FromShortStar(interpreter::Bytecode::k##Name), \ 1523 value); \ 1524 } 1525SHORT_STAR_BYTECODE_LIST(SHORT_STAR_VISITOR) 1526#undef SHORT_STAR_VISITOR 1527 1528void BytecodeGraphBuilder::VisitMov() { 1529 Node* value = 1530 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1531 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value); 1532} 1533 1534Node* BytecodeGraphBuilder::BuildLoadGlobal(NameRef name, 1535 uint32_t feedback_slot_index, 1536 TypeofMode typeof_mode) { 1537 FeedbackSource feedback = CreateFeedbackSource(feedback_slot_index); 1538 DCHECK(IsLoadGlobalICKind(broker()->GetFeedbackSlotKind(feedback))); 1539 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode); 1540 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 1541 return NewNode(op, feedback_vector_node()); 1542} 1543 1544void BytecodeGraphBuilder::VisitLdaGlobal() { 1545 PrepareEagerCheckpoint(); 1546 NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 1547 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 1548 Node* node = 1549 BuildLoadGlobal(name, feedback_slot_index, TypeofMode::kNotInside); 1550 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1551} 1552 1553void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() { 1554 PrepareEagerCheckpoint(); 1555 NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 1556 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 1557 Node* node = BuildLoadGlobal(name, feedback_slot_index, TypeofMode::kInside); 1558 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1559} 1560 1561void BytecodeGraphBuilder::VisitStaGlobal() { 1562 PrepareEagerCheckpoint(); 1563 NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 1564 FeedbackSource feedback = 1565 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 1566 Node* value = environment()->LookupAccumulator(); 1567 1568 LanguageMode language_mode = 1569 GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(feedback)); 1570 const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback); 1571 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 1572 Node* node = NewNode(op, value, feedback_vector_node()); 1573 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1574} 1575 1576void BytecodeGraphBuilder::VisitStaInArrayLiteral() { 1577 PrepareEagerCheckpoint(); 1578 Node* value = environment()->LookupAccumulator(); 1579 Node* array = 1580 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1581 Node* index = 1582 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1583 FeedbackSource feedback = 1584 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 1585 const Operator* op = javascript()->StoreInArrayLiteral(feedback); 1586 1587 JSTypeHintLowering::LoweringResult lowering = 1588 TryBuildSimplifiedStoreKeyed(op, array, index, value, feedback.slot); 1589 if (lowering.IsExit()) return; 1590 1591 Node* node = nullptr; 1592 if (lowering.IsSideEffectFree()) { 1593 node = lowering.value(); 1594 } else { 1595 DCHECK(!lowering.Changed()); 1596 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 1597 node = NewNode(op, array, index, value, feedback_vector_node()); 1598 } 1599 1600 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1601} 1602 1603void BytecodeGraphBuilder::VisitDefineKeyedOwnPropertyInLiteral() { 1604 PrepareEagerCheckpoint(); 1605 1606 Node* object = 1607 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1608 Node* name = 1609 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1610 Node* value = environment()->LookupAccumulator(); 1611 int flags = bytecode_iterator().GetFlagOperand(2); 1612 FeedbackSource feedback = 1613 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(3)); 1614 const Operator* op = javascript()->DefineKeyedOwnPropertyInLiteral(feedback); 1615 1616 JSTypeHintLowering::LoweringResult lowering = 1617 TryBuildSimplifiedStoreKeyed(op, object, name, value, feedback.slot); 1618 if (lowering.IsExit()) return; 1619 1620 Node* node = nullptr; 1621 if (lowering.IsSideEffectFree()) { 1622 node = lowering.value(); 1623 } else { 1624 DCHECK(!lowering.Changed()); 1625 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 1626 node = NewNode(op, object, name, value, jsgraph()->Constant(flags), 1627 feedback_vector_node()); 1628 } 1629 1630 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1631} 1632 1633void BytecodeGraphBuilder::VisitCollectTypeProfile() { 1634 PrepareEagerCheckpoint(); 1635 1636 Node* position = 1637 jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 1638 Node* value = environment()->LookupAccumulator(); 1639 Node* vector = jsgraph()->Constant(feedback_vector()); 1640 1641 const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile); 1642 1643 Node* node = NewNode(op, position, value, vector); 1644 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1645} 1646 1647void BytecodeGraphBuilder::VisitLdaContextSlot() { 1648 const Operator* op = javascript()->LoadContext( 1649 bytecode_iterator().GetUnsignedImmediateOperand(2), 1650 bytecode_iterator().GetIndexOperand(1), false); 1651 Node* node = NewNode(op); 1652 Node* context = 1653 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1654 NodeProperties::ReplaceContextInput(node, context); 1655 environment()->BindAccumulator(node); 1656} 1657 1658void BytecodeGraphBuilder::VisitLdaImmutableContextSlot() { 1659 const Operator* op = javascript()->LoadContext( 1660 bytecode_iterator().GetUnsignedImmediateOperand(2), 1661 bytecode_iterator().GetIndexOperand(1), true); 1662 Node* node = NewNode(op); 1663 Node* context = 1664 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1665 NodeProperties::ReplaceContextInput(node, context); 1666 environment()->BindAccumulator(node); 1667} 1668 1669void BytecodeGraphBuilder::VisitLdaCurrentContextSlot() { 1670 const Operator* op = javascript()->LoadContext( 1671 0, bytecode_iterator().GetIndexOperand(0), false); 1672 Node* node = NewNode(op); 1673 environment()->BindAccumulator(node); 1674} 1675 1676void BytecodeGraphBuilder::VisitLdaImmutableCurrentContextSlot() { 1677 const Operator* op = javascript()->LoadContext( 1678 0, bytecode_iterator().GetIndexOperand(0), true); 1679 Node* node = NewNode(op); 1680 environment()->BindAccumulator(node); 1681} 1682 1683void BytecodeGraphBuilder::VisitStaContextSlot() { 1684 const Operator* op = javascript()->StoreContext( 1685 bytecode_iterator().GetUnsignedImmediateOperand(2), 1686 bytecode_iterator().GetIndexOperand(1)); 1687 Node* value = environment()->LookupAccumulator(); 1688 Node* node = NewNode(op, value); 1689 Node* context = 1690 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1691 NodeProperties::ReplaceContextInput(node, context); 1692} 1693 1694void BytecodeGraphBuilder::VisitStaCurrentContextSlot() { 1695 const Operator* op = 1696 javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0)); 1697 Node* value = environment()->LookupAccumulator(); 1698 NewNode(op, value); 1699} 1700 1701void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) { 1702 PrepareEagerCheckpoint(); 1703 Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 1704 const Operator* op = 1705 javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside 1706 ? Runtime::kLoadLookupSlot 1707 : Runtime::kLoadLookupSlotInsideTypeof); 1708 Node* value = NewNode(op, name); 1709 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1710} 1711 1712void BytecodeGraphBuilder::VisitLdaLookupSlot() { 1713 BuildLdaLookupSlot(TypeofMode::kNotInside); 1714} 1715 1716void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() { 1717 BuildLdaLookupSlot(TypeofMode::kInside); 1718} 1719 1720BytecodeGraphBuilder::Environment* 1721BytecodeGraphBuilder::CheckContextExtensionAtDepth( 1722 Environment* slow_environment, uint32_t depth) { 1723 Node* extension_slot = NewNode( 1724 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false)); 1725 Node* check_no_extension = 1726 NewNode(simplified()->ReferenceEqual(), extension_slot, 1727 jsgraph()->UndefinedConstant()); 1728 NewBranch(check_no_extension); 1729 { 1730 SubEnvironment sub_environment(this); 1731 NewIfFalse(); 1732 // If there is an extension, merge into the slow path. 1733 if (slow_environment == nullptr) { 1734 slow_environment = environment(); 1735 NewMerge(); 1736 } else { 1737 slow_environment->Merge(environment(), 1738 bytecode_analysis().GetInLivenessFor( 1739 bytecode_iterator().current_offset())); 1740 } 1741 } 1742 NewIfTrue(); 1743 // Do nothing on if there is no extension, eventually falling through to 1744 // the fast path. 1745 DCHECK_NOT_NULL(slow_environment); 1746 return slow_environment; 1747} 1748 1749base::Optional<ScopeInfoRef> BytecodeGraphBuilder::TryGetScopeInfo() { 1750 Node* context = environment()->Context(); 1751 switch (context->opcode()) { 1752 case IrOpcode::kJSCreateFunctionContext: 1753 return CreateFunctionContextParametersOf(context->op()) 1754 .scope_info(broker()); 1755 case IrOpcode::kJSCreateBlockContext: 1756 case IrOpcode::kJSCreateCatchContext: 1757 case IrOpcode::kJSCreateWithContext: 1758 return ScopeInfoOf(broker(), context->op()); 1759 case IrOpcode::kParameter: { 1760 ScopeInfoRef scope_info = shared_info_.scope_info(); 1761 if (scope_info.HasOuterScopeInfo()) { 1762 scope_info = scope_info.OuterScopeInfo(); 1763 } 1764 return scope_info; 1765 } 1766 default: 1767 return base::nullopt; 1768 } 1769} 1770 1771BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( 1772 uint32_t depth) { 1773 base::Optional<ScopeInfoRef> maybe_scope_info = TryGetScopeInfo(); 1774 if (!maybe_scope_info.has_value()) { 1775 return CheckContextExtensionsSlowPath(depth); 1776 } 1777 1778 ScopeInfoRef scope_info = maybe_scope_info.value(); 1779 // We only need to check up to the last-but-one depth, because an eval 1780 // in the same scope as the variable itself has no way of shadowing it. 1781 Environment* slow_environment = nullptr; 1782 for (uint32_t d = 0; d < depth; d++) { 1783 if (scope_info.HasContextExtensionSlot()) { 1784 slow_environment = CheckContextExtensionAtDepth(slow_environment, d); 1785 } 1786 DCHECK_IMPLIES(!scope_info.HasOuterScopeInfo(), d + 1 == depth); 1787 if (scope_info.HasOuterScopeInfo()) { 1788 scope_info = scope_info.OuterScopeInfo(); 1789 } 1790 } 1791 1792 // The depth can be zero, in which case no slow-path checks are built, and 1793 // the slow path environment can be null. 1794 DCHECK_IMPLIES(slow_environment == nullptr, depth == 0); 1795 return slow_environment; 1796} 1797 1798BytecodeGraphBuilder::Environment* 1799BytecodeGraphBuilder::CheckContextExtensionsSlowPath(uint32_t depth) { 1800 // Output environment where the context has an extension 1801 Environment* slow_environment = nullptr; 1802 1803 // We only need to check up to the last-but-one depth, because an eval 1804 // in the same scope as the variable itself has no way of shadowing it. 1805 for (uint32_t d = 0; d < depth; d++) { 1806 Node* has_extension = NewNode(javascript()->HasContextExtension(d)); 1807 1808 Environment* undefined_extension_env; 1809 NewBranch(has_extension); 1810 { 1811 SubEnvironment sub_environment(this); 1812 NewIfTrue(); 1813 slow_environment = CheckContextExtensionAtDepth(slow_environment, d); 1814 undefined_extension_env = environment(); 1815 } 1816 NewIfFalse(); 1817 environment()->Merge(undefined_extension_env, 1818 bytecode_analysis().GetInLivenessFor( 1819 bytecode_iterator().current_offset())); 1820 mark_as_needing_eager_checkpoint(true); 1821 // Do nothing on if there is no extension, eventually falling through to 1822 // the fast path. 1823 } 1824 1825 // The depth can be zero, in which case no slow-path checks are built, and 1826 // the slow path environment can be null. 1827 DCHECK_IMPLIES(slow_environment == nullptr, depth == 0); 1828 return slow_environment; 1829} 1830 1831void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) { 1832 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); 1833 1834 // Check if any context in the depth has an extension. 1835 Environment* slow_environment = CheckContextExtensions(depth); 1836 1837 // Fast path, do a context load. 1838 { 1839 uint32_t slot_index = bytecode_iterator().GetIndexOperand(1); 1840 1841 const Operator* op = javascript()->LoadContext(depth, slot_index, false); 1842 environment()->BindAccumulator(NewNode(op)); 1843 } 1844 1845 // Only build the slow path if there were any slow-path checks. 1846 if (slow_environment != nullptr) { 1847 // Add a merge to the fast environment. 1848 NewMerge(); 1849 Environment* fast_environment = environment(); 1850 1851 // Slow path, do a runtime load lookup. 1852 set_environment(slow_environment); 1853 { 1854 Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 1855 1856 const Operator* op = 1857 javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside 1858 ? Runtime::kLoadLookupSlot 1859 : Runtime::kLoadLookupSlotInsideTypeof); 1860 Node* value = NewNode(op, name); 1861 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1862 } 1863 1864 fast_environment->Merge(environment(), 1865 bytecode_analysis().GetOutLivenessFor( 1866 bytecode_iterator().current_offset())); 1867 set_environment(fast_environment); 1868 mark_as_needing_eager_checkpoint(true); 1869 } 1870} 1871 1872void BytecodeGraphBuilder::VisitLdaLookupContextSlot() { 1873 BuildLdaLookupContextSlot(TypeofMode::kNotInside); 1874} 1875 1876void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() { 1877 BuildLdaLookupContextSlot(TypeofMode::kInside); 1878} 1879 1880void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) { 1881 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); 1882 1883 // Check if any context in the depth has an extension. 1884 Environment* slow_environment = CheckContextExtensions(depth); 1885 1886 // Fast path, do a global load. 1887 { 1888 PrepareEagerCheckpoint(); 1889 NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 1890 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 1891 Node* node = BuildLoadGlobal(name, feedback_slot_index, typeof_mode); 1892 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1893 } 1894 1895 // Only build the slow path if there were any slow-path checks. 1896 if (slow_environment != nullptr) { 1897 // Add a merge to the fast environment. 1898 NewMerge(); 1899 Environment* fast_environment = environment(); 1900 1901 // Slow path, do a runtime load lookup. 1902 set_environment(slow_environment); 1903 { 1904 Node* name = 1905 jsgraph()->Constant(MakeRefForConstantForIndexOperand<Name>(0)); 1906 1907 const Operator* op = 1908 javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside 1909 ? Runtime::kLoadLookupSlot 1910 : Runtime::kLoadLookupSlotInsideTypeof); 1911 Node* value = NewNode(op, name); 1912 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1913 } 1914 1915 fast_environment->Merge(environment(), 1916 bytecode_analysis().GetOutLivenessFor( 1917 bytecode_iterator().current_offset())); 1918 set_environment(fast_environment); 1919 mark_as_needing_eager_checkpoint(true); 1920 } 1921} 1922 1923void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() { 1924 BuildLdaLookupGlobalSlot(TypeofMode::kNotInside); 1925} 1926 1927void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() { 1928 BuildLdaLookupGlobalSlot(TypeofMode::kInside); 1929} 1930 1931void BytecodeGraphBuilder::VisitStaLookupSlot() { 1932 PrepareEagerCheckpoint(); 1933 Node* value = environment()->LookupAccumulator(); 1934 Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 1935 int bytecode_flags = bytecode_iterator().GetFlagOperand(1); 1936 LanguageMode language_mode = static_cast<LanguageMode>( 1937 interpreter::StoreLookupSlotFlags::LanguageModeBit::decode( 1938 bytecode_flags)); 1939 LookupHoistingMode lookup_hoisting_mode = static_cast<LookupHoistingMode>( 1940 interpreter::StoreLookupSlotFlags::LookupHoistingModeBit::decode( 1941 bytecode_flags)); 1942 DCHECK_IMPLIES(lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy, 1943 is_sloppy(language_mode)); 1944 const Operator* op = javascript()->CallRuntime( 1945 is_strict(language_mode) 1946 ? Runtime::kStoreLookupSlot_Strict 1947 : lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy 1948 ? Runtime::kStoreLookupSlot_SloppyHoisting 1949 : Runtime::kStoreLookupSlot_Sloppy); 1950 Node* store = NewNode(op, name, value); 1951 environment()->BindAccumulator(store, Environment::kAttachFrameState); 1952} 1953 1954void BytecodeGraphBuilder::VisitGetNamedProperty() { 1955 PrepareEagerCheckpoint(); 1956 Node* object = 1957 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1958 NameRef name = MakeRefForConstantForIndexOperand<Name>(1); 1959 FeedbackSource feedback = 1960 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 1961 const Operator* op = javascript()->LoadNamed(name, feedback); 1962 1963 JSTypeHintLowering::LoweringResult lowering = 1964 TryBuildSimplifiedLoadNamed(op, feedback.slot); 1965 if (lowering.IsExit()) return; 1966 1967 Node* node = nullptr; 1968 if (lowering.IsSideEffectFree()) { 1969 node = lowering.value(); 1970 } else { 1971 DCHECK(!lowering.Changed()); 1972 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 1973 node = NewNode(op, object, feedback_vector_node()); 1974 } 1975 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1976} 1977 1978void BytecodeGraphBuilder::VisitGetNamedPropertyFromSuper() { 1979 PrepareEagerCheckpoint(); 1980 Node* receiver = 1981 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1982 Node* home_object = environment()->LookupAccumulator(); 1983 NameRef name = MakeRefForConstantForIndexOperand<Name>(1); 1984 1985 FeedbackSource feedback = 1986 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 1987 const Operator* op = javascript()->LoadNamedFromSuper(name, feedback); 1988 1989 JSTypeHintLowering::LoweringResult lowering = 1990 TryBuildSimplifiedLoadNamed(op, feedback.slot); 1991 if (lowering.IsExit()) return; 1992 1993 Node* node = nullptr; 1994 if (lowering.IsSideEffectFree()) { 1995 node = lowering.value(); 1996 } else { 1997 DCHECK(!lowering.Changed()); 1998 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 1999 node = NewNode(op, receiver, home_object, feedback_vector_node()); 2000 } 2001 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2002} 2003 2004void BytecodeGraphBuilder::VisitGetKeyedProperty() { 2005 PrepareEagerCheckpoint(); 2006 Node* key = environment()->LookupAccumulator(); 2007 Node* object = 2008 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2009 FeedbackSource feedback = 2010 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 2011 const Operator* op = javascript()->LoadProperty(feedback); 2012 2013 JSTypeHintLowering::LoweringResult lowering = 2014 TryBuildSimplifiedLoadKeyed(op, object, key, feedback.slot); 2015 if (lowering.IsExit()) return; 2016 2017 Node* node = nullptr; 2018 if (lowering.IsSideEffectFree()) { 2019 node = lowering.value(); 2020 } else { 2021 DCHECK(!lowering.Changed()); 2022 STATIC_ASSERT(JSLoadPropertyNode::ObjectIndex() == 0); 2023 STATIC_ASSERT(JSLoadPropertyNode::KeyIndex() == 1); 2024 STATIC_ASSERT(JSLoadPropertyNode::FeedbackVectorIndex() == 2); 2025 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2026 node = NewNode(op, object, key, feedback_vector_node()); 2027 } 2028 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2029} 2030 2031void BytecodeGraphBuilder::BuildNamedStore(NamedStoreMode store_mode) { 2032 PrepareEagerCheckpoint(); 2033 Node* value = environment()->LookupAccumulator(); 2034 Node* object = 2035 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2036 NameRef name = MakeRefForConstantForIndexOperand<Name>(1); 2037 FeedbackSource feedback = 2038 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 2039 2040 const Operator* op; 2041 if (store_mode == NamedStoreMode::kDefineOwn) { 2042 DCHECK_EQ(FeedbackSlotKind::kDefineNamedOwn, 2043 broker()->GetFeedbackSlotKind(feedback)); 2044 2045 op = javascript()->DefineNamedOwnProperty(name, feedback); 2046 } else { 2047 DCHECK_EQ(NamedStoreMode::kSet, store_mode); 2048 LanguageMode language_mode = 2049 GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(feedback)); 2050 op = javascript()->SetNamedProperty(language_mode, name, feedback); 2051 } 2052 2053 JSTypeHintLowering::LoweringResult lowering = 2054 TryBuildSimplifiedStoreNamed(op, object, value, feedback.slot); 2055 if (lowering.IsExit()) return; 2056 2057 Node* node = nullptr; 2058 if (lowering.IsSideEffectFree()) { 2059 node = lowering.value(); 2060 } else { 2061 DCHECK(!lowering.Changed()); 2062 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2063 node = NewNode(op, object, value, feedback_vector_node()); 2064 } 2065 environment()->RecordAfterState(node, Environment::kAttachFrameState); 2066} 2067 2068void BytecodeGraphBuilder::VisitSetNamedProperty() { 2069 BuildNamedStore(NamedStoreMode::kSet); 2070} 2071 2072void BytecodeGraphBuilder::VisitDefineNamedOwnProperty() { 2073 BuildNamedStore(NamedStoreMode::kDefineOwn); 2074} 2075 2076void BytecodeGraphBuilder::VisitSetKeyedProperty() { 2077 PrepareEagerCheckpoint(); 2078 Node* value = environment()->LookupAccumulator(); 2079 Node* object = 2080 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2081 Node* key = 2082 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 2083 FeedbackSource source = 2084 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 2085 LanguageMode language_mode = 2086 GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(source)); 2087 const Operator* op = javascript()->SetKeyedProperty(language_mode, source); 2088 2089 JSTypeHintLowering::LoweringResult lowering = 2090 TryBuildSimplifiedStoreKeyed(op, object, key, value, source.slot); 2091 if (lowering.IsExit()) return; 2092 2093 Node* node = nullptr; 2094 if (lowering.IsSideEffectFree()) { 2095 node = lowering.value(); 2096 } else { 2097 DCHECK(!lowering.Changed()); 2098 STATIC_ASSERT(JSSetKeyedPropertyNode::ObjectIndex() == 0); 2099 STATIC_ASSERT(JSSetKeyedPropertyNode::KeyIndex() == 1); 2100 STATIC_ASSERT(JSSetKeyedPropertyNode::ValueIndex() == 2); 2101 STATIC_ASSERT(JSSetKeyedPropertyNode::FeedbackVectorIndex() == 3); 2102 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2103 node = NewNode(op, object, key, value, feedback_vector_node()); 2104 } 2105 2106 environment()->RecordAfterState(node, Environment::kAttachFrameState); 2107} 2108 2109void BytecodeGraphBuilder::VisitDefineKeyedOwnProperty() { 2110 PrepareEagerCheckpoint(); 2111 Node* value = environment()->LookupAccumulator(); 2112 Node* object = 2113 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2114 Node* key = 2115 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 2116 FeedbackSource source = 2117 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 2118 LanguageMode language_mode = 2119 GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(source)); 2120 2121 const Operator* op = 2122 javascript()->DefineKeyedOwnProperty(language_mode, source); 2123 2124 JSTypeHintLowering::LoweringResult lowering = 2125 TryBuildSimplifiedStoreKeyed(op, object, key, value, source.slot); 2126 if (lowering.IsExit()) return; 2127 2128 Node* node = nullptr; 2129 if (lowering.IsSideEffectFree()) { 2130 node = lowering.value(); 2131 } else { 2132 DCHECK(!lowering.Changed()); 2133 STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::ObjectIndex() == 0); 2134 STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::KeyIndex() == 1); 2135 STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::ValueIndex() == 2); 2136 STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::FeedbackVectorIndex() == 3); 2137 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2138 node = NewNode(op, object, key, value, feedback_vector_node()); 2139 } 2140 2141 environment()->RecordAfterState(node, Environment::kAttachFrameState); 2142} 2143 2144void BytecodeGraphBuilder::VisitLdaModuleVariable() { 2145 int32_t cell_index = bytecode_iterator().GetImmediateOperand(0); 2146 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1); 2147 Node* module = 2148 NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true)); 2149 Node* value = NewNode(javascript()->LoadModule(cell_index), module); 2150 environment()->BindAccumulator(value); 2151} 2152 2153void BytecodeGraphBuilder::VisitStaModuleVariable() { 2154 int32_t cell_index = bytecode_iterator().GetImmediateOperand(0); 2155 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1); 2156 Node* module = 2157 NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true)); 2158 Node* value = environment()->LookupAccumulator(); 2159 NewNode(javascript()->StoreModule(cell_index), module, value); 2160} 2161 2162void BytecodeGraphBuilder::VisitPushContext() { 2163 Node* new_context = environment()->LookupAccumulator(); 2164 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), 2165 environment()->Context()); 2166 environment()->SetContext(new_context); 2167} 2168 2169void BytecodeGraphBuilder::VisitPopContext() { 2170 Node* context = 2171 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2172 environment()->SetContext(context); 2173} 2174 2175void BytecodeGraphBuilder::VisitCreateClosure() { 2176 SharedFunctionInfoRef shared_info = 2177 MakeRefForConstantForIndexOperand<SharedFunctionInfo>(0); 2178 AllocationType allocation = 2179 interpreter::CreateClosureFlags::PretenuredBit::decode( 2180 bytecode_iterator().GetFlagOperand(2)) 2181 ? AllocationType::kOld 2182 : AllocationType::kYoung; 2183 CodeTRef compile_lazy = 2184 MakeRef(broker(), *BUILTIN_CODE(jsgraph()->isolate(), CompileLazy)); 2185 const Operator* op = 2186 javascript()->CreateClosure(shared_info, compile_lazy, allocation); 2187 Node* closure = NewNode( 2188 op, BuildLoadFeedbackCell(bytecode_iterator().GetIndexOperand(1))); 2189 environment()->BindAccumulator(closure); 2190} 2191 2192void BytecodeGraphBuilder::VisitCreateBlockContext() { 2193 ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0); 2194 const Operator* op = javascript()->CreateBlockContext(scope_info); 2195 Node* context = NewNode(op); 2196 environment()->BindAccumulator(context); 2197} 2198 2199void BytecodeGraphBuilder::VisitCreateFunctionContext() { 2200 ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0); 2201 uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1); 2202 const Operator* op = 2203 javascript()->CreateFunctionContext(scope_info, slots, FUNCTION_SCOPE); 2204 Node* context = NewNode(op); 2205 environment()->BindAccumulator(context); 2206} 2207 2208void BytecodeGraphBuilder::VisitCreateEvalContext() { 2209 ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0); 2210 uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1); 2211 const Operator* op = 2212 javascript()->CreateFunctionContext(scope_info, slots, EVAL_SCOPE); 2213 Node* context = NewNode(op); 2214 environment()->BindAccumulator(context); 2215} 2216 2217void BytecodeGraphBuilder::VisitCreateCatchContext() { 2218 interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0); 2219 Node* exception = environment()->LookupRegister(reg); 2220 ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(1); 2221 2222 const Operator* op = javascript()->CreateCatchContext(scope_info); 2223 Node* context = NewNode(op, exception); 2224 environment()->BindAccumulator(context); 2225} 2226 2227void BytecodeGraphBuilder::VisitCreateWithContext() { 2228 Node* object = 2229 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2230 ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(1); 2231 2232 const Operator* op = javascript()->CreateWithContext(scope_info); 2233 Node* context = NewNode(op, object); 2234 environment()->BindAccumulator(context); 2235} 2236 2237void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) { 2238 const Operator* op = javascript()->CreateArguments(type); 2239 Node* object = NewNode(op, GetFunctionClosure()); 2240 environment()->BindAccumulator(object, Environment::kAttachFrameState); 2241} 2242 2243void BytecodeGraphBuilder::VisitCreateMappedArguments() { 2244 BuildCreateArguments(CreateArgumentsType::kMappedArguments); 2245} 2246 2247void BytecodeGraphBuilder::VisitCreateUnmappedArguments() { 2248 BuildCreateArguments(CreateArgumentsType::kUnmappedArguments); 2249} 2250 2251void BytecodeGraphBuilder::VisitCreateRestParameter() { 2252 BuildCreateArguments(CreateArgumentsType::kRestParameter); 2253} 2254 2255void BytecodeGraphBuilder::VisitCreateRegExpLiteral() { 2256 StringRef constant_pattern = MakeRefForConstantForIndexOperand<String>(0); 2257 int const slot_id = bytecode_iterator().GetIndexOperand(1); 2258 FeedbackSource pair = CreateFeedbackSource(slot_id); 2259 int literal_flags = bytecode_iterator().GetFlagOperand(2); 2260 STATIC_ASSERT(JSCreateLiteralRegExpNode::FeedbackVectorIndex() == 0); 2261 const Operator* op = 2262 javascript()->CreateLiteralRegExp(constant_pattern, pair, literal_flags); 2263 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2264 Node* literal = NewNode(op, feedback_vector_node()); 2265 environment()->BindAccumulator(literal, Environment::kAttachFrameState); 2266} 2267 2268void BytecodeGraphBuilder::VisitCreateArrayLiteral() { 2269 ArrayBoilerplateDescriptionRef array_boilerplate_description = 2270 MakeRefForConstantForIndexOperand<ArrayBoilerplateDescription>(0); 2271 int const slot_id = bytecode_iterator().GetIndexOperand(1); 2272 FeedbackSource pair = CreateFeedbackSource(slot_id); 2273 int bytecode_flags = bytecode_iterator().GetFlagOperand(2); 2274 int literal_flags = 2275 interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags); 2276 // Disable allocation site mementos. Only unoptimized code will collect 2277 // feedback about allocation site. Once the code is optimized we expect the 2278 // data to converge. So, we disable allocation site mementos in optimized 2279 // code. We can revisit this when we have data to the contrary. 2280 literal_flags |= ArrayLiteral::kDisableMementos; 2281 int number_of_elements = 2282 array_boilerplate_description.constants_elements_length(); 2283 STATIC_ASSERT(JSCreateLiteralArrayNode::FeedbackVectorIndex() == 0); 2284 const Operator* op = javascript()->CreateLiteralArray( 2285 array_boilerplate_description, pair, literal_flags, number_of_elements); 2286 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2287 Node* literal = NewNode(op, feedback_vector_node()); 2288 environment()->BindAccumulator(literal, Environment::kAttachFrameState); 2289} 2290 2291void BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() { 2292 int const slot_id = bytecode_iterator().GetIndexOperand(0); 2293 FeedbackSource pair = CreateFeedbackSource(slot_id); 2294 const Operator* op = javascript()->CreateEmptyLiteralArray(pair); 2295 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2296 Node* literal = NewNode(op, feedback_vector_node()); 2297 environment()->BindAccumulator(literal); 2298} 2299 2300void BytecodeGraphBuilder::VisitCreateArrayFromIterable() { 2301 Node* iterable = NewNode(javascript()->CreateArrayFromIterable(), 2302 environment()->LookupAccumulator()); 2303 environment()->BindAccumulator(iterable, Environment::kAttachFrameState); 2304} 2305 2306void BytecodeGraphBuilder::VisitCreateObjectLiteral() { 2307 ObjectBoilerplateDescriptionRef constant_properties = 2308 MakeRefForConstantForIndexOperand<ObjectBoilerplateDescription>(0); 2309 int const slot_id = bytecode_iterator().GetIndexOperand(1); 2310 FeedbackSource pair = CreateFeedbackSource(slot_id); 2311 int bytecode_flags = bytecode_iterator().GetFlagOperand(2); 2312 int literal_flags = 2313 interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags); 2314 int number_of_properties = constant_properties.size(); 2315 STATIC_ASSERT(JSCreateLiteralObjectNode::FeedbackVectorIndex() == 0); 2316 const Operator* op = javascript()->CreateLiteralObject( 2317 constant_properties, pair, literal_flags, number_of_properties); 2318 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2319 Node* literal = NewNode(op, feedback_vector_node()); 2320 environment()->BindAccumulator(literal, Environment::kAttachFrameState); 2321} 2322 2323void BytecodeGraphBuilder::VisitCreateEmptyObjectLiteral() { 2324 Node* literal = NewNode(javascript()->CreateEmptyLiteralObject()); 2325 environment()->BindAccumulator(literal); 2326} 2327 2328void BytecodeGraphBuilder::VisitCloneObject() { 2329 PrepareEagerCheckpoint(); 2330 Node* source = 2331 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2332 int flags = bytecode_iterator().GetFlagOperand(1); 2333 int slot = bytecode_iterator().GetIndexOperand(2); 2334 const Operator* op = 2335 javascript()->CloneObject(CreateFeedbackSource(slot), flags); 2336 STATIC_ASSERT(JSCloneObjectNode::SourceIndex() == 0); 2337 STATIC_ASSERT(JSCloneObjectNode::FeedbackVectorIndex() == 1); 2338 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2339 Node* value = NewNode(op, source, feedback_vector_node()); 2340 environment()->BindAccumulator(value, Environment::kAttachFrameState); 2341} 2342 2343void BytecodeGraphBuilder::VisitGetTemplateObject() { 2344 FeedbackSource source = 2345 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 2346 TemplateObjectDescriptionRef description = 2347 MakeRefForConstantForIndexOperand<TemplateObjectDescription>(0); 2348 STATIC_ASSERT(JSGetTemplateObjectNode::FeedbackVectorIndex() == 0); 2349 const Operator* op = 2350 javascript()->GetTemplateObject(description, shared_info(), source); 2351 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2352 Node* template_object = NewNode(op, feedback_vector_node()); 2353 environment()->BindAccumulator(template_object); 2354} 2355 2356Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters( 2357 Node* callee, Node* receiver, interpreter::Register first_arg, 2358 int arg_count) { 2359 const int arity = JSCallNode::ArityForArgc(arg_count); 2360 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); 2361 int cursor = 0; 2362 2363 STATIC_ASSERT(JSCallNode::TargetIndex() == 0); 2364 STATIC_ASSERT(JSCallNode::ReceiverIndex() == 1); 2365 STATIC_ASSERT(JSCallNode::FirstArgumentIndex() == 2); 2366 STATIC_ASSERT(JSCallNode::kFeedbackVectorIsLastInput); 2367 2368 all[cursor++] = callee; 2369 all[cursor++] = receiver; 2370 2371 // The function arguments are in consecutive registers. 2372 const int arg_base = first_arg.index(); 2373 for (int i = 0; i < arg_count; ++i) { 2374 all[cursor++] = 2375 environment()->LookupRegister(interpreter::Register(arg_base + i)); 2376 } 2377 2378 all[cursor++] = feedback_vector_node(); 2379 2380 DCHECK_EQ(cursor, arity); 2381 return all; 2382} 2383 2384void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode, 2385 Node* const* args, size_t arg_count, 2386 int slot_id) { 2387 DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode( 2388 bytecode_iterator().current_bytecode()), 2389 receiver_mode); 2390 PrepareEagerCheckpoint(); 2391 2392 FeedbackSource feedback = CreateFeedbackSource(slot_id); 2393 CallFrequency frequency = ComputeCallFrequency(slot_id); 2394 SpeculationMode speculation_mode = GetSpeculationMode(slot_id); 2395 CallFeedbackRelation call_feedback_relation = 2396 ComputeCallFeedbackRelation(slot_id); 2397 const Operator* op = 2398 javascript()->Call(arg_count, frequency, feedback, receiver_mode, 2399 speculation_mode, call_feedback_relation); 2400 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2401 2402 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall( 2403 op, args, static_cast<int>(arg_count), feedback.slot); 2404 if (lowering.IsExit()) return; 2405 2406 Node* node = nullptr; 2407 if (lowering.IsSideEffectFree()) { 2408 node = lowering.value(); 2409 } else { 2410 DCHECK(!lowering.Changed()); 2411 node = MakeNode(op, static_cast<int>(arg_count), args); 2412 } 2413 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2414} 2415 2416Node* const* BytecodeGraphBuilder::ProcessCallVarArgs( 2417 ConvertReceiverMode receiver_mode, Node* callee, 2418 interpreter::Register first_reg, int arg_count) { 2419 DCHECK_GE(arg_count, 0); 2420 Node* receiver_node; 2421 interpreter::Register first_arg; 2422 2423 if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { 2424 // The receiver is implicit (and undefined), the arguments are in 2425 // consecutive registers. 2426 receiver_node = jsgraph()->UndefinedConstant(); 2427 first_arg = first_reg; 2428 } else { 2429 // The receiver is the first register, followed by the arguments in the 2430 // consecutive registers. 2431 receiver_node = environment()->LookupRegister(first_reg); 2432 first_arg = interpreter::Register(first_reg.index() + 1); 2433 } 2434 2435 Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node, 2436 first_arg, arg_count); 2437 return call_args; 2438} 2439 2440void BytecodeGraphBuilder::BuildCallVarArgs(ConvertReceiverMode receiver_mode) { 2441 DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode( 2442 bytecode_iterator().current_bytecode()), 2443 receiver_mode); 2444 Node* callee = 2445 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2446 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 2447 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2448 int const slot_id = bytecode_iterator().GetIndexOperand(3); 2449 2450 int arg_count = receiver_mode == ConvertReceiverMode::kNullOrUndefined 2451 ? static_cast<int>(reg_count) 2452 : static_cast<int>(reg_count) - 1; 2453 Node* const* call_args = 2454 ProcessCallVarArgs(receiver_mode, callee, first_reg, arg_count); 2455 BuildCall(receiver_mode, call_args, JSCallNode::ArityForArgc(arg_count), 2456 slot_id); 2457} 2458 2459void BytecodeGraphBuilder::VisitCallAnyReceiver() { 2460 BuildCallVarArgs(ConvertReceiverMode::kAny); 2461} 2462 2463void BytecodeGraphBuilder::VisitCallProperty() { 2464 BuildCallVarArgs(ConvertReceiverMode::kNotNullOrUndefined); 2465} 2466 2467void BytecodeGraphBuilder::VisitCallProperty0() { 2468 Node* callee = 2469 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2470 Node* receiver = 2471 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 2472 int const slot_id = bytecode_iterator().GetIndexOperand(2); 2473 BuildCall(ConvertReceiverMode::kNotNullOrUndefined, 2474 {callee, receiver, feedback_vector_node()}, slot_id); 2475} 2476 2477void BytecodeGraphBuilder::VisitCallProperty1() { 2478 Node* callee = 2479 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2480 Node* receiver = 2481 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 2482 Node* arg0 = 2483 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); 2484 int const slot_id = bytecode_iterator().GetIndexOperand(3); 2485 BuildCall(ConvertReceiverMode::kNotNullOrUndefined, 2486 {callee, receiver, arg0, feedback_vector_node()}, slot_id); 2487} 2488 2489void BytecodeGraphBuilder::VisitCallProperty2() { 2490 Node* callee = 2491 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2492 Node* receiver = 2493 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 2494 Node* arg0 = 2495 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); 2496 Node* arg1 = 2497 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3)); 2498 int const slot_id = bytecode_iterator().GetIndexOperand(4); 2499 BuildCall(ConvertReceiverMode::kNotNullOrUndefined, 2500 {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id); 2501} 2502 2503void BytecodeGraphBuilder::VisitCallUndefinedReceiver() { 2504 BuildCallVarArgs(ConvertReceiverMode::kNullOrUndefined); 2505} 2506 2507void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() { 2508 Node* callee = 2509 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2510 Node* receiver = jsgraph()->UndefinedConstant(); 2511 int const slot_id = bytecode_iterator().GetIndexOperand(1); 2512 BuildCall(ConvertReceiverMode::kNullOrUndefined, 2513 {callee, receiver, feedback_vector_node()}, slot_id); 2514} 2515 2516void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() { 2517 Node* callee = 2518 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2519 Node* receiver = jsgraph()->UndefinedConstant(); 2520 Node* arg0 = 2521 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 2522 int const slot_id = bytecode_iterator().GetIndexOperand(2); 2523 BuildCall(ConvertReceiverMode::kNullOrUndefined, 2524 {callee, receiver, arg0, feedback_vector_node()}, slot_id); 2525} 2526 2527void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() { 2528 Node* callee = 2529 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2530 Node* receiver = jsgraph()->UndefinedConstant(); 2531 Node* arg0 = 2532 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 2533 Node* arg1 = 2534 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); 2535 int const slot_id = bytecode_iterator().GetIndexOperand(3); 2536 BuildCall(ConvertReceiverMode::kNullOrUndefined, 2537 {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id); 2538} 2539 2540void BytecodeGraphBuilder::VisitCallWithSpread() { 2541 PrepareEagerCheckpoint(); 2542 Node* callee = 2543 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2544 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 2545 Node* receiver_node = environment()->LookupRegister(receiver); 2546 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2547 interpreter::Register first_arg = interpreter::Register(receiver.index() + 1); 2548 int arg_count = static_cast<int>(reg_count) - 1; 2549 Node* const* args = GetCallArgumentsFromRegisters(callee, receiver_node, 2550 first_arg, arg_count); 2551 int const slot_id = bytecode_iterator().GetIndexOperand(3); 2552 FeedbackSource feedback = CreateFeedbackSource(slot_id); 2553 CallFrequency frequency = ComputeCallFrequency(slot_id); 2554 SpeculationMode speculation_mode = GetSpeculationMode(slot_id); 2555 const Operator* op = javascript()->CallWithSpread( 2556 JSCallWithSpreadNode::ArityForArgc(arg_count), frequency, feedback, 2557 speculation_mode); 2558 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2559 2560 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall( 2561 op, args, static_cast<int>(arg_count), feedback.slot); 2562 if (lowering.IsExit()) return; 2563 2564 Node* node = nullptr; 2565 if (lowering.IsSideEffectFree()) { 2566 node = lowering.value(); 2567 } else { 2568 DCHECK(!lowering.Changed()); 2569 node = MakeNode(op, JSCallWithSpreadNode::ArityForArgc(arg_count), args); 2570 } 2571 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2572} 2573 2574void BytecodeGraphBuilder::VisitCallJSRuntime() { 2575 PrepareEagerCheckpoint(); 2576 Node* callee = BuildLoadNativeContextField( 2577 bytecode_iterator().GetNativeContextIndexOperand(0)); 2578 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 2579 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2580 int arg_count = static_cast<int>(reg_count); 2581 int arity = JSCallNode::ArityForArgc(arg_count); 2582 2583 const Operator* call = javascript()->Call(arity); 2584 Node* const* call_args = ProcessCallVarArgs( 2585 ConvertReceiverMode::kNullOrUndefined, callee, first_reg, arg_count); 2586 Node* value = MakeNode(call, arity, call_args); 2587 environment()->BindAccumulator(value, Environment::kAttachFrameState); 2588} 2589 2590Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( 2591 const Operator* call_runtime_op, interpreter::Register receiver, 2592 size_t reg_count) { 2593 int arg_count = static_cast<int>(reg_count); 2594 // arity is args. 2595 int arity = arg_count; 2596 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); 2597 int first_arg_index = receiver.index(); 2598 for (int i = 0; i < static_cast<int>(reg_count); ++i) { 2599 all[i] = environment()->LookupRegister( 2600 interpreter::Register(first_arg_index + i)); 2601 } 2602 Node* value = MakeNode(call_runtime_op, arity, all); 2603 return value; 2604} 2605 2606void BytecodeGraphBuilder::VisitCallRuntime() { 2607 PrepareEagerCheckpoint(); 2608 Runtime::FunctionId function_id = bytecode_iterator().GetRuntimeIdOperand(0); 2609 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 2610 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2611 2612 // Handle %ObserveNode here (rather than in JSIntrinsicLowering) to observe 2613 // the node as early as possible. 2614 if (function_id == Runtime::FunctionId::kObserveNode) { 2615 DCHECK_EQ(1, reg_count); 2616 Node* value = environment()->LookupRegister(receiver); 2617 observe_node_info_.StartObserving(value); 2618 environment()->BindAccumulator(value); 2619 } else { 2620 // Create node to perform the runtime call. 2621 const Operator* call = javascript()->CallRuntime(function_id, reg_count); 2622 Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); 2623 environment()->BindAccumulator(value, Environment::kAttachFrameState); 2624 2625 // Connect to the end if {function_id} is non-returning. 2626 if (Runtime::IsNonReturning(function_id)) { 2627 // TODO(7099): Investigate if we need LoopExit node here. 2628 Node* control = NewNode(common()->Throw()); 2629 MergeControlToLeaveFunction(control); 2630 } 2631 } 2632} 2633 2634void BytecodeGraphBuilder::VisitCallRuntimeForPair() { 2635 PrepareEagerCheckpoint(); 2636 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); 2637 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 2638 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2639 interpreter::Register first_return = 2640 bytecode_iterator().GetRegisterOperand(3); 2641 2642 // Create node to perform the runtime call. 2643 const Operator* call = javascript()->CallRuntime(functionId, reg_count); 2644 Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count); 2645 environment()->BindRegistersToProjections(first_return, return_pair, 2646 Environment::kAttachFrameState); 2647} 2648 2649Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister( 2650 Node* target, Node* new_target, interpreter::Register first_arg, 2651 int arg_count) { 2652 const int arity = JSConstructNode::ArityForArgc(arg_count); 2653 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); 2654 int cursor = 0; 2655 2656 STATIC_ASSERT(JSConstructNode::TargetIndex() == 0); 2657 STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1); 2658 STATIC_ASSERT(JSConstructNode::FirstArgumentIndex() == 2); 2659 STATIC_ASSERT(JSConstructNode::kFeedbackVectorIsLastInput); 2660 2661 all[cursor++] = target; 2662 all[cursor++] = new_target; 2663 2664 // The function arguments are in consecutive registers. 2665 int arg_base = first_arg.index(); 2666 for (int i = 0; i < arg_count; ++i) { 2667 all[cursor++] = 2668 environment()->LookupRegister(interpreter::Register(arg_base + i)); 2669 } 2670 2671 all[cursor++] = feedback_vector_node(); 2672 2673 DCHECK_EQ(cursor, arity); 2674 return all; 2675} 2676 2677void BytecodeGraphBuilder::VisitConstruct() { 2678 PrepareEagerCheckpoint(); 2679 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); 2680 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 2681 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2682 int const slot_id = bytecode_iterator().GetIndexOperand(3); 2683 FeedbackSource feedback = CreateFeedbackSource(slot_id); 2684 2685 Node* new_target = environment()->LookupAccumulator(); 2686 Node* callee = environment()->LookupRegister(callee_reg); 2687 2688 CallFrequency frequency = ComputeCallFrequency(slot_id); 2689 const uint32_t arg_count = static_cast<uint32_t>(reg_count); 2690 const uint32_t arity = JSConstructNode::ArityForArgc(arg_count); 2691 const Operator* op = javascript()->Construct(arity, frequency, feedback); 2692 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2693 Node* const* args = GetConstructArgumentsFromRegister(callee, new_target, 2694 first_reg, arg_count); 2695 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct( 2696 op, args, static_cast<int>(arg_count), feedback.slot); 2697 if (lowering.IsExit()) return; 2698 2699 Node* node = nullptr; 2700 if (lowering.IsSideEffectFree()) { 2701 node = lowering.value(); 2702 } else { 2703 DCHECK(!lowering.Changed()); 2704 node = MakeNode(op, arity, args); 2705 } 2706 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2707} 2708 2709void BytecodeGraphBuilder::VisitConstructWithSpread() { 2710 PrepareEagerCheckpoint(); 2711 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); 2712 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 2713 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2714 int const slot_id = bytecode_iterator().GetIndexOperand(3); 2715 FeedbackSource feedback = CreateFeedbackSource(slot_id); 2716 2717 Node* new_target = environment()->LookupAccumulator(); 2718 Node* callee = environment()->LookupRegister(callee_reg); 2719 2720 CallFrequency frequency = ComputeCallFrequency(slot_id); 2721 const uint32_t arg_count = static_cast<uint32_t>(reg_count); 2722 const uint32_t arity = JSConstructNode::ArityForArgc(arg_count); 2723 const Operator* op = 2724 javascript()->ConstructWithSpread(arity, frequency, feedback); 2725 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2726 Node* const* args = GetConstructArgumentsFromRegister(callee, new_target, 2727 first_reg, arg_count); 2728 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct( 2729 op, args, static_cast<int>(arg_count), feedback.slot); 2730 if (lowering.IsExit()) return; 2731 2732 Node* node = nullptr; 2733 if (lowering.IsSideEffectFree()) { 2734 node = lowering.value(); 2735 } else { 2736 DCHECK(!lowering.Changed()); 2737 node = MakeNode(op, arity, args); 2738 } 2739 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2740} 2741 2742void BytecodeGraphBuilder::VisitInvokeIntrinsic() { 2743 PrepareEagerCheckpoint(); 2744 Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); 2745 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 2746 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 2747 2748 // Create node to perform the runtime call. Turbofan will take care of the 2749 // lowering. 2750 const Operator* call = javascript()->CallRuntime(functionId, reg_count); 2751 Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); 2752 environment()->BindAccumulator(value, Environment::kAttachFrameState); 2753} 2754 2755void BytecodeGraphBuilder::VisitThrow() { 2756 BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 2757 bytecode_iterator().current_offset())); 2758 Node* value = environment()->LookupAccumulator(); 2759 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); 2760 environment()->BindAccumulator(call, Environment::kAttachFrameState); 2761 Node* control = NewNode(common()->Throw()); 2762 MergeControlToLeaveFunction(control); 2763} 2764 2765void BytecodeGraphBuilder::VisitAbort() { 2766 BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 2767 bytecode_iterator().current_offset())); 2768 AbortReason reason = 2769 static_cast<AbortReason>(bytecode_iterator().GetIndexOperand(0)); 2770 NewNode(simplified()->RuntimeAbort(reason)); 2771 Node* control = NewNode(common()->Throw()); 2772 MergeControlToLeaveFunction(control); 2773} 2774 2775void BytecodeGraphBuilder::VisitReThrow() { 2776 BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 2777 bytecode_iterator().current_offset())); 2778 Node* value = environment()->LookupAccumulator(); 2779 NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); 2780 Node* control = NewNode(common()->Throw()); 2781 MergeControlToLeaveFunction(control); 2782} 2783 2784void BytecodeGraphBuilder::BuildHoleCheckAndThrow( 2785 Node* condition, Runtime::FunctionId runtime_id, Node* name) { 2786 Node* accumulator = environment()->LookupAccumulator(); 2787 NewBranch(condition, BranchHint::kFalse); 2788 { 2789 SubEnvironment sub_environment(this); 2790 2791 NewIfTrue(); 2792 BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 2793 bytecode_iterator().current_offset())); 2794 Node* node; 2795 const Operator* op = javascript()->CallRuntime(runtime_id); 2796 if (runtime_id == Runtime::kThrowAccessedUninitializedVariable) { 2797 DCHECK_NOT_NULL(name); 2798 node = NewNode(op, name); 2799 } else { 2800 DCHECK(runtime_id == Runtime::kThrowSuperAlreadyCalledError || 2801 runtime_id == Runtime::kThrowSuperNotCalled); 2802 node = NewNode(op); 2803 } 2804 environment()->RecordAfterState(node, Environment::kAttachFrameState); 2805 Node* control = NewNode(common()->Throw()); 2806 MergeControlToLeaveFunction(control); 2807 } 2808 NewIfFalse(); 2809 environment()->BindAccumulator(accumulator); 2810} 2811 2812void BytecodeGraphBuilder::VisitThrowReferenceErrorIfHole() { 2813 Node* accumulator = environment()->LookupAccumulator(); 2814 Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator, 2815 jsgraph()->TheHoleConstant()); 2816 Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 2817 BuildHoleCheckAndThrow(check_for_hole, 2818 Runtime::kThrowAccessedUninitializedVariable, name); 2819} 2820 2821void BytecodeGraphBuilder::VisitThrowSuperNotCalledIfHole() { 2822 Node* accumulator = environment()->LookupAccumulator(); 2823 Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator, 2824 jsgraph()->TheHoleConstant()); 2825 BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowSuperNotCalled); 2826} 2827 2828void BytecodeGraphBuilder::VisitThrowSuperAlreadyCalledIfNotHole() { 2829 Node* accumulator = environment()->LookupAccumulator(); 2830 Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator, 2831 jsgraph()->TheHoleConstant()); 2832 Node* check_for_not_hole = 2833 NewNode(simplified()->BooleanNot(), check_for_hole); 2834 BuildHoleCheckAndThrow(check_for_not_hole, 2835 Runtime::kThrowSuperAlreadyCalledError); 2836} 2837 2838void BytecodeGraphBuilder::VisitThrowIfNotSuperConstructor() { 2839 Node* constructor = 2840 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2841 Node* check_is_constructor = 2842 NewNode(simplified()->ObjectIsConstructor(), constructor); 2843 NewBranch(check_is_constructor, BranchHint::kTrue); 2844 { 2845 SubEnvironment sub_environment(this); 2846 NewIfFalse(); 2847 BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 2848 bytecode_iterator().current_offset())); 2849 Node* node = 2850 NewNode(javascript()->CallRuntime(Runtime::kThrowNotSuperConstructor), 2851 constructor, GetFunctionClosure()); 2852 environment()->RecordAfterState(node, Environment::kAttachFrameState); 2853 Node* control = NewNode(common()->Throw()); 2854 MergeControlToLeaveFunction(control); 2855 } 2856 NewIfTrue(); 2857 2858 constructor = NewNode(common()->TypeGuard(Type::Callable()), constructor); 2859 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), 2860 constructor); 2861} 2862 2863void BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) { 2864 DCHECK(JSOperator::IsUnaryWithFeedback(op->opcode())); 2865 PrepareEagerCheckpoint(); 2866 Node* operand = environment()->LookupAccumulator(); 2867 2868 FeedbackSlot slot = 2869 bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex); 2870 JSTypeHintLowering::LoweringResult lowering = 2871 TryBuildSimplifiedUnaryOp(op, operand, slot); 2872 if (lowering.IsExit()) return; 2873 2874 Node* node = nullptr; 2875 if (lowering.IsSideEffectFree()) { 2876 node = lowering.value(); 2877 } else { 2878 DCHECK(!lowering.Changed()); 2879 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2880 node = NewNode(op, operand, feedback_vector_node()); 2881 } 2882 2883 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2884} 2885 2886void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) { 2887 DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode())); 2888 PrepareEagerCheckpoint(); 2889 Node* left = 2890 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 2891 Node* right = environment()->LookupAccumulator(); 2892 2893 FeedbackSlot slot = 2894 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex); 2895 JSTypeHintLowering::LoweringResult lowering = 2896 TryBuildSimplifiedBinaryOp(op, left, right, slot); 2897 if (lowering.IsExit()) return; 2898 2899 Node* node = nullptr; 2900 if (lowering.IsSideEffectFree()) { 2901 node = lowering.value(); 2902 } else { 2903 DCHECK(!lowering.Changed()); 2904 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 2905 node = NewNode(op, left, right, feedback_vector_node()); 2906 } 2907 2908 environment()->BindAccumulator(node, Environment::kAttachFrameState); 2909} 2910 2911// Helper function to create for-in mode from the recorded type feedback. 2912ForInMode BytecodeGraphBuilder::GetForInMode(FeedbackSlot slot) { 2913 FeedbackSource source(feedback_vector(), slot); 2914 switch (broker()->GetFeedbackForForIn(source)) { 2915 case ForInHint::kNone: 2916 case ForInHint::kEnumCacheKeysAndIndices: 2917 return ForInMode::kUseEnumCacheKeysAndIndices; 2918 case ForInHint::kEnumCacheKeys: 2919 return ForInMode::kUseEnumCacheKeys; 2920 case ForInHint::kAny: 2921 return ForInMode::kGeneric; 2922 } 2923 UNREACHABLE(); 2924} 2925 2926CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const { 2927 if (invocation_frequency_.IsUnknown()) return CallFrequency(); 2928 FeedbackSlot slot = FeedbackVector::ToSlot(slot_id); 2929 FeedbackSource source(feedback_vector(), slot); 2930 ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source); 2931 float feedback_frequency = 2932 feedback.IsInsufficient() ? 0.0f : feedback.AsCall().frequency(); 2933 if (feedback_frequency == 0.0f) { // Prevent multiplying zero and infinity. 2934 return CallFrequency(0.0f); 2935 } else { 2936 return CallFrequency(feedback_frequency * invocation_frequency_.value()); 2937 } 2938} 2939 2940SpeculationMode BytecodeGraphBuilder::GetSpeculationMode(int slot_id) const { 2941 FeedbackSlot slot = FeedbackVector::ToSlot(slot_id); 2942 FeedbackSource source(feedback_vector(), slot); 2943 ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source); 2944 return feedback.IsInsufficient() ? SpeculationMode::kDisallowSpeculation 2945 : feedback.AsCall().speculation_mode(); 2946} 2947 2948CallFeedbackRelation BytecodeGraphBuilder::ComputeCallFeedbackRelation( 2949 int slot_id) const { 2950 FeedbackSlot slot = FeedbackVector::ToSlot(slot_id); 2951 FeedbackSource source(feedback_vector(), slot); 2952 ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source); 2953 if (feedback.IsInsufficient()) return CallFeedbackRelation::kUnrelated; 2954 CallFeedbackContent call_feedback_content = 2955 feedback.AsCall().call_feedback_content(); 2956 return call_feedback_content == CallFeedbackContent::kTarget 2957 ? CallFeedbackRelation::kTarget 2958 : CallFeedbackRelation::kReceiver; 2959} 2960 2961void BytecodeGraphBuilder::VisitBitwiseNot() { 2962 FeedbackSource feedback = CreateFeedbackSource( 2963 bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 2964 BuildUnaryOp(javascript()->BitwiseNot(feedback)); 2965} 2966 2967void BytecodeGraphBuilder::VisitDec() { 2968 FeedbackSource feedback = CreateFeedbackSource( 2969 bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 2970 BuildUnaryOp(javascript()->Decrement(feedback)); 2971} 2972 2973void BytecodeGraphBuilder::VisitInc() { 2974 FeedbackSource feedback = CreateFeedbackSource( 2975 bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 2976 BuildUnaryOp(javascript()->Increment(feedback)); 2977} 2978 2979void BytecodeGraphBuilder::VisitNegate() { 2980 FeedbackSource feedback = CreateFeedbackSource( 2981 bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 2982 BuildUnaryOp(javascript()->Negate(feedback)); 2983} 2984 2985void BytecodeGraphBuilder::VisitAdd() { 2986 FeedbackSource feedback = CreateFeedbackSource( 2987 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 2988 BuildBinaryOp(javascript()->Add(feedback)); 2989} 2990 2991void BytecodeGraphBuilder::VisitSub() { 2992 FeedbackSource feedback = CreateFeedbackSource( 2993 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 2994 BuildBinaryOp(javascript()->Subtract(feedback)); 2995} 2996 2997void BytecodeGraphBuilder::VisitMul() { 2998 FeedbackSource feedback = CreateFeedbackSource( 2999 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3000 BuildBinaryOp(javascript()->Multiply(feedback)); 3001} 3002 3003void BytecodeGraphBuilder::VisitDiv() { 3004 FeedbackSource feedback = CreateFeedbackSource( 3005 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3006 BuildBinaryOp(javascript()->Divide(feedback)); 3007} 3008 3009void BytecodeGraphBuilder::VisitMod() { 3010 FeedbackSource feedback = CreateFeedbackSource( 3011 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3012 BuildBinaryOp(javascript()->Modulus(feedback)); 3013} 3014 3015void BytecodeGraphBuilder::VisitExp() { 3016 FeedbackSource feedback = CreateFeedbackSource( 3017 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3018 BuildBinaryOp(javascript()->Exponentiate(feedback)); 3019} 3020 3021void BytecodeGraphBuilder::VisitBitwiseOr() { 3022 FeedbackSource feedback = CreateFeedbackSource( 3023 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3024 BuildBinaryOp(javascript()->BitwiseOr(feedback)); 3025} 3026 3027void BytecodeGraphBuilder::VisitBitwiseXor() { 3028 FeedbackSource feedback = CreateFeedbackSource( 3029 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3030 BuildBinaryOp(javascript()->BitwiseXor(feedback)); 3031} 3032 3033void BytecodeGraphBuilder::VisitBitwiseAnd() { 3034 FeedbackSource feedback = CreateFeedbackSource( 3035 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3036 BuildBinaryOp(javascript()->BitwiseAnd(feedback)); 3037} 3038 3039void BytecodeGraphBuilder::VisitShiftLeft() { 3040 FeedbackSource feedback = CreateFeedbackSource( 3041 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3042 BuildBinaryOp(javascript()->ShiftLeft(feedback)); 3043} 3044 3045void BytecodeGraphBuilder::VisitShiftRight() { 3046 FeedbackSource feedback = CreateFeedbackSource( 3047 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3048 BuildBinaryOp(javascript()->ShiftRight(feedback)); 3049} 3050 3051void BytecodeGraphBuilder::VisitShiftRightLogical() { 3052 FeedbackSource feedback = CreateFeedbackSource( 3053 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 3054 BuildBinaryOp(javascript()->ShiftRightLogical(feedback)); 3055} 3056 3057void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) { 3058 DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode())); 3059 PrepareEagerCheckpoint(); 3060 Node* left = environment()->LookupAccumulator(); 3061 Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 3062 3063 FeedbackSlot slot = 3064 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex); 3065 JSTypeHintLowering::LoweringResult lowering = 3066 TryBuildSimplifiedBinaryOp(op, left, right, slot); 3067 if (lowering.IsExit()) return; 3068 3069 Node* node = nullptr; 3070 if (lowering.IsSideEffectFree()) { 3071 node = lowering.value(); 3072 } else { 3073 DCHECK(!lowering.Changed()); 3074 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 3075 node = NewNode(op, left, right, feedback_vector_node()); 3076 } 3077 environment()->BindAccumulator(node, Environment::kAttachFrameState); 3078} 3079 3080void BytecodeGraphBuilder::VisitAddSmi() { 3081 FeedbackSource feedback = CreateFeedbackSource( 3082 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3083 BuildBinaryOpWithImmediate(javascript()->Add(feedback)); 3084} 3085 3086void BytecodeGraphBuilder::VisitSubSmi() { 3087 FeedbackSource feedback = CreateFeedbackSource( 3088 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3089 BuildBinaryOpWithImmediate(javascript()->Subtract(feedback)); 3090} 3091 3092void BytecodeGraphBuilder::VisitMulSmi() { 3093 FeedbackSource feedback = CreateFeedbackSource( 3094 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3095 BuildBinaryOpWithImmediate(javascript()->Multiply(feedback)); 3096} 3097 3098void BytecodeGraphBuilder::VisitDivSmi() { 3099 FeedbackSource feedback = CreateFeedbackSource( 3100 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3101 BuildBinaryOpWithImmediate(javascript()->Divide(feedback)); 3102} 3103 3104void BytecodeGraphBuilder::VisitModSmi() { 3105 FeedbackSource feedback = CreateFeedbackSource( 3106 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3107 BuildBinaryOpWithImmediate(javascript()->Modulus(feedback)); 3108} 3109 3110void BytecodeGraphBuilder::VisitExpSmi() { 3111 FeedbackSource feedback = CreateFeedbackSource( 3112 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3113 BuildBinaryOpWithImmediate(javascript()->Exponentiate(feedback)); 3114} 3115 3116void BytecodeGraphBuilder::VisitBitwiseOrSmi() { 3117 FeedbackSource feedback = CreateFeedbackSource( 3118 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3119 BuildBinaryOpWithImmediate(javascript()->BitwiseOr(feedback)); 3120} 3121 3122void BytecodeGraphBuilder::VisitBitwiseXorSmi() { 3123 FeedbackSource feedback = CreateFeedbackSource( 3124 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3125 BuildBinaryOpWithImmediate(javascript()->BitwiseXor(feedback)); 3126} 3127 3128void BytecodeGraphBuilder::VisitBitwiseAndSmi() { 3129 FeedbackSource feedback = CreateFeedbackSource( 3130 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3131 BuildBinaryOpWithImmediate(javascript()->BitwiseAnd(feedback)); 3132} 3133 3134void BytecodeGraphBuilder::VisitShiftLeftSmi() { 3135 FeedbackSource feedback = CreateFeedbackSource( 3136 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3137 BuildBinaryOpWithImmediate(javascript()->ShiftLeft(feedback)); 3138} 3139 3140void BytecodeGraphBuilder::VisitShiftRightSmi() { 3141 FeedbackSource feedback = CreateFeedbackSource( 3142 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3143 BuildBinaryOpWithImmediate(javascript()->ShiftRight(feedback)); 3144} 3145 3146void BytecodeGraphBuilder::VisitShiftRightLogicalSmi() { 3147 FeedbackSource feedback = CreateFeedbackSource( 3148 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 3149 BuildBinaryOpWithImmediate(javascript()->ShiftRightLogical(feedback)); 3150} 3151 3152void BytecodeGraphBuilder::VisitLogicalNot() { 3153 Node* value = environment()->LookupAccumulator(); 3154 Node* node = NewNode(simplified()->BooleanNot(), value); 3155 environment()->BindAccumulator(node); 3156} 3157 3158void BytecodeGraphBuilder::VisitToBooleanLogicalNot() { 3159 Node* value = 3160 NewNode(simplified()->ToBoolean(), environment()->LookupAccumulator()); 3161 Node* node = NewNode(simplified()->BooleanNot(), value); 3162 environment()->BindAccumulator(node); 3163} 3164 3165void BytecodeGraphBuilder::VisitTypeOf() { 3166 Node* node = 3167 NewNode(simplified()->TypeOf(), environment()->LookupAccumulator()); 3168 environment()->BindAccumulator(node); 3169} 3170 3171void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) { 3172 PrepareEagerCheckpoint(); 3173 Node* key = environment()->LookupAccumulator(); 3174 Node* object = 3175 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3176 Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode)); 3177 Node* node = NewNode(javascript()->DeleteProperty(), object, key, mode); 3178 environment()->BindAccumulator(node, Environment::kAttachFrameState); 3179} 3180 3181void BytecodeGraphBuilder::VisitDeletePropertyStrict() { 3182 BuildDelete(LanguageMode::kStrict); 3183} 3184 3185void BytecodeGraphBuilder::VisitDeletePropertySloppy() { 3186 BuildDelete(LanguageMode::kSloppy); 3187} 3188 3189void BytecodeGraphBuilder::VisitGetSuperConstructor() { 3190 Node* node = NewNode(javascript()->GetSuperConstructor(), 3191 environment()->LookupAccumulator()); 3192 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node, 3193 Environment::kAttachFrameState); 3194} 3195 3196void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) { 3197 DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode())); 3198 PrepareEagerCheckpoint(); 3199 Node* left = 3200 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3201 Node* right = environment()->LookupAccumulator(); 3202 3203 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1); 3204 JSTypeHintLowering::LoweringResult lowering = 3205 TryBuildSimplifiedBinaryOp(op, left, right, slot); 3206 if (lowering.IsExit()) return; 3207 3208 Node* node = nullptr; 3209 if (lowering.IsSideEffectFree()) { 3210 node = lowering.value(); 3211 } else { 3212 DCHECK(!lowering.Changed()); 3213 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 3214 node = NewNode(op, left, right, feedback_vector_node()); 3215 } 3216 environment()->BindAccumulator(node, Environment::kAttachFrameState); 3217} 3218 3219void BytecodeGraphBuilder::VisitTestEqual() { 3220 FeedbackSource feedback = CreateFeedbackSource( 3221 bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 3222 BuildCompareOp(javascript()->Equal(feedback)); 3223} 3224 3225void BytecodeGraphBuilder::VisitTestEqualStrict() { 3226 FeedbackSource feedback = CreateFeedbackSource( 3227 bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 3228 BuildCompareOp(javascript()->StrictEqual(feedback)); 3229} 3230 3231void BytecodeGraphBuilder::VisitTestLessThan() { 3232 FeedbackSource feedback = CreateFeedbackSource( 3233 bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 3234 BuildCompareOp(javascript()->LessThan(feedback)); 3235} 3236 3237void BytecodeGraphBuilder::VisitTestGreaterThan() { 3238 FeedbackSource feedback = CreateFeedbackSource( 3239 bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 3240 BuildCompareOp(javascript()->GreaterThan(feedback)); 3241} 3242 3243void BytecodeGraphBuilder::VisitTestLessThanOrEqual() { 3244 FeedbackSource feedback = CreateFeedbackSource( 3245 bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 3246 BuildCompareOp(javascript()->LessThanOrEqual(feedback)); 3247} 3248 3249void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() { 3250 FeedbackSource feedback = CreateFeedbackSource( 3251 bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 3252 BuildCompareOp(javascript()->GreaterThanOrEqual(feedback)); 3253} 3254 3255void BytecodeGraphBuilder::VisitTestReferenceEqual() { 3256 Node* left = 3257 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3258 Node* right = environment()->LookupAccumulator(); 3259 Node* result = NewNode(simplified()->ReferenceEqual(), left, right); 3260 environment()->BindAccumulator(result); 3261} 3262 3263void BytecodeGraphBuilder::VisitTestIn() { 3264 PrepareEagerCheckpoint(); 3265 Node* object = environment()->LookupAccumulator(); 3266 Node* key = 3267 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3268 FeedbackSource feedback = 3269 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 3270 STATIC_ASSERT(JSHasPropertyNode::ObjectIndex() == 0); 3271 STATIC_ASSERT(JSHasPropertyNode::KeyIndex() == 1); 3272 STATIC_ASSERT(JSHasPropertyNode::FeedbackVectorIndex() == 2); 3273 const Operator* op = javascript()->HasProperty(feedback); 3274 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 3275 Node* node = NewNode(op, object, key, feedback_vector_node()); 3276 environment()->BindAccumulator(node, Environment::kAttachFrameState); 3277} 3278 3279void BytecodeGraphBuilder::VisitTestInstanceOf() { 3280 FeedbackSource feedback = CreateFeedbackSource( 3281 bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 3282 BuildCompareOp(javascript()->InstanceOf(feedback)); 3283} 3284 3285void BytecodeGraphBuilder::VisitTestUndetectable() { 3286 Node* object = environment()->LookupAccumulator(); 3287 Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object); 3288 environment()->BindAccumulator(node); 3289} 3290 3291void BytecodeGraphBuilder::VisitTestNull() { 3292 Node* object = environment()->LookupAccumulator(); 3293 Node* result = NewNode(simplified()->ReferenceEqual(), object, 3294 jsgraph()->NullConstant()); 3295 environment()->BindAccumulator(result); 3296} 3297 3298void BytecodeGraphBuilder::VisitTestUndefined() { 3299 Node* object = environment()->LookupAccumulator(); 3300 Node* result = NewNode(simplified()->ReferenceEqual(), object, 3301 jsgraph()->UndefinedConstant()); 3302 environment()->BindAccumulator(result); 3303} 3304 3305void BytecodeGraphBuilder::VisitTestTypeOf() { 3306 Node* object = environment()->LookupAccumulator(); 3307 auto literal_flag = interpreter::TestTypeOfFlags::Decode( 3308 bytecode_iterator().GetFlagOperand(0)); 3309 Node* result; 3310 switch (literal_flag) { 3311 case interpreter::TestTypeOfFlags::LiteralFlag::kNumber: 3312 result = NewNode(simplified()->ObjectIsNumber(), object); 3313 break; 3314 case interpreter::TestTypeOfFlags::LiteralFlag::kString: 3315 result = NewNode(simplified()->ObjectIsString(), object); 3316 break; 3317 case interpreter::TestTypeOfFlags::LiteralFlag::kSymbol: 3318 result = NewNode(simplified()->ObjectIsSymbol(), object); 3319 break; 3320 case interpreter::TestTypeOfFlags::LiteralFlag::kBigInt: 3321 result = NewNode(simplified()->ObjectIsBigInt(), object); 3322 break; 3323 case interpreter::TestTypeOfFlags::LiteralFlag::kBoolean: 3324 result = NewNode(common()->Select(MachineRepresentation::kTagged), 3325 NewNode(simplified()->ReferenceEqual(), object, 3326 jsgraph()->TrueConstant()), 3327 jsgraph()->TrueConstant(), 3328 NewNode(simplified()->ReferenceEqual(), object, 3329 jsgraph()->FalseConstant())); 3330 break; 3331 case interpreter::TestTypeOfFlags::LiteralFlag::kUndefined: 3332 result = graph()->NewNode( 3333 common()->Select(MachineRepresentation::kTagged), 3334 graph()->NewNode(simplified()->ReferenceEqual(), object, 3335 jsgraph()->NullConstant()), 3336 jsgraph()->FalseConstant(), 3337 graph()->NewNode(simplified()->ObjectIsUndetectable(), object)); 3338 break; 3339 case interpreter::TestTypeOfFlags::LiteralFlag::kFunction: 3340 result = 3341 graph()->NewNode(simplified()->ObjectIsDetectableCallable(), object); 3342 break; 3343 case interpreter::TestTypeOfFlags::LiteralFlag::kObject: 3344 result = graph()->NewNode( 3345 common()->Select(MachineRepresentation::kTagged), 3346 graph()->NewNode(simplified()->ObjectIsNonCallable(), object), 3347 jsgraph()->TrueConstant(), 3348 graph()->NewNode(simplified()->ReferenceEqual(), object, 3349 jsgraph()->NullConstant())); 3350 break; 3351 case interpreter::TestTypeOfFlags::LiteralFlag::kOther: 3352 UNREACHABLE(); // Should never be emitted. 3353 } 3354 environment()->BindAccumulator(result); 3355} 3356 3357void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) { 3358 Node* value = NewNode(js_op, environment()->LookupAccumulator()); 3359 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value, 3360 Environment::kAttachFrameState); 3361} 3362 3363void BytecodeGraphBuilder::VisitToName() { 3364 BuildCastOperator(javascript()->ToName()); 3365} 3366 3367void BytecodeGraphBuilder::VisitToObject() { 3368 BuildCastOperator(javascript()->ToObject()); 3369} 3370 3371void BytecodeGraphBuilder::VisitToString() { 3372 Node* value = 3373 NewNode(javascript()->ToString(), environment()->LookupAccumulator()); 3374 environment()->BindAccumulator(value, Environment::kAttachFrameState); 3375} 3376 3377void BytecodeGraphBuilder::VisitToNumber() { 3378 PrepareEagerCheckpoint(); 3379 Node* object = environment()->LookupAccumulator(); 3380 3381 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0); 3382 JSTypeHintLowering::LoweringResult lowering = 3383 TryBuildSimplifiedToNumber(object, slot); 3384 3385 Node* node = nullptr; 3386 if (lowering.IsSideEffectFree()) { 3387 node = lowering.value(); 3388 } else { 3389 DCHECK(!lowering.Changed()); 3390 node = NewNode(javascript()->ToNumber(), object); 3391 } 3392 3393 environment()->BindAccumulator(node, Environment::kAttachFrameState); 3394} 3395 3396void BytecodeGraphBuilder::VisitToNumeric() { 3397 PrepareEagerCheckpoint(); 3398 Node* object = environment()->LookupAccumulator(); 3399 3400 // If we have some kind of Number feedback, we do the same lowering as for 3401 // ToNumber. 3402 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0); 3403 JSTypeHintLowering::LoweringResult lowering = 3404 TryBuildSimplifiedToNumber(object, slot); 3405 3406 Node* node = nullptr; 3407 if (lowering.IsSideEffectFree()) { 3408 node = lowering.value(); 3409 } else { 3410 DCHECK(!lowering.Changed()); 3411 node = NewNode(javascript()->ToNumeric(), object); 3412 } 3413 3414 environment()->BindAccumulator(node, Environment::kAttachFrameState); 3415} 3416 3417void BytecodeGraphBuilder::VisitJump() { BuildJump(); } 3418 3419void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); } 3420 3421void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); } 3422 3423void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); } 3424 3425void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); } 3426 3427void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); } 3428 3429void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() { 3430 BuildJumpIfToBooleanTrue(); 3431} 3432 3433void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() { 3434 BuildJumpIfToBooleanTrue(); 3435} 3436 3437void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() { 3438 BuildJumpIfToBooleanFalse(); 3439} 3440 3441void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() { 3442 BuildJumpIfToBooleanFalse(); 3443} 3444 3445void BytecodeGraphBuilder::VisitJumpIfJSReceiver() { BuildJumpIfJSReceiver(); } 3446 3447void BytecodeGraphBuilder::VisitJumpIfJSReceiverConstant() { 3448 BuildJumpIfJSReceiver(); 3449} 3450 3451void BytecodeGraphBuilder::VisitJumpIfNull() { 3452 BuildJumpIfEqual(jsgraph()->NullConstant()); 3453} 3454 3455void BytecodeGraphBuilder::VisitJumpIfNullConstant() { 3456 BuildJumpIfEqual(jsgraph()->NullConstant()); 3457} 3458 3459void BytecodeGraphBuilder::VisitJumpIfNotNull() { 3460 BuildJumpIfNotEqual(jsgraph()->NullConstant()); 3461} 3462 3463void BytecodeGraphBuilder::VisitJumpIfNotNullConstant() { 3464 BuildJumpIfNotEqual(jsgraph()->NullConstant()); 3465} 3466 3467void BytecodeGraphBuilder::VisitJumpIfUndefined() { 3468 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 3469} 3470 3471void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { 3472 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 3473} 3474 3475void BytecodeGraphBuilder::VisitJumpIfNotUndefined() { 3476 BuildJumpIfNotEqual(jsgraph()->UndefinedConstant()); 3477} 3478 3479void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() { 3480 BuildJumpIfNotEqual(jsgraph()->UndefinedConstant()); 3481} 3482 3483void BytecodeGraphBuilder::VisitJumpIfUndefinedOrNull() { 3484 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 3485 BuildJumpIfEqual(jsgraph()->NullConstant()); 3486} 3487 3488void BytecodeGraphBuilder::VisitJumpIfUndefinedOrNullConstant() { 3489 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 3490 BuildJumpIfEqual(jsgraph()->NullConstant()); 3491} 3492 3493void BytecodeGraphBuilder::VisitJumpLoop() { 3494 BuildIterationBodyStackCheck(); 3495 BuildJump(); 3496} 3497 3498void BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) { 3499 interpreter::JumpTableTargetOffsets offsets = 3500 bytecode_iterator().GetJumpTableTargetOffsets(); 3501 3502 NewSwitch(condition, offsets.size() + 1); 3503 for (interpreter::JumpTableTargetOffset entry : offsets) { 3504 SubEnvironment sub_environment(this); 3505 NewIfValue(entry.case_value); 3506 MergeIntoSuccessorEnvironment(entry.target_offset); 3507 } 3508 NewIfDefault(); 3509} 3510 3511void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() { 3512 PrepareEagerCheckpoint(); 3513 3514 Node* acc = environment()->LookupAccumulator(); 3515 Node* acc_smi = NewNode(simplified()->CheckSmi(FeedbackSource()), acc); 3516 BuildSwitchOnSmi(acc_smi); 3517} 3518 3519void BytecodeGraphBuilder::VisitSetPendingMessage() { 3520 Node* previous_message = NewNode(javascript()->LoadMessage()); 3521 NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator()); 3522 environment()->BindAccumulator(previous_message); 3523} 3524 3525void BytecodeGraphBuilder::BuildReturn(const BytecodeLivenessState* liveness) { 3526 BuildLoopExitsForFunctionExit(liveness); 3527 Node* pop_node = jsgraph()->ZeroConstant(); 3528 Node* control = 3529 NewNode(common()->Return(), pop_node, environment()->LookupAccumulator()); 3530 MergeControlToLeaveFunction(control); 3531} 3532 3533void BytecodeGraphBuilder::VisitReturn() { 3534 BuildReturn(bytecode_analysis().GetInLivenessFor( 3535 bytecode_iterator().current_offset())); 3536} 3537 3538void BytecodeGraphBuilder::VisitDebugger() { 3539 PrepareEagerCheckpoint(); 3540 Node* call = NewNode(javascript()->Debugger()); 3541 environment()->RecordAfterState(call, Environment::kAttachFrameState); 3542} 3543 3544// We cannot create a graph from the debugger copy of the bytecode array. 3545#define DEBUG_BREAK(Name, ...) \ 3546 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } 3547DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK) 3548#undef DEBUG_BREAK 3549 3550void BytecodeGraphBuilder::VisitIncBlockCounter() { 3551 Node* closure = GetFunctionClosure(); 3552 Node* coverage_array_slot = 3553 jsgraph()->Constant(bytecode_iterator().GetIndexOperand(0)); 3554 3555 // Lowered by js-intrinsic-lowering to call Builtin::kIncBlockCounter. 3556 const Operator* op = 3557 javascript()->CallRuntime(Runtime::kInlineIncBlockCounter); 3558 3559 NewNode(op, closure, coverage_array_slot); 3560} 3561 3562void BytecodeGraphBuilder::VisitForInEnumerate() { 3563 Node* receiver = 3564 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3565 Node* enumerator = NewNode(javascript()->ForInEnumerate(), receiver); 3566 environment()->BindAccumulator(enumerator, Environment::kAttachFrameState); 3567} 3568 3569void BytecodeGraphBuilder::VisitForInPrepare() { 3570 PrepareEagerCheckpoint(); 3571 Node* enumerator = environment()->LookupAccumulator(); 3572 3573 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1); 3574 JSTypeHintLowering::LoweringResult lowering = 3575 TryBuildSimplifiedForInPrepare(enumerator, slot); 3576 if (lowering.IsExit()) return; 3577 DCHECK(!lowering.Changed()); 3578 FeedbackSource feedback = CreateFeedbackSource(slot); 3579 Node* node = NewNode(javascript()->ForInPrepare(GetForInMode(slot), feedback), 3580 enumerator, feedback_vector_node()); 3581 environment()->BindRegistersToProjections( 3582 bytecode_iterator().GetRegisterOperand(0), node); 3583} 3584 3585void BytecodeGraphBuilder::VisitForInContinue() { 3586 PrepareEagerCheckpoint(); 3587 Node* index = 3588 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3589 Node* cache_length = 3590 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 3591 Node* exit_cond = NewNode(simplified()->SpeculativeNumberLessThan( 3592 NumberOperationHint::kSignedSmall), 3593 index, cache_length); 3594 environment()->BindAccumulator(exit_cond); 3595} 3596 3597void BytecodeGraphBuilder::VisitForInNext() { 3598 PrepareEagerCheckpoint(); 3599 Node* receiver = 3600 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3601 Node* index = 3602 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 3603 int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index(); 3604 Node* cache_type = environment()->LookupRegister( 3605 interpreter::Register(catch_reg_pair_index)); 3606 Node* cache_array = environment()->LookupRegister( 3607 interpreter::Register(catch_reg_pair_index + 1)); 3608 3609 // We need to rename the {index} here, as in case of OSR we lose the 3610 // information that the {index} is always a valid unsigned Smi value. 3611 index = NewNode(common()->TypeGuard(Type::UnsignedSmall()), index); 3612 3613 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(3); 3614 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedForInNext( 3615 receiver, cache_array, cache_type, index, slot); 3616 if (lowering.IsExit()) return; 3617 3618 DCHECK(!lowering.Changed()); 3619 FeedbackSource feedback = CreateFeedbackSource(slot); 3620 Node* node = 3621 NewNode(javascript()->ForInNext(GetForInMode(slot), feedback), receiver, 3622 cache_array, cache_type, index, feedback_vector_node()); 3623 environment()->BindAccumulator(node, Environment::kAttachFrameState); 3624} 3625 3626void BytecodeGraphBuilder::VisitForInStep() { 3627 PrepareEagerCheckpoint(); 3628 Node* index = 3629 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3630 index = NewNode(simplified()->SpeculativeSafeIntegerAdd( 3631 NumberOperationHint::kSignedSmall), 3632 index, jsgraph()->OneConstant()); 3633 environment()->BindAccumulator(index, Environment::kAttachFrameState); 3634} 3635 3636void BytecodeGraphBuilder::VisitGetIterator() { 3637 PrepareEagerCheckpoint(); 3638 Node* receiver = 3639 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3640 FeedbackSource load_feedback = 3641 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 3642 FeedbackSource call_feedback = 3643 CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 3644 const Operator* op = javascript()->GetIterator(load_feedback, call_feedback); 3645 3646 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedGetIterator( 3647 op, receiver, load_feedback.slot, call_feedback.slot); 3648 if (lowering.IsExit()) return; 3649 3650 DCHECK(!lowering.Changed()); 3651 STATIC_ASSERT(JSGetIteratorNode::ReceiverIndex() == 0); 3652 STATIC_ASSERT(JSGetIteratorNode::FeedbackVectorIndex() == 1); 3653 DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 3654 Node* iterator = NewNode(op, receiver, feedback_vector_node()); 3655 environment()->BindAccumulator(iterator, Environment::kAttachFrameState); 3656} 3657 3658void BytecodeGraphBuilder::VisitSuspendGenerator() { 3659 Node* generator = environment()->LookupRegister( 3660 bytecode_iterator().GetRegisterOperand(0)); 3661 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 3662 // We assume we are storing a range starting from index 0. 3663 CHECK_EQ(0, first_reg.index()); 3664 int register_count = 3665 static_cast<int>(bytecode_iterator().GetRegisterCountOperand(2)); 3666 int parameter_count_without_receiver = bytecode_array().parameter_count() - 1; 3667 3668 Node* suspend_id = jsgraph()->SmiConstant( 3669 bytecode_iterator().GetUnsignedImmediateOperand(3)); 3670 3671 // The offsets used by the bytecode iterator are relative to a different base 3672 // than what is used in the interpreter, hence the addition. 3673 Node* offset = 3674 jsgraph()->Constant(bytecode_iterator().current_offset() + 3675 (BytecodeArray::kHeaderSize - kHeapObjectTag)); 3676 3677 const BytecodeLivenessState* liveness = bytecode_analysis().GetInLivenessFor( 3678 bytecode_iterator().current_offset()); 3679 3680 // Maybe overallocate the value list since we don't know how many registers 3681 // are live. 3682 // TODO(leszeks): We could get this count from liveness rather than the 3683 // register list. 3684 int value_input_count = 3 + parameter_count_without_receiver + register_count; 3685 3686 Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count); 3687 value_inputs[0] = generator; 3688 value_inputs[1] = suspend_id; 3689 value_inputs[2] = offset; 3690 3691 int count_written = 0; 3692 // Store the parameters. 3693 for (int i = 0; i < parameter_count_without_receiver; i++) { 3694 value_inputs[3 + count_written++] = 3695 environment()->LookupRegister(bytecode_iterator().GetParameter(i)); 3696 } 3697 3698 // Store the registers. 3699 for (int i = 0; i < register_count; ++i) { 3700 if (liveness == nullptr || liveness->RegisterIsLive(i)) { 3701 int index_in_parameters_and_registers = 3702 parameter_count_without_receiver + i; 3703 while (count_written < index_in_parameters_and_registers) { 3704 value_inputs[3 + count_written++] = jsgraph()->OptimizedOutConstant(); 3705 } 3706 value_inputs[3 + count_written++] = 3707 environment()->LookupRegister(interpreter::Register(i)); 3708 DCHECK_EQ(count_written, index_in_parameters_and_registers + 1); 3709 } 3710 } 3711 3712 // Use the actual written count rather than the register count to create the 3713 // node. 3714 MakeNode(javascript()->GeneratorStore(count_written), 3 + count_written, 3715 value_inputs, false); 3716 3717 // TODO(leszeks): This over-approximates the liveness at exit, only the 3718 // accumulator should be live by this point. 3719 BuildReturn(bytecode_analysis().GetInLivenessFor( 3720 bytecode_iterator().current_offset())); 3721} 3722 3723void BytecodeGraphBuilder::BuildSwitchOnGeneratorState( 3724 const ZoneVector<ResumeJumpTarget>& resume_jump_targets, 3725 bool allow_fallthrough_on_executing) { 3726 Node* generator_state = environment()->LookupGeneratorState(); 3727 3728 int extra_cases = allow_fallthrough_on_executing ? 2 : 1; 3729 NewSwitch(generator_state, 3730 static_cast<int>(resume_jump_targets.size() + extra_cases)); 3731 for (const ResumeJumpTarget& target : resume_jump_targets) { 3732 SubEnvironment sub_environment(this); 3733 NewIfValue(target.suspend_id()); 3734 if (target.is_leaf()) { 3735 // Mark that we are resuming executing. 3736 environment()->BindGeneratorState( 3737 jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting)); 3738 } 3739 // Jump to the target offset, whether it's a loop header or the resume. 3740 MergeIntoSuccessorEnvironment(target.target_offset()); 3741 } 3742 3743 { 3744 SubEnvironment sub_environment(this); 3745 // We should never hit the default case (assuming generator state cannot be 3746 // corrupted), so abort if we do. 3747 // TODO(leszeks): Maybe only check this in debug mode, and otherwise use 3748 // the default to represent one of the cases above/fallthrough below? 3749 NewIfDefault(); 3750 NewNode(simplified()->RuntimeAbort(AbortReason::kInvalidJumpTableIndex)); 3751 // TODO(7099): Investigate if we need LoopExit here. 3752 Node* control = NewNode(common()->Throw()); 3753 MergeControlToLeaveFunction(control); 3754 } 3755 3756 if (allow_fallthrough_on_executing) { 3757 // If we are executing (rather than resuming), and we allow it, just fall 3758 // through to the actual loop body. 3759 NewIfValue(JSGeneratorObject::kGeneratorExecuting); 3760 } else { 3761 // Otherwise, this environment is dead. 3762 set_environment(nullptr); 3763 } 3764} 3765 3766void BytecodeGraphBuilder::VisitSwitchOnGeneratorState() { 3767 Node* generator = 3768 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3769 3770 Node* generator_is_undefined = 3771 NewNode(simplified()->ReferenceEqual(), generator, 3772 jsgraph()->UndefinedConstant()); 3773 3774 NewBranch(generator_is_undefined); 3775 { 3776 SubEnvironment resume_env(this); 3777 NewIfFalse(); 3778 3779 Node* generator_state = 3780 NewNode(javascript()->GeneratorRestoreContinuation(), generator); 3781 environment()->BindGeneratorState(generator_state); 3782 3783 Node* generator_context = 3784 NewNode(javascript()->GeneratorRestoreContext(), generator); 3785 environment()->SetContext(generator_context); 3786 3787 BuildSwitchOnGeneratorState(bytecode_analysis().resume_jump_targets(), 3788 false); 3789 } 3790 3791 // Fallthrough for the first-call case. 3792 NewIfTrue(); 3793} 3794 3795void BytecodeGraphBuilder::VisitResumeGenerator() { 3796 Node* generator = 3797 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 3798 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 3799 // We assume we are restoring registers starting fromm index 0. 3800 CHECK_EQ(0, first_reg.index()); 3801 3802 const BytecodeLivenessState* liveness = bytecode_analysis().GetOutLivenessFor( 3803 bytecode_iterator().current_offset()); 3804 3805 int parameter_count_without_receiver = bytecode_array().parameter_count() - 1; 3806 3807 // Mapping between registers and array indices must match that used in 3808 // InterpreterAssembler::ExportParametersAndRegisterFile. 3809 for (int i = 0; i < environment()->register_count(); ++i) { 3810 if (liveness == nullptr || liveness->RegisterIsLive(i)) { 3811 Node* value = NewNode(javascript()->GeneratorRestoreRegister( 3812 parameter_count_without_receiver + i), 3813 generator); 3814 environment()->BindRegister(interpreter::Register(i), value); 3815 } 3816 } 3817 3818 // Update the accumulator with the generator's input_or_debug_pos. 3819 Node* input_or_debug_pos = 3820 NewNode(javascript()->GeneratorRestoreInputOrDebugPos(), generator); 3821 environment()->BindAccumulator(input_or_debug_pos); 3822} 3823 3824void BytecodeGraphBuilder::VisitWide() { 3825 // Consumed by the BytecodeArrayIterator. 3826 UNREACHABLE(); 3827} 3828 3829void BytecodeGraphBuilder::VisitExtraWide() { 3830 // Consumed by the BytecodeArrayIterator. 3831 UNREACHABLE(); 3832} 3833 3834void BytecodeGraphBuilder::VisitIllegal() { 3835 // Not emitted in valid bytecode. 3836 UNREACHABLE(); 3837} 3838 3839void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { 3840 auto it = merge_environments_.find(current_offset); 3841 if (it != merge_environments_.end()) { 3842 mark_as_needing_eager_checkpoint(true); 3843 if (environment() != nullptr) { 3844 it->second->Merge(environment(), 3845 bytecode_analysis().GetInLivenessFor(current_offset)); 3846 } 3847 set_environment(it->second); 3848 } 3849} 3850 3851void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { 3852 if (bytecode_analysis().IsLoopHeader(current_offset)) { 3853 mark_as_needing_eager_checkpoint(true); 3854 const LoopInfo& loop_info = 3855 bytecode_analysis().GetLoopInfoFor(current_offset); 3856 const BytecodeLivenessState* liveness = 3857 bytecode_analysis().GetInLivenessFor(current_offset); 3858 3859 const auto& resume_jump_targets = loop_info.resume_jump_targets(); 3860 bool generate_suspend_switch = !resume_jump_targets.empty(); 3861 3862 // Add loop header. 3863 environment()->PrepareForLoop(loop_info.assignments(), liveness); 3864 3865 // Store a copy of the environment so we can connect merged back edge inputs 3866 // to the loop header. 3867 merge_environments_[current_offset] = environment()->Copy(); 3868 3869 // If this loop contains resumes, create a new switch just after the loop 3870 // for those resumes. 3871 if (generate_suspend_switch) { 3872 BuildSwitchOnGeneratorState(loop_info.resume_jump_targets(), true); 3873 3874 // TODO(leszeks): At this point we know we are executing rather than 3875 // resuming, so we should be able to prune off the phis in the environment 3876 // related to the resume path. 3877 3878 // Set the generator state to a known constant. 3879 environment()->BindGeneratorState( 3880 jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting)); 3881 } 3882 } 3883} 3884 3885void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { 3886 BuildLoopExitsForBranch(target_offset); 3887 Environment*& merge_environment = merge_environments_[target_offset]; 3888 3889 if (merge_environment == nullptr) { 3890 // Append merge nodes to the environment. We may merge here with another 3891 // environment. So add a place holder for merge nodes. We may add redundant 3892 // but will be eliminated in a later pass. 3893 NewMerge(); 3894 merge_environment = environment(); 3895 } else { 3896 // Merge any values which are live coming into the successor. 3897 merge_environment->Merge( 3898 environment(), bytecode_analysis().GetInLivenessFor(target_offset)); 3899 } 3900 set_environment(nullptr); 3901} 3902 3903void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { 3904 exit_controls_.push_back(exit); 3905 set_environment(nullptr); 3906} 3907 3908void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { 3909 int origin_offset = bytecode_iterator().current_offset(); 3910 // Only build loop exits for forward edges. 3911 if (target_offset > origin_offset) { 3912 BuildLoopExitsUntilLoop( 3913 bytecode_analysis().GetLoopOffsetFor(target_offset), 3914 bytecode_analysis().GetInLivenessFor(target_offset)); 3915 } 3916} 3917 3918void BytecodeGraphBuilder::BuildLoopExitsUntilLoop( 3919 int loop_offset, const BytecodeLivenessState* liveness) { 3920 int origin_offset = bytecode_iterator().current_offset(); 3921 int current_loop = bytecode_analysis().GetLoopOffsetFor(origin_offset); 3922 // The limit_offset is the stop offset for building loop exists, used for OSR. 3923 // It prevents the creations of loopexits for loops which do not exist. 3924 loop_offset = std::max(loop_offset, currently_peeled_loop_offset_); 3925 3926 while (loop_offset < current_loop) { 3927 Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); 3928 const LoopInfo& loop_info = 3929 bytecode_analysis().GetLoopInfoFor(current_loop); 3930 environment()->PrepareForLoopExit(loop_node, loop_info.assignments(), 3931 liveness); 3932 current_loop = loop_info.parent_offset(); 3933 } 3934} 3935 3936void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit( 3937 const BytecodeLivenessState* liveness) { 3938 BuildLoopExitsUntilLoop(-1, liveness); 3939} 3940 3941void BytecodeGraphBuilder::BuildJump() { 3942 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 3943} 3944 3945void BytecodeGraphBuilder::BuildJumpIf(Node* condition) { 3946 NewBranch(condition, BranchHint::kNone); 3947 { 3948 SubEnvironment sub_environment(this); 3949 NewIfTrue(); 3950 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 3951 } 3952 NewIfFalse(); 3953} 3954 3955void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) { 3956 NewBranch(condition, BranchHint::kNone); 3957 { 3958 SubEnvironment sub_environment(this); 3959 NewIfFalse(); 3960 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 3961 } 3962 NewIfTrue(); 3963} 3964 3965void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { 3966 Node* accumulator = environment()->LookupAccumulator(); 3967 Node* condition = 3968 NewNode(simplified()->ReferenceEqual(), accumulator, comperand); 3969 BuildJumpIf(condition); 3970} 3971 3972void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) { 3973 Node* accumulator = environment()->LookupAccumulator(); 3974 Node* condition = 3975 NewNode(simplified()->ReferenceEqual(), accumulator, comperand); 3976 BuildJumpIfNot(condition); 3977} 3978 3979void BytecodeGraphBuilder::BuildJumpIfFalse() { 3980 NewBranch(environment()->LookupAccumulator(), BranchHint::kNone); 3981 { 3982 SubEnvironment sub_environment(this); 3983 NewIfFalse(); 3984 environment()->BindAccumulator(jsgraph()->FalseConstant()); 3985 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 3986 } 3987 NewIfTrue(); 3988 environment()->BindAccumulator(jsgraph()->TrueConstant()); 3989} 3990 3991void BytecodeGraphBuilder::BuildJumpIfTrue() { 3992 NewBranch(environment()->LookupAccumulator(), BranchHint::kNone); 3993 { 3994 SubEnvironment sub_environment(this); 3995 NewIfTrue(); 3996 environment()->BindAccumulator(jsgraph()->TrueConstant()); 3997 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 3998 } 3999 NewIfFalse(); 4000 environment()->BindAccumulator(jsgraph()->FalseConstant()); 4001} 4002 4003void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() { 4004 Node* accumulator = environment()->LookupAccumulator(); 4005 Node* condition = NewNode(simplified()->ToBoolean(), accumulator); 4006 BuildJumpIf(condition); 4007} 4008 4009void BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() { 4010 Node* accumulator = environment()->LookupAccumulator(); 4011 Node* condition = NewNode(simplified()->ToBoolean(), accumulator); 4012 BuildJumpIfNot(condition); 4013} 4014 4015void BytecodeGraphBuilder::BuildJumpIfNotHole() { 4016 Node* accumulator = environment()->LookupAccumulator(); 4017 Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator, 4018 jsgraph()->TheHoleConstant()); 4019 BuildJumpIfNot(condition); 4020} 4021 4022void BytecodeGraphBuilder::BuildJumpIfJSReceiver() { 4023 Node* accumulator = environment()->LookupAccumulator(); 4024 Node* condition = NewNode(simplified()->ObjectIsReceiver(), accumulator); 4025 BuildJumpIf(condition); 4026} 4027 4028JSTypeHintLowering::LoweringResult 4029BytecodeGraphBuilder::TryBuildSimplifiedUnaryOp(const Operator* op, 4030 Node* operand, 4031 FeedbackSlot slot) { 4032 Node* effect = environment()->GetEffectDependency(); 4033 Node* control = environment()->GetControlDependency(); 4034 JSTypeHintLowering::LoweringResult result = 4035 type_hint_lowering().ReduceUnaryOperation(op, operand, effect, control, 4036 slot); 4037 ApplyEarlyReduction(result); 4038 return result; 4039} 4040 4041JSTypeHintLowering::LoweringResult 4042BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, 4043 Node* right, 4044 FeedbackSlot slot) { 4045 Node* effect = environment()->GetEffectDependency(); 4046 Node* control = environment()->GetControlDependency(); 4047 JSTypeHintLowering::LoweringResult result = 4048 type_hint_lowering().ReduceBinaryOperation(op, left, right, effect, 4049 control, slot); 4050 ApplyEarlyReduction(result); 4051 return result; 4052} 4053 4054JSTypeHintLowering::LoweringResult 4055BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver, 4056 Node* cache_array, 4057 Node* cache_type, Node* index, 4058 FeedbackSlot slot) { 4059 Node* effect = environment()->GetEffectDependency(); 4060 Node* control = environment()->GetControlDependency(); 4061 JSTypeHintLowering::LoweringResult result = 4062 type_hint_lowering().ReduceForInNextOperation( 4063 receiver, cache_array, cache_type, index, effect, control, slot); 4064 ApplyEarlyReduction(result); 4065 return result; 4066} 4067 4068JSTypeHintLowering::LoweringResult 4069BytecodeGraphBuilder::TryBuildSimplifiedForInPrepare(Node* enumerator, 4070 FeedbackSlot slot) { 4071 Node* effect = environment()->GetEffectDependency(); 4072 Node* control = environment()->GetControlDependency(); 4073 JSTypeHintLowering::LoweringResult result = 4074 type_hint_lowering().ReduceForInPrepareOperation(enumerator, effect, 4075 control, slot); 4076 ApplyEarlyReduction(result); 4077 return result; 4078} 4079 4080JSTypeHintLowering::LoweringResult 4081BytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value, 4082 FeedbackSlot slot) { 4083 Node* effect = environment()->GetEffectDependency(); 4084 Node* control = environment()->GetControlDependency(); 4085 JSTypeHintLowering::LoweringResult result = 4086 type_hint_lowering().ReduceToNumberOperation(value, effect, control, 4087 slot); 4088 ApplyEarlyReduction(result); 4089 return result; 4090} 4091 4092JSTypeHintLowering::LoweringResult BytecodeGraphBuilder::TryBuildSimplifiedCall( 4093 const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot) { 4094 Node* effect = environment()->GetEffectDependency(); 4095 Node* control = environment()->GetControlDependency(); 4096 JSTypeHintLowering::LoweringResult result = 4097 type_hint_lowering().ReduceCallOperation(op, args, arg_count, effect, 4098 control, slot); 4099 ApplyEarlyReduction(result); 4100 return result; 4101} 4102 4103JSTypeHintLowering::LoweringResult 4104BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op, 4105 Node* const* args, 4106 int arg_count, 4107 FeedbackSlot slot) { 4108 Node* effect = environment()->GetEffectDependency(); 4109 Node* control = environment()->GetControlDependency(); 4110 JSTypeHintLowering::LoweringResult result = 4111 type_hint_lowering().ReduceConstructOperation(op, args, arg_count, effect, 4112 control, slot); 4113 ApplyEarlyReduction(result); 4114 return result; 4115} 4116 4117JSTypeHintLowering::LoweringResult 4118BytecodeGraphBuilder::TryBuildSimplifiedGetIterator(const Operator* op, 4119 Node* receiver, 4120 FeedbackSlot load_slot, 4121 FeedbackSlot call_slot) { 4122 Node* effect = environment()->GetEffectDependency(); 4123 Node* control = environment()->GetControlDependency(); 4124 JSTypeHintLowering::LoweringResult early_reduction = 4125 type_hint_lowering().ReduceGetIteratorOperation( 4126 op, receiver, effect, control, load_slot, call_slot); 4127 ApplyEarlyReduction(early_reduction); 4128 return early_reduction; 4129} 4130 4131JSTypeHintLowering::LoweringResult 4132BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op, 4133 FeedbackSlot slot) { 4134 Node* effect = environment()->GetEffectDependency(); 4135 Node* control = environment()->GetControlDependency(); 4136 JSTypeHintLowering::LoweringResult early_reduction = 4137 type_hint_lowering().ReduceLoadNamedOperation(op, effect, control, slot); 4138 ApplyEarlyReduction(early_reduction); 4139 return early_reduction; 4140} 4141 4142JSTypeHintLowering::LoweringResult 4143BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op, 4144 Node* receiver, Node* key, 4145 FeedbackSlot slot) { 4146 Node* effect = environment()->GetEffectDependency(); 4147 Node* control = environment()->GetControlDependency(); 4148 JSTypeHintLowering::LoweringResult result = 4149 type_hint_lowering().ReduceLoadKeyedOperation(op, receiver, key, effect, 4150 control, slot); 4151 ApplyEarlyReduction(result); 4152 return result; 4153} 4154 4155JSTypeHintLowering::LoweringResult 4156BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op, 4157 Node* receiver, Node* value, 4158 FeedbackSlot slot) { 4159 Node* effect = environment()->GetEffectDependency(); 4160 Node* control = environment()->GetControlDependency(); 4161 JSTypeHintLowering::LoweringResult result = 4162 type_hint_lowering().ReduceStoreNamedOperation(op, receiver, value, 4163 effect, control, slot); 4164 ApplyEarlyReduction(result); 4165 return result; 4166} 4167 4168JSTypeHintLowering::LoweringResult 4169BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op, 4170 Node* receiver, Node* key, 4171 Node* value, 4172 FeedbackSlot slot) { 4173 Node* effect = environment()->GetEffectDependency(); 4174 Node* control = environment()->GetControlDependency(); 4175 JSTypeHintLowering::LoweringResult result = 4176 type_hint_lowering().ReduceStoreKeyedOperation(op, receiver, key, value, 4177 effect, control, slot); 4178 ApplyEarlyReduction(result); 4179 return result; 4180} 4181 4182void BytecodeGraphBuilder::ApplyEarlyReduction( 4183 JSTypeHintLowering::LoweringResult reduction) { 4184 if (reduction.IsExit()) { 4185 MergeControlToLeaveFunction(reduction.control()); 4186 } else if (reduction.IsSideEffectFree()) { 4187 environment()->UpdateEffectDependency(reduction.effect()); 4188 environment()->UpdateControlDependency(reduction.control()); 4189 } else { 4190 DCHECK(!reduction.Changed()); 4191 // At the moment, we assume side-effect free reduction. To support 4192 // side-effects, we would have to invalidate the eager checkpoint, 4193 // so that deoptimization does not repeat the side effect. 4194 } 4195} 4196 4197Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { 4198 if (size > input_buffer_size_) { 4199 size = size + kInputBufferSizeIncrement + input_buffer_size_; 4200 input_buffer_ = local_zone()->NewArray<Node*>(size); 4201 input_buffer_size_ = size; 4202 } 4203 return input_buffer_; 4204} 4205 4206void BytecodeGraphBuilder::ExitThenEnterExceptionHandlers(int current_offset) { 4207 DisallowGarbageCollection no_gc; 4208 HandlerTable table(bytecode_array().handler_table_address(), 4209 bytecode_array().handler_table_size(), 4210 HandlerTable::kRangeBasedEncoding); 4211 4212 // Potentially exit exception handlers. 4213 while (!exception_handlers_.empty()) { 4214 int current_end = exception_handlers_.top().end_offset_; 4215 if (current_offset < current_end) break; // Still covered by range. 4216 exception_handlers_.pop(); 4217 } 4218 4219 // Potentially enter exception handlers. 4220 int num_entries = table.NumberOfRangeEntries(); 4221 while (current_exception_handler_ < num_entries) { 4222 int next_start = table.GetRangeStart(current_exception_handler_); 4223 if (current_offset < next_start) break; // Not yet covered by range. 4224 int next_end = table.GetRangeEnd(current_exception_handler_); 4225 int next_handler = table.GetRangeHandler(current_exception_handler_); 4226 int context_register = table.GetRangeData(current_exception_handler_); 4227 exception_handlers_.push( 4228 {next_start, next_end, next_handler, context_register}); 4229 current_exception_handler_++; 4230 } 4231} 4232 4233Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, 4234 Node* const* value_inputs, 4235 bool incomplete) { 4236 DCHECK_EQ(op->ValueInputCount(), value_input_count); 4237 // Parameter nodes must be created through GetParameter. 4238 DCHECK_IMPLIES( 4239 op->opcode() == IrOpcode::kParameter, 4240 (nullptr == cached_parameters_[static_cast<std::size_t>( 4241 ParameterIndexOf(op) - ParameterInfo::kMinIndex)])); 4242 4243 bool has_context = OperatorProperties::HasContextInput(op); 4244 bool has_frame_state = OperatorProperties::HasFrameStateInput(op); 4245 bool has_control = op->ControlInputCount() == 1; 4246 bool has_effect = op->EffectInputCount() == 1; 4247 4248 DCHECK_LT(op->ControlInputCount(), 2); 4249 DCHECK_LT(op->EffectInputCount(), 2); 4250 4251 Node* result = nullptr; 4252 if (!has_context && !has_frame_state && !has_control && !has_effect) { 4253 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); 4254 } else { 4255 bool inside_handler = !exception_handlers_.empty(); 4256 int input_count_with_deps = value_input_count; 4257 if (has_context) ++input_count_with_deps; 4258 if (has_frame_state) ++input_count_with_deps; 4259 if (has_control) ++input_count_with_deps; 4260 if (has_effect) ++input_count_with_deps; 4261 Node** buffer = EnsureInputBufferSize(input_count_with_deps); 4262 if (value_input_count > 0) { 4263 memcpy(buffer, value_inputs, kSystemPointerSize * value_input_count); 4264 } 4265 Node** current_input = buffer + value_input_count; 4266 if (has_context) { 4267 *current_input++ = OperatorProperties::NeedsExactContext(op) 4268 ? environment()->Context() 4269 : native_context_node(); 4270 } 4271 if (has_frame_state) { 4272 // The frame state will be inserted later. Here we misuse the {Dead} node 4273 // as a sentinel to be later overwritten with the real frame state by the 4274 // calls to {PrepareFrameState} within individual visitor methods. 4275 *current_input++ = jsgraph()->Dead(); 4276 } 4277 if (has_effect) { 4278 *current_input++ = environment()->GetEffectDependency(); 4279 } 4280 if (has_control) { 4281 *current_input++ = environment()->GetControlDependency(); 4282 } 4283 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); 4284 // Update the current control dependency for control-producing nodes. 4285 if (result->op()->ControlOutputCount() > 0) { 4286 environment()->UpdateControlDependency(result); 4287 } 4288 // Update the current effect dependency for effect-producing nodes. 4289 if (result->op()->EffectOutputCount() > 0) { 4290 environment()->UpdateEffectDependency(result); 4291 } 4292 // Add implicit exception continuation for throwing nodes. 4293 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { 4294 int handler_offset = exception_handlers_.top().handler_offset_; 4295 int context_index = exception_handlers_.top().context_register_; 4296 interpreter::Register context_register(context_index); 4297 Environment* success_env = environment()->Copy(); 4298 const Operator* if_exception = common()->IfException(); 4299 Node* effect = environment()->GetEffectDependency(); 4300 Node* on_exception = graph()->NewNode(if_exception, effect, result); 4301 Node* context = environment()->LookupRegister(context_register); 4302 environment()->UpdateControlDependency(on_exception); 4303 environment()->UpdateEffectDependency(on_exception); 4304 environment()->BindAccumulator(on_exception); 4305 environment()->SetContext(context); 4306 MergeIntoSuccessorEnvironment(handler_offset); 4307 set_environment(success_env); 4308 } 4309 // Add implicit success continuation for throwing nodes. 4310 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { 4311 const Operator* if_success = common()->IfSuccess(); 4312 Node* on_success = graph()->NewNode(if_success, result); 4313 environment()->UpdateControlDependency(on_success); 4314 } 4315 // Ensure checkpoints are created after operations with side-effects. 4316 if (has_effect && !result->op()->HasProperty(Operator::kNoWrite)) { 4317 mark_as_needing_eager_checkpoint(true); 4318 } 4319 } 4320 4321 return result; 4322} 4323 4324 4325Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { 4326 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); 4327 Node** buffer = EnsureInputBufferSize(count + 1); 4328 MemsetPointer(buffer, input, count); 4329 buffer[count] = control; 4330 return graph()->NewNode(phi_op, count + 1, buffer, true); 4331} 4332 4333Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, 4334 Node* control) { 4335 const Operator* phi_op = common()->EffectPhi(count); 4336 Node** buffer = EnsureInputBufferSize(count + 1); 4337 MemsetPointer(buffer, input, count); 4338 buffer[count] = control; 4339 return graph()->NewNode(phi_op, count + 1, buffer, true); 4340} 4341 4342 4343Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { 4344 int inputs = control->op()->ControlInputCount() + 1; 4345 if (control->opcode() == IrOpcode::kLoop) { 4346 // Control node for loop exists, add input. 4347 const Operator* op = common()->Loop(inputs); 4348 control->AppendInput(graph_zone(), other); 4349 NodeProperties::ChangeOp(control, op); 4350 } else if (control->opcode() == IrOpcode::kMerge) { 4351 // Control node for merge exists, add input. 4352 const Operator* op = common()->Merge(inputs); 4353 control->AppendInput(graph_zone(), other); 4354 NodeProperties::ChangeOp(control, op); 4355 } else { 4356 // Control node is a singleton, introduce a merge. 4357 const Operator* op = common()->Merge(inputs); 4358 Node* merge_inputs[] = {control, other}; 4359 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); 4360 } 4361 return control; 4362} 4363 4364Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, 4365 Node* control) { 4366 int inputs = control->op()->ControlInputCount(); 4367 if (value->opcode() == IrOpcode::kEffectPhi && 4368 NodeProperties::GetControlInput(value) == control) { 4369 // Phi already exists, add input. 4370 value->InsertInput(graph_zone(), inputs - 1, other); 4371 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); 4372 } else if (value != other) { 4373 // Phi does not exist yet, introduce one. 4374 value = NewEffectPhi(inputs, value, control); 4375 value->ReplaceInput(inputs - 1, other); 4376 } 4377 return value; 4378} 4379 4380Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, 4381 Node* control) { 4382 int inputs = control->op()->ControlInputCount(); 4383 if (value->opcode() == IrOpcode::kPhi && 4384 NodeProperties::GetControlInput(value) == control) { 4385 // Phi already exists, add input. 4386 value->InsertInput(graph_zone(), inputs - 1, other); 4387 NodeProperties::ChangeOp( 4388 value, common()->Phi(MachineRepresentation::kTagged, inputs)); 4389 } else if (value != other) { 4390 // Phi does not exist yet, introduce one. 4391 value = NewPhi(inputs, value, control); 4392 value->ReplaceInput(inputs - 1, other); 4393 } 4394 return value; 4395} 4396 4397void BytecodeGraphBuilder::UpdateSourcePosition(int offset) { 4398 if (source_position_iterator().done()) return; 4399 if (source_position_iterator().code_offset() == offset) { 4400 source_positions_->SetCurrentPosition(SourcePosition( 4401 source_position_iterator().source_position().ScriptOffset(), 4402 start_position_.InliningId())); 4403 source_position_iterator().Advance(); 4404 } else { 4405 DCHECK_GT(source_position_iterator().code_offset(), offset); 4406 } 4407} 4408 4409void BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone, 4410 SharedFunctionInfoRef const& shared_info, 4411 FeedbackCellRef const& feedback_cell, 4412 BytecodeOffset osr_offset, JSGraph* jsgraph, 4413 CallFrequency const& invocation_frequency, 4414 SourcePositionTable* source_positions, 4415 int inlining_id, CodeKind code_kind, 4416 BytecodeGraphBuilderFlags flags, 4417 TickCounter* tick_counter, 4418 ObserveNodeInfo const& observe_node_info) { 4419 BytecodeGraphBuilder builder( 4420 broker, local_zone, broker->target_native_context(), shared_info, 4421 feedback_cell, osr_offset, jsgraph, invocation_frequency, 4422 source_positions, inlining_id, code_kind, flags, tick_counter, 4423 observe_node_info); 4424 builder.CreateGraph(); 4425} 4426 4427} // namespace compiler 4428} // namespace internal 4429} // namespace v8 4430