ast-graph-builder.cc 96.7 KB
Newer Older
1 2 3 4 5 6
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/ast-graph-builder.h"

7
#include "src/ast/compile-time-value.h"
8
#include "src/ast/scopes.h"
9
#include "src/compilation-info.h"
10
#include "src/compiler.h"
11
#include "src/compiler/ast-loop-assignment-analyzer.h"
12
#include "src/compiler/control-builders.h"
13
#include "src/compiler/linkage.h"
14
#include "src/compiler/machine-operator.h"
15
#include "src/compiler/node-matchers.h"
16
#include "src/compiler/node-properties.h"
17
#include "src/compiler/operator-properties.h"
18
#include "src/compiler/state-values-utils.h"
19
#include "src/feedback-vector.h"
20
#include "src/objects-inl.h"
21
#include "src/objects/literal-objects.h"
22 23 24 25 26

namespace v8 {
namespace internal {
namespace compiler {

27

28 29 30 31 32 33 34 35 36 37
// Each expression in the AST is evaluated in a specific context. This context
// decides how the evaluation result is passed up the visitor.
class AstGraphBuilder::AstContext BASE_EMBEDDED {
 public:
  bool IsEffect() const { return kind_ == Expression::kEffect; }
  bool IsValue() const { return kind_ == Expression::kValue; }
  bool IsTest() const { return kind_ == Expression::kTest; }

  // Plug a node into this expression context.  Call this function in tail
  // position in the Visit functions for expressions.
38
  virtual void ProduceValue(Expression* expr, Node* value) = 0;
39 40 41 42 43 44

  // Unplugs a node from this expression context.  Call this to retrieve the
  // result of another Visit function that already plugged the context.
  virtual Node* ConsumeValue() = 0;

  // Shortcut for "context->ProduceValue(context->ConsumeValue())".
45
  void ReplaceValue(Expression* expr) { ProduceValue(expr, ConsumeValue()); }
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

 protected:
  AstContext(AstGraphBuilder* owner, Expression::Context kind);
  virtual ~AstContext();

  AstGraphBuilder* owner() const { return owner_; }
  Environment* environment() const { return owner_->environment(); }

// We want to be able to assert, in a context-specific way, that the stack
// height makes sense when the context is filled.
#ifdef DEBUG
  int original_height_;
#endif

 private:
  Expression::Context kind_;
  AstGraphBuilder* owner_;
  AstContext* outer_;
};


// Context to evaluate expression for its side effects only.
68
class AstGraphBuilder::AstEffectContext final : public AstContext {
69 70 71
 public:
  explicit AstEffectContext(AstGraphBuilder* owner)
      : AstContext(owner, Expression::kEffect) {}
72
  ~AstEffectContext() final;
73
  void ProduceValue(Expression* expr, Node* value) final;
74
  Node* ConsumeValue() final;
75 76 77 78
};


// Context to evaluate expression for its value (and side effects).
79
class AstGraphBuilder::AstValueContext final : public AstContext {
80 81 82
 public:
  explicit AstValueContext(AstGraphBuilder* owner)
      : AstContext(owner, Expression::kValue) {}
83
  ~AstValueContext() final;
84
  void ProduceValue(Expression* expr, Node* value) final;
85
  Node* ConsumeValue() final;
86 87 88 89
};


// Context to evaluate expression for a condition value (and side effects).
90
class AstGraphBuilder::AstTestContext final : public AstContext {
91
 public:
92 93
  explicit AstTestContext(AstGraphBuilder* owner)
      : AstContext(owner, Expression::kTest) {}
94
  ~AstTestContext() final;
95
  void ProduceValue(Expression* expr, Node* value) final;
96
  Node* ConsumeValue() final;
97 98 99 100 101 102 103 104
};


// Scoped class tracking context objects created by the visitor. Represents
// mutations of the context chain within the function body and allows to
// change the current {scope} and {context} during visitation.
class AstGraphBuilder::ContextScope BASE_EMBEDDED {
 public:
105 106 107 108
  ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
      : builder_(builder),
        outer_(builder->execution_context()),
        scope_(scope),
109
        depth_(builder_->environment()->context_chain_length()) {
110 111
    builder_->environment()->PushContext(context);  // Push.
    builder_->set_execution_context(this);
112 113 114
  }

  ~ContextScope() {
115
    builder_->set_execution_context(outer_);  // Pop.
116
    builder_->environment()->PopContext();
117
    CHECK_EQ(depth_, builder_->environment()->context_chain_length());
118 119 120 121 122 123
  }

  // Current scope during visitation.
  Scope* scope() const { return scope_; }

 private:
124 125
  AstGraphBuilder* builder_;
  ContextScope* outer_;
126
  Scope* scope_;
127
  int depth_;
128 129 130
};


131 132 133 134 135 136 137 138 139
// Scoped class tracking control statements entered by the visitor. There are
// different types of statements participating in this stack to properly track
// local as well as non-local control flow:
//  - IterationStatement : Allows proper 'break' and 'continue' behavior.
//  - BreakableStatement : Allows 'break' from block and switch statements.
//  - TryCatchStatement  : Intercepts 'throw' and implicit exceptional edges.
//  - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
class AstGraphBuilder::ControlScope BASE_EMBEDDED {
 public:
140
  explicit ControlScope(AstGraphBuilder* builder)
141
      : builder_(builder),
142
        outer_(builder->execution_control()),
143
        context_length_(builder->environment()->context_chain_length()),
144
        stack_height_(builder->environment()->stack_height()) {
145 146 147 148
    builder_->set_execution_control(this);  // Push.
  }

  virtual ~ControlScope() {
149
    builder_->set_execution_control(outer_);  // Pop.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
  }

  // Either 'break' or 'continue' to the target statement.
  void BreakTo(BreakableStatement* target);
  void ContinueTo(BreakableStatement* target);

  // Either 'return' or 'throw' the given value.
  void ReturnValue(Node* return_value);
  void ThrowValue(Node* exception_value);

 protected:
  enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };

  // Performs one of the above commands on this stack of control scopes. This
  // walks through the stack giving each scope a chance to execute or defer the
  // given command by overriding the {Execute} method appropriately. Note that
  // this also drops extra operands from the environment for each skipped scope.
  void PerformCommand(Command cmd, Statement* target, Node* value);

  // Interface to execute a given command in this scope. Returning {true} here
  // indicates successful execution whereas {false} requests to skip scope.
171
  virtual bool Execute(Command cmd, Statement* target, Node** value) {
172 173 174
    // For function-level control.
    switch (cmd) {
      case CMD_THROW:
175
        builder()->BuildThrow(*value);
176 177
        return true;
      case CMD_RETURN:
178
        builder()->BuildReturn(*value);
179 180 181 182 183 184 185 186 187 188
        return true;
      case CMD_BREAK:
      case CMD_CONTINUE:
        break;
    }
    return false;
  }

  Environment* environment() { return builder_->environment(); }
  AstGraphBuilder* builder() const { return builder_; }
189
  int context_length() const { return context_length_; }
190
  int stack_height() const { return stack_height_; }
191 192 193

 private:
  AstGraphBuilder* builder_;
194
  ControlScope* outer_;
195
  int context_length_;
196
  int stack_height_;
197 198 199 200 201 202 203 204
};


// Control scope implementation for a BreakableStatement.
class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
 public:
  ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
                           ControlBuilder* control)
205
      : ControlScope(owner), target_(target), control_(control) {}
206 207

 protected:
208
  bool Execute(Command cmd, Statement* target, Node** value) override {
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    if (target != target_) return false;  // We are not the command target.
    switch (cmd) {
      case CMD_BREAK:
        control_->Break();
        return true;
      case CMD_CONTINUE:
      case CMD_THROW:
      case CMD_RETURN:
        break;
    }
    return false;
  }

 private:
  BreakableStatement* target_;
  ControlBuilder* control_;
};


// Control scope implementation for an IterationStatement.
class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
 public:
  ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
232 233
                           LoopBuilder* control)
      : ControlScope(owner), target_(target), control_(control) {}
234 235

 protected:
236 237 238 239 240
  bool Execute(Command cmd, Statement* target, Node** value) override {
    if (target != target_) {
      control_->ExitLoop(value);
      return false;
    }
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
    switch (cmd) {
      case CMD_BREAK:
        control_->Break();
        return true;
      case CMD_CONTINUE:
        control_->Continue();
        return true;
      case CMD_THROW:
      case CMD_RETURN:
        break;
    }
    return false;
  }

 private:
  BreakableStatement* target_;
  LoopBuilder* control_;
};

260
AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
261 262
                                 JSGraph* jsgraph,
                                 CallFrequency invocation_frequency,
263
                                 LoopAssignmentAnalysis* loop)
264 265
    : isolate_(info->isolate()),
      local_zone_(local_zone),
266 267
      info_(info),
      jsgraph_(jsgraph),
268
      invocation_frequency_(invocation_frequency),
269 270
      environment_(nullptr),
      ast_context_(nullptr),
271
      globals_(0, local_zone),
272
      execution_control_(nullptr),
273 274 275
      execution_context_(nullptr),
      input_buffer_size_(0),
      input_buffer_(nullptr),
276
      exit_controls_(local_zone),
277
      loop_assignment_analysis_(loop),
278
      state_values_cache_(jsgraph) {
279
  InitializeAstVisitor(info->isolate());
280 281 282
}


283
Node* AstGraphBuilder::GetFunctionClosureForContext() {
284
  DeclarationScope* closure_scope = current_scope()->GetClosureScope();
285 286
  if (closure_scope->is_script_scope() ||
      closure_scope->is_module_scope()) {
287 288
    // Contexts nested in the native context have a canonical empty function as
    // their closure, not the anonymous closure containing the global code.
289
    return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
290 291 292 293 294
  } else if (closure_scope->is_eval_scope()) {
    // Contexts nested inside eval code have the same closure as the context
    // calling eval, not the anonymous closure containing the eval code.
    const Operator* op =
        javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
295
    return NewNode(op);
296
  } else {
297
    DCHECK(closure_scope->is_function_scope());
298 299 300 301 302
    return GetFunctionClosure();
  }
}


303 304
Node* AstGraphBuilder::GetFunctionClosure() {
  if (!function_closure_.is_set()) {
305 306
    int index = Linkage::kJSCallClosureParamIndex;
    const Operator* op = common()->Parameter(index, "%closure");
307
    Node* node = NewNode(op, graph()->start());
308 309 310 311 312 313
    function_closure_.set(node);
  }
  return function_closure_.get();
}


314 315
Node* AstGraphBuilder::GetFunctionContext() {
  if (!function_context_.is_set()) {
316 317 318
    int params = info()->num_parameters_including_this();
    int index = Linkage::GetJSCallContextParamIndex(params);
    const Operator* op = common()->Parameter(index, "%context");
319 320 321 322
    Node* node = NewNode(op, graph()->start());
    function_context_.set(node);
  }
  return function_context_.get();
323 324
}

325 326 327 328 329 330 331 332 333 334 335 336
Node* AstGraphBuilder::GetEmptyFrameState() {
  if (!empty_frame_state_.is_set()) {
    const Operator* op = common()->FrameState(
        BailoutId::None(), OutputFrameStateCombine::Ignore(), nullptr);
    Node* node = graph()->NewNode(
        op, jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
        jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
        jsgraph()->UndefinedConstant(), graph()->start());
    empty_frame_state_.set(node);
  }
  return empty_frame_state_.get();
}
337

338
bool AstGraphBuilder::CreateGraph(bool stack_check) {
339
  DeclarationScope* scope = info()->scope();
340
  DCHECK_NOT_NULL(graph());
341

342
  // Set up the basic structure of the graph. Outputs for {Start} are the formal
343 344 345
  // parameters (including the receiver) plus new target, number of arguments,
  // context and closure.
  int actual_parameter_count = info()->num_parameters_including_this() + 4;
346
  graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
347 348

  // Initialize the top-level environment.
349
  Environment env(this, scope, graph()->start());
350 351
  set_environment(&env);

352 353 354 355 356 357
  if (info()->is_osr()) {
    // Use OSR normal entry as the start of the top-level environment.
    // It will be replaced with {Dead} after typing and optimizations.
    NewNode(common()->OsrNormalEntry());
  }

358
  // Initialize the incoming context.
359
  ContextScope incoming(this, scope, GetFunctionContext());
360

361 362 363
  // Initialize control scope.
  ControlScope control(this);

364 365 366
  // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
  // not {the_hole}, because for derived classes {this} has a TDZ and the
  // JSConstructStubForDerived magically passes {the_hole} as a receiver.
367
  if (scope->has_this_declaration() && scope->receiver()->mode() == CONST) {
368 369 370
    env.RawParameterBind(0, jsgraph()->TheHoleConstant());
  }

371
  if (scope->NeedsContext()) {
372 373
    // Push a new inner context scope for the current activation.
    Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
374
    ContextScope top_context(this, scope, inner_context);
375
    CreateGraphBody(stack_check);
376 377
  } else {
    // Simply use the outer function context in building the graph.
378
    CreateGraphBody(stack_check);
379 380 381
  }

  // Finish the basic structure of the graph.
382 383 384 385 386
  DCHECK_NE(0u, exit_controls_.size());
  int const input_count = static_cast<int>(exit_controls_.size());
  Node** const inputs = &exit_controls_.front();
  Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
  graph()->SetEnd(end);
387

388 389
  // Failures indicated by stack overflow.
  return !HasStackOverflow();
390
}
391 392


393
void AstGraphBuilder::CreateGraphBody(bool stack_check) {
394
  DeclarationScope* scope = info()->scope();
395

396 397 398
  // Build the arguments object if it is used.
  BuildArgumentsObject(scope->arguments());

399 400 401 402
  // We don't support new.target and rest parameters here.
  DCHECK_NULL(scope->new_target_var());
  DCHECK_NULL(scope->rest_parameter());
  DCHECK_NULL(scope->this_function_var());
403

404 405
  // Emit tracing call if requested to do so.
  if (FLAG_trace) {
406
    NewNode(javascript()->CallRuntime(Runtime::kTraceEnter));
407 408 409 410 411
  }

  // Visit declarations within the function scope.
  VisitDeclarations(scope->declarations());

412
  // Build a stack-check before the body.
413
  if (stack_check) {
414
    NewNode(javascript()->StackCheck());
415
  }
416 417

  // Visit statements in the function body.
418
  VisitStatements(info()->literal()->body());
419 420

  // Return 'undefined' in case we can fall off the end.
421
  BuildReturn(jsgraph()->UndefinedConstant());
422 423 424
}


425 426
static const char* GetDebugParameterName(Zone* zone, DeclarationScope* scope,
                                         int index) {
427 428 429 430 431 432 433 434 435 436 437 438
#if DEBUG
  const AstRawString* name = scope->parameter(index)->raw_name();
  if (name && name->length() > 0) {
    char* data = zone->NewArray<char>(name->length() + 1);
    data[name->length()] = 0;
    memcpy(data, name->raw_data(), name->length());
    return data;
  }
#endif
  return nullptr;
}

439
AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
440
                                          DeclarationScope* scope,
441
                                          Node* control_dependency)
442
    : builder_(builder),
443 444
      parameters_count_(scope->num_parameters() + 1),
      locals_count_(scope->num_stack_slots()),
445
      values_(builder_->local_zone()),
446
      contexts_(builder_->local_zone()),
447 448 449 450 451
      control_dependency_(control_dependency),
      effect_dependency_(control_dependency),
      parameters_node_(nullptr),
      locals_node_(nullptr),
      stack_node_(nullptr) {
452
  DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
453 454

  // Bind the receiver variable.
455 456
  int param_num = 0;
  if (builder->info()->is_this_defined()) {
457 458
    const Operator* op = common()->Parameter(param_num++, "%this");
    Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
459 460 461 462
    values()->push_back(receiver);
  } else {
    values()->push_back(builder->jsgraph()->UndefinedConstant());
  }
463 464

  // Bind all parameter variables. The parameter indices are shifted by 1
465 466
  // (receiver is variable index -1 but {Parameter} node index 0 and located at
  // index 0 in the environment).
467
  for (int i = 0; i < scope->num_parameters(); ++i) {
468
    const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
469 470
    const Operator* op = common()->Parameter(param_num++, debug_name);
    Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
471
    values()->push_back(parameter);
472 473 474 475 476 477 478
  }

  // Bind all local variables to undefined.
  Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
  values()->insert(values()->end(), locals_count(), undefined_constant);
}

479
AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy)
480 481 482 483
    : builder_(copy->builder_),
      parameters_count_(copy->parameters_count_),
      locals_count_(copy->locals_count_),
      values_(copy->zone()),
484
      contexts_(copy->zone()),
485 486 487 488 489 490 491 492
      control_dependency_(copy->control_dependency_),
      effect_dependency_(copy->effect_dependency_),
      parameters_node_(copy->parameters_node_),
      locals_node_(copy->locals_node_),
      stack_node_(copy->stack_node_) {
  const size_t kStackEstimate = 7;  // optimum from experimentation!
  values_.reserve(copy->values_.size() + kStackEstimate);
  values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
493 494 495
  contexts_.reserve(copy->contexts_.size());
  contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
                   copy->contexts_.end());
496 497 498 499 500 501
}


void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
  DCHECK(variable->IsStackAllocated());
  if (variable->IsParameter()) {
502 503
    // The parameter indices are shifted by 1 (receiver is variable
    // index -1 but located at index 0 in the environment).
504 505 506 507 508 509 510 511 512 513 514
    values()->at(variable->index() + 1) = node;
  } else {
    DCHECK(variable->IsStackLocal());
    values()->at(variable->index() + parameters_count_) = node;
  }
}


Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
  DCHECK(variable->IsStackAllocated());
  if (variable->IsParameter()) {
515 516
    // The parameter indices are shifted by 1 (receiver is variable
    // index -1 but located at index 0 in the environment).
517 518 519 520 521 522 523 524
    return values()->at(variable->index() + 1);
  } else {
    DCHECK(variable->IsStackLocal());
    return values()->at(variable->index() + parameters_count_);
  }
}


525 526 527 528 529 530 531 532 533 534 535 536
void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
  DCHECK_LT(index, parameters_count());
  values()->at(index) = node;
}


Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
  DCHECK_LT(index, parameters_count());
  return values()->at(index);
}


537 538
AstGraphBuilder::Environment*
AstGraphBuilder::Environment::CopyForConditional() {
539
  return new (zone()) Environment(this);
540 541 542 543 544
}


AstGraphBuilder::Environment*
AstGraphBuilder::Environment::CopyAsUnreachable() {
545
  Environment* env = new (zone()) Environment(this);
546 547 548 549
  env->MarkAsUnreachable();
  return env;
}

550
AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForOsrEntry() {
551
  return new (zone()) Environment(this);
552
}
553

554 555
AstGraphBuilder::Environment*
AstGraphBuilder::Environment::CopyAndShareLiveness() {
556
  Environment* env = new (zone()) Environment(this);
557
  return env;
558
}
559 560


561 562
AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
    BitVector* assigned, bool is_osr) {
563 564 565 566 567 568 569 570 571
  PrepareForLoop(assigned);
  Environment* loop = CopyAndShareLiveness();
  if (is_osr) {
    // Create and merge the OSR entry if necessary.
    Environment* osr_env = CopyForOsrEntry();
    osr_env->PrepareForOsrEntry();
    loop->Merge(osr_env);
  }
  return loop;
572 573 574
}


575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
void AstGraphBuilder::Environment::PrepareForLoopExit(
    Node* loop, BitVector* assigned_variables) {
  if (IsMarkedAsUnreachable()) return;

  DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);

  Node* control = GetControlDependency();

  // Create the loop exit node.
  Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
  UpdateControlDependency(loop_exit);

  // Rename the environmnent values.
  for (size_t i = 0; i < values()->size(); i++) {
    if (assigned_variables == nullptr ||
        static_cast<int>(i) >= assigned_variables->length() ||
        assigned_variables->Contains(static_cast<int>(i))) {
      Node* rename = graph()->NewNode(common()->LoopExitValue(), (*values())[i],
                                      loop_exit);
      (*values())[i] = rename;
    }
  }

  // Rename the effect.
  Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
                                         GetEffectDependency(), loop_exit);
  UpdateEffectDependency(effect_rename);
}
603

604

605
AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
606 607
                                        Expression::Context kind)
    : kind_(kind), owner_(own), outer_(own->ast_context()) {
608 609 610 611 612 613 614 615 616 617 618 619 620
  owner()->set_ast_context(this);  // Push.
#ifdef DEBUG
  original_height_ = environment()->stack_height();
#endif
}


AstGraphBuilder::AstContext::~AstContext() {
  owner()->set_ast_context(outer_);  // Pop.
}


AstGraphBuilder::AstEffectContext::~AstEffectContext() {
621
  DCHECK(environment()->stack_height() == original_height_);
622 623 624 625
}


AstGraphBuilder::AstValueContext::~AstValueContext() {
626
  DCHECK(environment()->stack_height() == original_height_ + 1);
627 628 629 630
}


AstGraphBuilder::AstTestContext::~AstTestContext() {
631
  DCHECK(environment()->stack_height() == original_height_ + 1);
632 633
}

634 635
void AstGraphBuilder::AstEffectContext::ProduceValue(Expression* expr,
                                                     Node* value) {
636 637 638
  // The value is ignored.
}

639 640
void AstGraphBuilder::AstValueContext::ProduceValue(Expression* expr,
                                                    Node* value) {
641 642 643
  environment()->Push(value);
}

644 645
void AstGraphBuilder::AstTestContext::ProduceValue(Expression* expr,
                                                   Node* value) {
646
  environment()->Push(owner()->BuildToBoolean(value));
647 648 649
}


650
Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
651 652 653 654 655 656 657 658 659 660 661 662


Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
  return environment()->Pop();
}


Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
  return environment()->Pop();
}


663 664 665 666 667
Scope* AstGraphBuilder::current_scope() const {
  return execution_context_->scope();
}


668
Node* AstGraphBuilder::current_context() const {
669
  return environment()->Context();
670 671 672
}


673 674 675 676 677
void AstGraphBuilder::ControlScope::PerformCommand(Command command,
                                                   Statement* target,
                                                   Node* value) {
  Environment* env = environment()->CopyAsUnreachable();
  ControlScope* current = this;
678
  while (current != nullptr) {
679 680
    environment()->TrimStack(current->stack_height());
    environment()->TrimContextChain(current->context_length());
681
    if (current->Execute(command, target, &value)) break;
682
    current = current->outer_;
683
  }
684
  builder()->set_environment(env);
685
  DCHECK_NOT_NULL(current);  // Always handled (unless stack is malformed).
686 687 688 689
}


void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
690
  PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
691 692 693
}


694
void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
695
  PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
696 697 698
}


699 700 701 702 703 704 705
void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
  PerformCommand(CMD_RETURN, nullptr, return_value);
}


void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
  PerformCommand(CMD_THROW, nullptr, exception_value);
706 707 708 709
}


void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
710
  if (expr == nullptr) {
711 712 713 714 715 716
    return environment()->Push(jsgraph()->NullConstant());
  }
  VisitForValue(expr);
}


717
void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
718
  if (expr == nullptr) {
719 720 721 722 723 724
    return environment()->Push(jsgraph()->TheHoleConstant());
  }
  VisitForValue(expr);
}


725 726 727 728 729 730 731 732
void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
  for (int i = 0; i < exprs->length(); ++i) {
    VisitForValue(exprs->at(i));
  }
}


void AstGraphBuilder::VisitForValue(Expression* expr) {
733
  AstValueContext for_value(this);
734
  if (!CheckStackOverflow()) {
735
    VisitNoStackOverflowCheck(expr);
736
  } else {
737
    ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
738 739 740 741 742
  }
}


void AstGraphBuilder::VisitForEffect(Expression* expr) {
743
  AstEffectContext for_effect(this);
744
  if (!CheckStackOverflow()) {
745
    VisitNoStackOverflowCheck(expr);
746
  } else {
747
    ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
748 749 750 751 752
  }
}


void AstGraphBuilder::VisitForTest(Expression* expr) {
753
  AstTestContext for_condition(this);
754
  if (!CheckStackOverflow()) {
755
    VisitNoStackOverflowCheck(expr);
756
  } else {
757
    ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
758 759 760 761 762 763 764
  }
}


void AstGraphBuilder::Visit(Expression* expr) {
  // Reuses enclosing AstContext.
  if (!CheckStackOverflow()) {
765
    VisitNoStackOverflowCheck(expr);
766
  } else {
767
    ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
768 769 770 771 772 773 774
  }
}


void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
  Variable* variable = decl->proxy()->var();
  switch (variable->location()) {
775
    case VariableLocation::UNALLOCATED: {
776
      DCHECK(!variable->binding_needs_init());
777
      globals()->push_back(variable->name());
778
      FeedbackSlot slot = decl->proxy()->VariableFeedbackSlot();
779 780
      DCHECK(!slot.IsInvalid());
      globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
781
      globals()->push_back(isolate()->factory()->undefined_value());
782
      globals()->push_back(isolate()->factory()->undefined_value());
783
      break;
784
    }
785 786
    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL:
787 788 789 790 791
      if (variable->binding_needs_init()) {
        Node* value = jsgraph()->TheHoleConstant();
        environment()->Bind(variable, value);
      }
      break;
792
    case VariableLocation::CONTEXT:
793 794 795 796 797
      if (variable->binding_needs_init()) {
        Node* value = jsgraph()->TheHoleConstant();
        const Operator* op = javascript()->StoreContext(0, variable->index());
        NewNode(op, value);
      }
798
      break;
799
    case VariableLocation::LOOKUP:
800 801
    case VariableLocation::MODULE:
      UNREACHABLE();
802 803 804 805 806 807 808
  }
}


void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
  Variable* variable = decl->proxy()->var();
  switch (variable->location()) {
809
    case VariableLocation::UNALLOCATED: {
810 811
      Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
          decl->fun(), info()->script(), info());
812 813
      // Check for stack-overflow exception.
      if (function.is_null()) return SetStackOverflow();
814
      globals()->push_back(variable->name());
815
      FeedbackSlot slot = decl->proxy()->VariableFeedbackSlot();
816 817
      DCHECK(!slot.IsInvalid());
      globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
818 819 820 821 822 823

      // We need the slot where the literals array lives, too.
      slot = decl->fun()->LiteralFeedbackSlot();
      DCHECK(!slot.IsInvalid());
      globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));

824
      globals()->push_back(function);
825 826
      break;
    }
827 828
    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL: {
829 830 831 832 833
      VisitForValue(decl->fun());
      Node* value = environment()->Pop();
      environment()->Bind(variable, value);
      break;
    }
834
    case VariableLocation::CONTEXT: {
835 836
      VisitForValue(decl->fun());
      Node* value = environment()->Pop();
837
      const Operator* op = javascript()->StoreContext(0, variable->index());
838
      NewNode(op, value);
839 840
      break;
    }
841
    case VariableLocation::LOOKUP:
842 843
    case VariableLocation::MODULE:
      UNREACHABLE();
844 845 846 847 848 849
  }
}


void AstGraphBuilder::VisitBlock(Block* stmt) {
  BlockBuilder block(this);
850
  ControlScopeForBreakable scope(this, stmt, &block);
851 852
  if (stmt->labels() != nullptr) block.BeginBlock();
  if (stmt->scope() == nullptr) {
853 854 855 856
    // Visit statements in the same scope, no declarations.
    VisitStatements(stmt->statements());
  } else {
    // Visit declarations and statements in a block scope.
857
    if (stmt->scope()->NeedsContext()) {
858 859 860 861 862 863 864 865
      Node* context = BuildLocalBlockContext(stmt->scope());
      ContextScope scope(this, stmt->scope(), context);
      VisitDeclarations(stmt->scope()->declarations());
      VisitStatements(stmt->statements());
    } else {
      VisitDeclarations(stmt->scope()->declarations());
      VisitStatements(stmt->statements());
    }
866
  }
867
  if (stmt->labels() != nullptr) block.EndBlock();
868 869 870 871 872 873 874 875 876 877 878 879 880
}


void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
  VisitForEffect(stmt->expression());
}


void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
  // Do nothing.
}


881 882 883 884 885 886
void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
    SloppyBlockFunctionStatement* stmt) {
  Visit(stmt->statement());
}


887 888 889 890 891 892 893 894 895 896 897 898 899 900
void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
  IfBuilder compare_if(this);
  VisitForTest(stmt->condition());
  Node* condition = environment()->Pop();
  compare_if.If(condition);
  compare_if.Then();
  Visit(stmt->then_statement());
  compare_if.Else();
  Visit(stmt->else_statement());
  compare_if.End();
}


void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
901
  execution_control()->ContinueTo(stmt->target());
902 903 904 905
}


void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
906
  execution_control()->BreakTo(stmt->target());
907 908 909 910 911 912
}


void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
  VisitForValue(stmt->expression());
  Node* result = environment()->Pop();
913
  execution_control()->ReturnValue(result);
914 915 916 917
}


void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
918 919
  // Dynamic scoping is supported only by going through Ignition first.
  UNREACHABLE();
920 921 922 923 924 925
}


void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
  ZoneList<CaseClause*>* clauses = stmt->cases();
  SwitchBuilder compare_switch(this, clauses->length());
926
  ControlScopeForBreakable scope(this, stmt, &compare_switch);
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
  compare_switch.BeginSwitch();
  int default_index = -1;

  // Keep the switch value on the stack until a case matches.
  VisitForValue(stmt->tag());

  // Iterate over all cases and create nodes for label comparison.
  for (int i = 0; i < clauses->length(); i++) {
    CaseClause* clause = clauses->at(i);

    // The default is not a test, remember index.
    if (clause->is_default()) {
      default_index = i;
      continue;
    }

    // Create nodes to perform label comparison as if via '==='. The switch
    // value is still on the operand stack while the label is evaluated.
    VisitForValue(clause->label());
    Node* label = environment()->Pop();
947
    Node* tag = environment()->Top();
948

949
    CompareOperationHint hint = CompareOperationHint::kAny;
950
    const Operator* op = javascript()->StrictEqual(hint);
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978
    Node* condition = NewNode(op, tag, label);
    compare_switch.BeginLabel(i, condition);

    // Discard the switch value at label match.
    environment()->Pop();
    compare_switch.EndLabel();
  }

  // Discard the switch value and mark the default case.
  environment()->Pop();
  if (default_index >= 0) {
    compare_switch.DefaultAt(default_index);
  }

  // Iterate over all cases and create nodes for case bodies.
  for (int i = 0; i < clauses->length(); i++) {
    CaseClause* clause = clauses->at(i);
    compare_switch.BeginCase(i);
    VisitStatements(clause->statements());
    compare_switch.EndCase();
  }

  compare_switch.EndSwitch();
}


void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
  LoopBuilder while_loop(this);
979
  while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
980
  VisitIterationBody(stmt, &while_loop);
981 982 983 984 985 986 987 988 989 990
  while_loop.EndBody();
  VisitForTest(stmt->cond());
  Node* condition = environment()->Pop();
  while_loop.BreakUnless(condition);
  while_loop.EndLoop();
}


void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
  LoopBuilder while_loop(this);
991
  while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
992 993 994
  VisitForTest(stmt->cond());
  Node* condition = environment()->Pop();
  while_loop.BreakUnless(condition);
995
  VisitIterationBody(stmt, &while_loop);
996 997 998 999 1000 1001 1002 1003
  while_loop.EndBody();
  while_loop.EndLoop();
}


void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
  LoopBuilder for_loop(this);
  VisitIfNotNull(stmt->init());
1004
  for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1005
  if (stmt->cond() != nullptr) {
1006 1007 1008
    VisitForTest(stmt->cond());
    Node* condition = environment()->Pop();
    for_loop.BreakUnless(condition);
1009 1010
  } else {
    for_loop.BreakUnless(jsgraph()->TrueConstant());
1011
  }
1012
  VisitIterationBody(stmt, &for_loop);
1013 1014 1015 1016 1017 1018 1019
  for_loop.EndBody();
  VisitIfNotNull(stmt->next());
  for_loop.EndLoop();
}


void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1020 1021
  // Only the BytecodeGraphBuilder supports for-in.
  return SetStackOverflow();
1022 1023 1024
}


1025
void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
1026 1027
  // Iterator looping is supported only by going through Ignition first.
  UNREACHABLE();
1028 1029 1030 1031
}


void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1032 1033
  // Exception handling is supported only by going through Ignition first.
  UNREACHABLE();
1034 1035 1036 1037
}


void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1038 1039
  // Exception handling is supported only by going through Ignition first.
  UNREACHABLE();
1040 1041 1042 1043
}


void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1044 1045
  // Debugger statement is supported only by going through Ignition first.
  UNREACHABLE();
1046 1047 1048 1049
}


void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1050 1051 1052 1053
  // Find or build a shared function info.
  Handle<SharedFunctionInfo> shared_info =
      Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
  CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
1054 1055

  // Create node to instantiate a new closure.
1056
  PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1057 1058 1059
  VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
  const Operator* op =
      javascript()->CreateClosure(shared_info, pair, pretenure);
1060
  Node* value = NewNode(op);
1061
  ast_context()->ProduceValue(expr, value);
1062 1063
}

1064
void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); }
arv@chromium.org's avatar
arv@chromium.org committed
1065

1066 1067 1068 1069 1070
void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
  UNREACHABLE();
}


1071 1072 1073
void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
  VisitBlock(expr->block());
  VisitVariableProxy(expr->result());
1074
  ast_context()->ReplaceValue(expr);
1075 1076 1077
}


1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
void AstGraphBuilder::VisitConditional(Conditional* expr) {
  IfBuilder compare_if(this);
  VisitForTest(expr->condition());
  Node* condition = environment()->Pop();
  compare_if.If(condition);
  compare_if.Then();
  Visit(expr->then_expression());
  compare_if.Else();
  Visit(expr->else_expression());
  compare_if.End();
1088 1089 1090 1091 1092
  // Skip plugging AST evaluation contexts of the test kind. This is to stay in
  // sync with full codegen which doesn't prepare the proper bailout point (see
  // the implementation of FullCodeGenerator::VisitForControl).
  if (ast_context()->IsTest()) return;
  ast_context()->ReplaceValue(expr);
1093 1094 1095 1096
}


void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
1097
  VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
1098
  Node* value = BuildVariableLoad(expr->var(), pair);
1099
  ast_context()->ProduceValue(expr, value);
1100 1101 1102 1103 1104
}


void AstGraphBuilder::VisitLiteral(Literal* expr) {
  Node* value = jsgraph()->Constant(expr->value());
1105
  ast_context()->ProduceValue(expr, value);
1106 1107 1108 1109
}


void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1110
  Node* closure = GetFunctionClosure();
1111 1112

  // Create node to materialize a regular expression literal.
1113
  const Operator* op = javascript()->CreateLiteralRegExp(
1114
      expr->pattern(), expr->flags(),
1115
      FeedbackVector::GetIndex(expr->literal_slot()));
1116
  Node* literal = NewNode(op, closure);
1117
  ast_context()->ProduceValue(expr, literal);
1118 1119 1120 1121
}


void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1122
  Node* closure = GetFunctionClosure();
1123 1124

  // Create node to deep-copy the literal boilerplate.
1125
  const Operator* op = javascript()->CreateLiteralObject(
1126
      expr->GetOrBuildConstantProperties(isolate()), expr->ComputeFlags(true),
1127
      FeedbackVector::GetIndex(expr->literal_slot()), expr->properties_count());
1128
  Node* literal = NewNode(op, closure);
1129 1130 1131 1132 1133 1134

  // The object is expected on the operand stack during computation of the
  // property values and is the value of the entire expression.
  environment()->Push(literal);

  // Create nodes to store computed values into the literal.
1135
  AccessorTable accessor_table(local_zone());
1136 1137
  for (int i = 0; i < expr->properties()->length(); i++) {
    ObjectLiteral::Property* property = expr->properties()->at(i);
1138
    DCHECK(!property->is_computed_name());
1139 1140
    if (property->IsCompileTimeValue()) continue;

arv's avatar
arv committed
1141
    Literal* key = property->key()->AsLiteral();
1142
    switch (property->kind()) {
1143
      case ObjectLiteral::Property::SPREAD:
1144 1145 1146
      case ObjectLiteral::Property::CONSTANT:
        UNREACHABLE();
      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1147
        DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1148 1149 1150 1151
      // Fall through.
      case ObjectLiteral::Property::COMPUTED: {
        // It is safe to use [[Put]] here because the boilerplate already
        // contains computed properties with an uninitialized value.
1152 1153
        if (key->IsStringLiteral()) {
          DCHECK(key->IsPropertyName());
1154 1155 1156
          if (property->emit_store()) {
            VisitForValue(property->value());
            Node* value = environment()->Pop();
1157
            Node* literal = environment()->Top();
1158
            Handle<Name> name = key->AsPropertyName();
1159
            VectorSlotPair feedback =
1160
                CreateVectorSlotPair(property->GetSlot(0));
1161
            BuildNamedStoreOwn(literal, name, value, feedback);
1162
            BuildSetHomeObject(value, literal, property, 1);
1163 1164 1165 1166 1167
          } else {
            VisitForEffect(property->value());
          }
          break;
        }
1168
        environment()->Push(environment()->Top());  // Duplicate receiver.
1169 1170 1171 1172 1173 1174
        VisitForValue(property->key());
        VisitForValue(property->value());
        Node* value = environment()->Pop();
        Node* key = environment()->Pop();
        Node* receiver = environment()->Pop();
        if (property->emit_store()) {
1175
          Node* language = jsgraph()->Constant(SLOPPY);
1176
          const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
1177
          NewNode(op, receiver, key, value, language);
1178
          BuildSetHomeObject(value, receiver, property);
1179 1180 1181 1182
        }
        break;
      }
      case ObjectLiteral::Property::PROTOTYPE: {
1183
        environment()->Push(environment()->Top());  // Duplicate receiver.
1184 1185 1186
        VisitForValue(property->value());
        Node* value = environment()->Pop();
        Node* receiver = environment()->Pop();
1187 1188
        DCHECK(property->emit_store());
        const Operator* op =
1189
            javascript()->CallRuntime(Runtime::kInternalSetPrototype);
1190
        NewNode(op, receiver, value);
1191 1192 1193
        break;
      }
      case ObjectLiteral::Property::GETTER:
1194
        if (property->emit_store()) {
1195 1196
          AccessorTable::Iterator it = accessor_table.lookup(key);
          it->second->getter = property;
1197
        }
1198 1199
        break;
      case ObjectLiteral::Property::SETTER:
1200
        if (property->emit_store()) {
1201 1202
          AccessorTable::Iterator it = accessor_table.lookup(key);
          it->second->setter = property;
1203
        }
1204 1205 1206 1207 1208 1209
        break;
    }
  }

  // Create nodes to define accessors, using only a single call to the runtime
  // for each pair of corresponding getters and setters.
1210
  literal = environment()->Top();  // Reload from operand stack.
1211 1212 1213
  for (AccessorTable::Iterator it = accessor_table.begin();
       it != accessor_table.end(); ++it) {
    VisitForValue(it->first);
1214 1215
    VisitObjectLiteralAccessor(literal, it->second->getter);
    VisitObjectLiteralAccessor(literal, it->second->setter);
1216 1217 1218 1219
    Node* setter = environment()->Pop();
    Node* getter = environment()->Pop();
    Node* name = environment()->Pop();
    Node* attr = jsgraph()->Constant(NONE);
1220
    const Operator* op =
1221
        javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
1222
    NewNode(op, literal, name, getter, setter, attr);
1223
  }
1224
  ast_context()->ProduceValue(expr, environment()->Pop());
1225 1226 1227
}


1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
void AstGraphBuilder::VisitObjectLiteralAccessor(
    Node* home_object, ObjectLiteralProperty* property) {
  if (property == nullptr) {
    VisitForValueOrNull(nullptr);
  } else {
    VisitForValue(property->value());
    BuildSetHomeObject(environment()->Top(), home_object, property);
  }
}


1239
void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1240
  Node* closure = GetFunctionClosure();
1241 1242

  // Create node to deep-copy the literal boilerplate.
1243
  const Operator* op = javascript()->CreateLiteralArray(
1244
      expr->GetOrBuildConstantElements(isolate()), expr->ComputeFlags(true),
1245
      FeedbackVector::GetIndex(expr->literal_slot()), expr->values()->length());
1246
  Node* literal = NewNode(op, closure);
1247

1248 1249
  // The array is expected on the operand stack during computation of the
  // element values.
1250 1251 1252 1253
  environment()->Push(literal);

  // Create nodes to evaluate all the non-constant subexpressions and to store
  // them into the newly cloned array.
1254 1255
  for (int array_index = 0; array_index < expr->values()->length();
       array_index++) {
arv's avatar
arv committed
1256
    Expression* subexpr = expr->values()->at(array_index);
1257
    DCHECK(!subexpr->IsSpread());
1258 1259 1260
    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;

    VisitForValue(subexpr);
1261 1262 1263 1264
    VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
    Node* value = environment()->Pop();
    Node* index = jsgraph()->Constant(array_index);
    Node* literal = environment()->Top();
1265
    BuildKeyedStore(literal, index, value, pair);
1266 1267
  }

1268
  ast_context()->ProduceValue(expr, environment()->Pop());
1269 1270 1271
}

void AstGraphBuilder::VisitAssignment(Assignment* expr) {
1272
  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1273 1274 1275

  // Left-hand side can only be a property, a global or a variable slot.
  Property* property = expr->target()->AsProperty();
1276
  LhsKind assign_type = Property::GetAssignType(property);
1277 1278 1279

  // Evaluate LHS expression.
  switch (assign_type) {
1280
    case VARIABLE:
1281 1282 1283 1284
      break;
    case NAMED_PROPERTY:
      VisitForValue(property->obj());
      break;
1285
    case KEYED_PROPERTY:
1286 1287 1288
      VisitForValue(property->obj());
      VisitForValue(property->key());
      break;
1289 1290
    case NAMED_SUPER_PROPERTY:
    case KEYED_SUPER_PROPERTY:
1291
      UNREACHABLE();
1292
      break;
1293 1294 1295 1296 1297
  }

  // Evaluate the value and potentially handle compound assignments by loading
  // the left-hand side value and performing a binary operation.
  if (expr->is_compound()) {
1298
    Node* old_value = nullptr;
1299 1300
    switch (assign_type) {
      case VARIABLE: {
1301
        VariableProxy* proxy = expr->target()->AsVariableProxy();
1302 1303
        VectorSlotPair pair =
            CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1304
        old_value = BuildVariableLoad(proxy->var(), pair);
1305 1306 1307 1308
        break;
      }
      case NAMED_PROPERTY: {
        Node* object = environment()->Top();
1309
        Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
1310 1311 1312
        VectorSlotPair pair =
            CreateVectorSlotPair(property->PropertyFeedbackSlot());
        old_value = BuildNamedLoad(object, name, pair);
1313 1314 1315 1316 1317
        break;
      }
      case KEYED_PROPERTY: {
        Node* key = environment()->Top();
        Node* object = environment()->Peek(1);
1318 1319 1320
        VectorSlotPair pair =
            CreateVectorSlotPair(property->PropertyFeedbackSlot());
        old_value = BuildKeyedLoad(object, key, pair);
1321 1322
        break;
      }
1323 1324 1325
      case NAMED_SUPER_PROPERTY:
      case KEYED_SUPER_PROPERTY:
        UNREACHABLE();
1326
        break;
1327 1328 1329
    }
    environment()->Push(old_value);
    VisitForValue(expr->value());
1330 1331
    Node* right = environment()->Pop();
    Node* left = environment()->Pop();
1332
    Node* value = BuildBinaryOp(left, right, expr->binary_op());
1333 1334 1335 1336 1337 1338 1339
    environment()->Push(value);
  } else {
    VisitForValue(expr->value());
  }

  // Store the value.
  Node* value = environment()->Pop();
1340
  VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
1341 1342 1343
  switch (assign_type) {
    case VARIABLE: {
      Variable* variable = expr->target()->AsVariableProxy()->var();
1344
      BuildVariableAssignment(variable, value, expr->op(), feedback);
1345 1346 1347 1348
      break;
    }
    case NAMED_PROPERTY: {
      Node* object = environment()->Pop();
1349
      Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
1350
      BuildNamedStore(object, name, value, feedback);
1351 1352 1353 1354 1355
      break;
    }
    case KEYED_PROPERTY: {
      Node* key = environment()->Pop();
      Node* object = environment()->Pop();
1356
      BuildKeyedStore(object, key, value, feedback);
1357 1358
      break;
    }
1359 1360 1361
    case NAMED_SUPER_PROPERTY:
    case KEYED_SUPER_PROPERTY:
      UNREACHABLE();
1362
      break;
1363 1364
  }

1365
  ast_context()->ProduceValue(expr, value);
1366 1367
}

1368
void AstGraphBuilder::VisitYield(Yield* expr) {
1369
  // Generator functions are supported only by going through Ignition first.
1370
  UNREACHABLE();
1371 1372
}

1373 1374 1375 1376
void AstGraphBuilder::VisitYieldStar(YieldStar* expr) {
  // Generator functions are supported only by going through Ignition first.
  UNREACHABLE();
}
1377

1378 1379 1380 1381 1382
void AstGraphBuilder::VisitAwait(Await* expr) {
  // Generator functions are supported only by going through Ignition first.
  UNREACHABLE();
}

1383 1384 1385
void AstGraphBuilder::VisitThrow(Throw* expr) {
  VisitForValue(expr->exception());
  Node* exception = environment()->Pop();
1386
  Node* value = BuildThrowError(exception);
1387
  ast_context()->ProduceValue(expr, value);
1388 1389 1390 1391
}


void AstGraphBuilder::VisitProperty(Property* expr) {
1392
  Node* value = nullptr;
1393
  LhsKind property_kind = Property::GetAssignType(expr);
1394
  VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
1395 1396 1397 1398 1399 1400 1401 1402
  switch (property_kind) {
    case VARIABLE:
      UNREACHABLE();
      break;
    case NAMED_PROPERTY: {
      VisitForValue(expr->obj());
      Node* object = environment()->Pop();
      Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
1403
      value = BuildNamedLoad(object, name, pair);
1404 1405 1406 1407 1408 1409 1410
      break;
    }
    case KEYED_PROPERTY: {
      VisitForValue(expr->obj());
      VisitForValue(expr->key());
      Node* key = environment()->Pop();
      Node* object = environment()->Pop();
1411
      value = BuildKeyedLoad(object, key, pair);
1412 1413
      break;
    }
1414 1415 1416
    case NAMED_SUPER_PROPERTY:
    case KEYED_SUPER_PROPERTY:
      UNREACHABLE();
1417
      break;
1418
  }
1419
  ast_context()->ProduceValue(expr, value);
1420 1421 1422 1423 1424
}


void AstGraphBuilder::VisitCall(Call* expr) {
  Expression* callee = expr->expression();
1425
  Call::CallType call_type = expr->GetCallType();
1426
  CHECK(!expr->is_possibly_eval());
1427 1428 1429

  // Prepare the callee and the receiver to the function call. This depends on
  // the semantics of the underlying call type.
1430 1431 1432
  ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
  Node* receiver_value = nullptr;
  Node* callee_value = nullptr;
1433 1434 1435 1436
  switch (call_type) {
    case Call::GLOBAL_CALL: {
      VariableProxy* proxy = callee->AsVariableProxy();
      VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1437
      callee_value = BuildVariableLoad(proxy->var(), pair);
1438 1439
      receiver_hint = ConvertReceiverMode::kNullOrUndefined;
      receiver_value = jsgraph()->UndefinedConstant();
1440
      break;
1441
    }
1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478
    case Call::NAMED_PROPERTY_CALL: {
      Property* property = callee->AsProperty();
      VectorSlotPair feedback =
          CreateVectorSlotPair(property->PropertyFeedbackSlot());
      VisitForValue(property->obj());
      Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
      Node* object = environment()->Top();
      callee_value = BuildNamedLoad(object, name, feedback);
      // Note that a property call requires the receiver to be wrapped into
      // an object for sloppy callees. However the receiver is guaranteed
      // not to be null or undefined at this point.
      receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
      receiver_value = environment()->Pop();
      break;
    }
    case Call::KEYED_PROPERTY_CALL: {
      Property* property = callee->AsProperty();
      VectorSlotPair feedback =
          CreateVectorSlotPair(property->PropertyFeedbackSlot());
      VisitForValue(property->obj());
      VisitForValue(property->key());
      Node* key = environment()->Pop();
      Node* object = environment()->Top();
      callee_value = BuildKeyedLoad(object, key, feedback);
      // Note that a property call requires the receiver to be wrapped into
      // an object for sloppy callees. However the receiver is guaranteed
      // not to be null or undefined at this point.
      receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
      receiver_value = environment()->Pop();
      break;
    }
    case Call::OTHER_CALL:
      VisitForValue(callee);
      callee_value = environment()->Pop();
      receiver_hint = ConvertReceiverMode::kNullOrUndefined;
      receiver_value = jsgraph()->UndefinedConstant();
      break;
1479 1480
    case Call::NAMED_SUPER_PROPERTY_CALL:
    case Call::KEYED_SUPER_PROPERTY_CALL:
1481
    case Call::SUPER_CALL:
1482 1483
    case Call::WITH_CALL:
      UNREACHABLE();
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
  }

  // The callee and the receiver both have to be pushed onto the operand stack
  // before arguments are being evaluated.
  environment()->Push(callee_value);
  environment()->Push(receiver_value);

  // Evaluate all arguments to the function call,
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

  // Create node to perform the function call.
1496
  CallFrequency frequency = ComputeCallFrequency(expr->CallFeedbackICSlot());
1497
  VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
1498 1499
  const Operator* call = javascript()->Call(args->length() + 2, frequency,
                                            feedback, receiver_hint);
1500
  Node* value = ProcessArguments(call, args->length() + 2);
1501
  ast_context()->ProduceValue(expr, value);
1502 1503 1504 1505 1506 1507 1508 1509 1510 1511
}


void AstGraphBuilder::VisitCallNew(CallNew* expr) {
  VisitForValue(expr->expression());

  // Evaluate all arguments to the construct call.
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

1512
  // The new target is the same as the callee.
1513 1514
  environment()->Push(environment()->Peek(args->length()));

1515
  // Create node to perform the construct call.
1516
  CallFrequency frequency = ComputeCallFrequency(expr->CallNewFeedbackSlot());
1517 1518
  VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
  const Operator* call =
1519
      javascript()->Construct(args->length() + 2, frequency, feedback);
1520
  Node* value = ProcessArguments(call, args->length() + 2);
1521
  ast_context()->ProduceValue(expr, value);
1522 1523 1524 1525 1526 1527
}


void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
  // The callee and the receiver both have to be pushed onto the operand stack
  // before arguments are being evaluated.
1528
  Node* callee_value = BuildLoadNativeContextField(expr->context_index());
1529 1530
  Node* receiver_value = jsgraph()->UndefinedConstant();

1531
  environment()->Push(callee_value);
1532 1533 1534 1535 1536 1537 1538
  environment()->Push(receiver_value);

  // Evaluate all arguments to the JS runtime call.
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

  // Create node to perform the JS runtime call.
1539
  const Operator* call = javascript()->Call(args->length() + 2);
1540
  Node* value = ProcessArguments(call, args->length() + 2);
1541
  ast_context()->ProduceValue(expr, value);
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556
}


void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
  // Handle calls to runtime functions implemented in JavaScript separately as
  // the call follows JavaScript ABI and the callee is statically unknown.
  if (expr->is_jsruntime()) {
    return VisitCallJSRuntime(expr);
  }

  // Evaluate all arguments to the runtime call.
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

  // Create node to perform the runtime call.
1557
  Runtime::FunctionId functionId = expr->function()->function_id;
1558
  const Operator* call = javascript()->CallRuntime(functionId, args->length());
1559
  Node* value = ProcessArguments(call, args->length());
1560
  ast_context()->ProduceValue(expr, value);
1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
}


void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
  switch (expr->op()) {
    case Token::DELETE:
      return VisitDelete(expr);
    case Token::VOID:
      return VisitVoid(expr);
    case Token::TYPEOF:
      return VisitTypeof(expr);
    case Token::NOT:
      return VisitNot(expr);
    default:
      UNREACHABLE();
  }
}


void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
1581
  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
1582 1583 1584

  // Left-hand side can only be a property, a global or a variable slot.
  Property* property = expr->expression()->AsProperty();
1585
  LhsKind assign_type = Property::GetAssignType(property);
1586 1587 1588

  // Reserve space for result of postfix operation.
  bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
1589 1590 1591
  if (is_postfix && assign_type != VARIABLE) {
    environment()->Push(jsgraph()->ZeroConstant());
  }
1592 1593

  // Evaluate LHS expression and get old value.
1594
  Node* old_value = nullptr;
1595 1596 1597
  int stack_depth = -1;
  switch (assign_type) {
    case VARIABLE: {
1598
      VariableProxy* proxy = expr->expression()->AsVariableProxy();
1599
      VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1600
      old_value = BuildVariableLoad(proxy->var(), pair);
1601 1602 1603 1604 1605 1606
      stack_depth = 0;
      break;
    }
    case NAMED_PROPERTY: {
      VisitForValue(property->obj());
      Node* object = environment()->Top();
1607
      Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
1608 1609 1610
      VectorSlotPair pair =
          CreateVectorSlotPair(property->PropertyFeedbackSlot());
      old_value = BuildNamedLoad(object, name, pair);
1611 1612 1613 1614 1615 1616 1617 1618
      stack_depth = 1;
      break;
    }
    case KEYED_PROPERTY: {
      VisitForValue(property->obj());
      VisitForValue(property->key());
      Node* key = environment()->Top();
      Node* object = environment()->Peek(1);
1619 1620 1621
      VectorSlotPair pair =
          CreateVectorSlotPair(property->PropertyFeedbackSlot());
      old_value = BuildKeyedLoad(object, key, pair);
1622 1623 1624
      stack_depth = 2;
      break;
    }
1625 1626 1627
    case NAMED_SUPER_PROPERTY:
    case KEYED_SUPER_PROPERTY:
      UNREACHABLE();
1628
      break;
1629 1630 1631
  }

  // Convert old value into a number.
1632
  old_value = NewNode(javascript()->ToNumber(), old_value);
1633

1634 1635 1636 1637
  // Create a proper eager frame state for the stores.
  environment()->Push(old_value);
  old_value = environment()->Pop();

1638
  // Save result for postfix expressions at correct stack depth.
1639
  if (is_postfix) {
1640 1641 1642 1643 1644
    if (assign_type != VARIABLE) {
      environment()->Poke(stack_depth, old_value);
    } else {
      environment()->Push(old_value);
    }
1645
  }
1646 1647

  // Create node to perform +1/-1 operation.
1648 1649
  Node* value =
      BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
1650 1651

  // Store the value.
1652
  VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
1653 1654 1655
  switch (assign_type) {
    case VARIABLE: {
      Variable* variable = expr->expression()->AsVariableProxy()->var();
1656
      environment()->Push(value);
1657
      BuildVariableAssignment(variable, value, expr->op(), feedback);
1658
      environment()->Pop();
1659 1660 1661 1662
      break;
    }
    case NAMED_PROPERTY: {
      Node* object = environment()->Pop();
1663
      Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
1664
      BuildNamedStore(object, name, value, feedback);
1665 1666 1667 1668 1669
      break;
    }
    case KEYED_PROPERTY: {
      Node* key = environment()->Pop();
      Node* object = environment()->Pop();
1670
      BuildKeyedStore(object, key, value, feedback);
1671 1672
      break;
    }
1673 1674 1675
    case NAMED_SUPER_PROPERTY:
    case KEYED_SUPER_PROPERTY:
      UNREACHABLE();
1676
      break;
1677 1678 1679 1680 1681
  }

  // Restore old value for postfix expressions.
  if (is_postfix) value = environment()->Pop();

1682
  ast_context()->ProduceValue(expr, value);
1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
}


void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
  switch (expr->op()) {
    case Token::COMMA:
      return VisitComma(expr);
    case Token::OR:
    case Token::AND:
      return VisitLogicalExpression(expr);
    default: {
      VisitForValue(expr->left());
      VisitForValue(expr->right());
      Node* right = environment()->Pop();
      Node* left = environment()->Pop();
1698
      Node* value = BuildBinaryOp(left, right, expr->op());
1699
      ast_context()->ProduceValue(expr, value);
1700 1701 1702 1703
    }
  }
}

1704 1705 1706 1707 1708 1709
void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
                                             Expression* sub_expr,
                                             Node* nil_value) {
  const Operator* op = nullptr;
  switch (expr->op()) {
    case Token::EQ:
1710
      op = javascript()->Equal(CompareOperationHint::kAny);
1711 1712
      break;
    case Token::EQ_STRICT:
1713
      op = javascript()->StrictEqual(CompareOperationHint::kAny);
1714 1715 1716 1717 1718 1719 1720
      break;
    default:
      UNREACHABLE();
  }
  VisitForValue(sub_expr);
  Node* value_to_compare = environment()->Pop();
  Node* value = NewNode(op, value_to_compare, nil_value);
1721
  return ast_context()->ProduceValue(expr, value);
1722 1723 1724 1725 1726 1727 1728
}

void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
                                                Expression* sub_expr,
                                                Handle<String> check) {
  VisitTypeofExpression(sub_expr);
  Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
1729
  Node* value = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
1730
                        typeof_arg, jsgraph()->Constant(check));
1731
  return ast_context()->ProduceValue(expr, value);
1732
}
1733 1734

void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
1735 1736 1737 1738
  // Check for a few fast cases. The AST visiting behavior must be in sync
  // with the full codegen: We don't push both left and right values onto
  // the expression stack when one side is a special-case literal.
  Expression* sub_expr = nullptr;
1739 1740 1741 1742
  Literal* literal;
  if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
    return VisitLiteralCompareTypeof(expr, sub_expr,
                                     Handle<String>::cast(literal->value()));
1743
  }
1744
  if (expr->IsLiteralCompareUndefined(&sub_expr)) {
1745 1746 1747 1748 1749 1750 1751
    return VisitLiteralCompareNil(expr, sub_expr,
                                  jsgraph()->UndefinedConstant());
  }
  if (expr->IsLiteralCompareNull(&sub_expr)) {
    return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
  }

1752
  CompareOperationHint hint = CompareOperationHint::kAny;
1753
  const Operator* op;
1754 1755
  switch (expr->op()) {
    case Token::EQ:
1756
      op = javascript()->Equal(hint);
1757 1758
      break;
    case Token::EQ_STRICT:
1759
      op = javascript()->StrictEqual(hint);
1760 1761
      break;
    case Token::LT:
1762
      op = javascript()->LessThan(hint);
1763 1764
      break;
    case Token::GT:
1765
      op = javascript()->GreaterThan(hint);
1766 1767
      break;
    case Token::LTE:
1768
      op = javascript()->LessThanOrEqual(hint);
1769 1770
      break;
    case Token::GTE:
1771
      op = javascript()->GreaterThanOrEqual(hint);
1772
      break;
1773 1774
    case Token::INSTANCEOF:
      op = javascript()->InstanceOf();
1775 1776 1777 1778 1779
      break;
    case Token::IN:
      op = javascript()->HasProperty();
      break;
    default:
1780
      op = nullptr;
1781 1782 1783 1784 1785 1786 1787
      UNREACHABLE();
  }
  VisitForValue(expr->left());
  VisitForValue(expr->right());
  Node* right = environment()->Pop();
  Node* left = environment()->Pop();
  Node* value = NewNode(op, left, right);
1788
  ast_context()->ProduceValue(expr, value);
1789 1790 1791
}


1792 1793 1794 1795
void AstGraphBuilder::VisitSpread(Spread* expr) {
  // Handled entirely by the parser itself.
  UNREACHABLE();
}
1796 1797


1798 1799 1800 1801 1802
void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
  // Handled entirely by the parser itself.
  UNREACHABLE();
}

1803 1804 1805 1806
void AstGraphBuilder::VisitGetIterator(GetIterator* expr) {
  // GetIterator is supported only by going through Ignition first.
  UNREACHABLE();
}
1807

1808 1809 1810 1811 1812
void AstGraphBuilder::VisitImportCallExpression(ImportCallExpression* expr) {
  // ImportCallExpression is supported only by going through Ignition first.
  UNREACHABLE();
}

1813 1814
void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
  Node* value = GetFunctionClosure();
1815
  ast_context()->ProduceValue(expr, value);
1816 1817 1818
}


1819 1820
void AstGraphBuilder::VisitSuperPropertyReference(
    SuperPropertyReference* expr) {
1821
  UNREACHABLE();
1822 1823 1824 1825
}


void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
1826 1827
  // Handled by VisitCall
  UNREACHABLE();
1828 1829 1830
}


1831 1832 1833 1834
void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
  // Handled entirely in VisitSwitch.
  UNREACHABLE();
}
1835

1836
void AstGraphBuilder::VisitDeclarations(Declaration::List* declarations) {
1837
  DCHECK(globals()->empty());
1838
  AstVisitor<AstGraphBuilder>::VisitDeclarations(declarations);
1839 1840
  if (globals()->empty()) return;
  int array_index = 0;
1841
  Handle<FeedbackVector> feedback_vector(info()->closure()->feedback_vector());
1842 1843 1844
  Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
      static_cast<int>(globals()->size()), TENURED);
  for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
1845
  int encoded_flags = info()->GetDeclareGlobalsFlags();
1846
  Node* flags = jsgraph()->Constant(encoded_flags);
1847
  Node* decls = jsgraph()->Constant(data);
1848
  Node* vector = jsgraph()->Constant(feedback_vector);
1849
  const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
1850
  NewNode(op, decls, flags, vector);
1851
  globals()->clear();
1852 1853 1854 1855
}


void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
1856
  if (stmt == nullptr) return;
1857 1858 1859 1860
  Visit(stmt);
}

void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
1861
                                         LoopBuilder* loop) {
1862
  ControlScopeForIteration scope(this, stmt, loop);
1863
  NewNode(javascript()->StackCheck());
1864 1865 1866 1867 1868 1869 1870
  Visit(stmt->body());
}


void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
  Node* value;
  if (expr->expression()->IsVariableProxy()) {
1871 1872
    // Delete of an unqualified identifier is disallowed in strict mode but
    // "delete this" is allowed.
1873 1874
    Variable* variable = expr->expression()->AsVariableProxy()->var();
    DCHECK(is_sloppy(language_mode()) || variable->is_this());
1875
    value = BuildVariableDelete(variable);
1876 1877 1878 1879 1880 1881
  } else if (expr->expression()->IsProperty()) {
    Property* property = expr->expression()->AsProperty();
    VisitForValue(property->obj());
    VisitForValue(property->key());
    Node* key = environment()->Pop();
    Node* object = environment()->Pop();
1882 1883
    Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode()));
    value = NewNode(javascript()->DeleteProperty(), object, key, mode);
1884 1885 1886 1887
  } else {
    VisitForEffect(expr->expression());
    value = jsgraph()->TrueConstant();
  }
1888
  ast_context()->ProduceValue(expr, value);
1889 1890 1891 1892 1893 1894
}


void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
  VisitForEffect(expr->expression());
  Node* value = jsgraph()->UndefinedConstant();
1895
  ast_context()->ProduceValue(expr, value);
1896 1897
}

1898 1899
void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
  if (expr->IsVariableProxy()) {
1900 1901
    // Typeof does not throw a reference error on global variables, hence we
    // perform a non-contextual load in case the operand is a variable proxy.
1902
    VariableProxy* proxy = expr->AsVariableProxy();
1903
    VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1904
    Node* load = BuildVariableLoad(proxy->var(), pair, INSIDE_TYPEOF);
1905
    environment()->Push(load);
1906
  } else {
1907
    VisitForValue(expr);
1908
  }
1909 1910 1911 1912 1913
}

void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
  VisitTypeofExpression(expr->expression());
  Node* value = NewNode(javascript()->TypeOf(), environment()->Pop());
1914
  ast_context()->ProduceValue(expr, value);
1915 1916 1917 1918
}


void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
1919 1920
  VisitForTest(expr->expression());
  Node* input = environment()->Pop();
1921
  Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
1922
                        jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1923 1924 1925 1926 1927
  // Skip plugging AST evaluation contexts of the test kind. This is to stay in
  // sync with full codegen which doesn't prepare the proper bailout point (see
  // the implementation of FullCodeGenerator::VisitForControl).
  if (ast_context()->IsTest()) return environment()->Push(value);
  ast_context()->ProduceValue(expr, value);
1928 1929 1930 1931 1932 1933
}


void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
  VisitForEffect(expr->left());
  Visit(expr->right());
1934 1935 1936 1937
  // Skip plugging AST evaluation contexts of the test kind. This is to stay in
  // sync with full codegen which doesn't prepare the proper bailout point (see
  // the implementation of FullCodeGenerator::VisitForControl).
  if (ast_context()->IsTest()) return;
1938
  ast_context()->ReplaceValue(expr);
1939 1940 1941 1942 1943 1944
}


void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
  bool is_logical_and = expr->op() == Token::AND;
  IfBuilder compare_if(this);
1945 1946 1947 1948 1949 1950 1951
  // Only use an AST evaluation context of the value kind when this expression
  // is evaluated as value as well. Otherwise stick to a test context which is
  // in sync with full codegen (see FullCodeGenerator::VisitLogicalExpression).
  Node* condition = nullptr;
  if (ast_context()->IsValue()) {
    VisitForValue(expr->left());
    Node* left = environment()->Top();
1952
    condition = BuildToBoolean(left);
1953 1954 1955 1956 1957
  } else {
    VisitForTest(expr->left());
    condition = environment()->Top();
  }
  compare_if.If(condition);
1958 1959 1960 1961 1962 1963
  compare_if.Then();
  if (is_logical_and) {
    environment()->Pop();
    Visit(expr->right());
  } else if (ast_context()->IsEffect()) {
    environment()->Pop();
1964 1965
  } else if (ast_context()->IsTest()) {
    environment()->Poke(0, jsgraph()->TrueConstant());
1966 1967 1968 1969 1970 1971 1972
  }
  compare_if.Else();
  if (!is_logical_and) {
    environment()->Pop();
    Visit(expr->right());
  } else if (ast_context()->IsEffect()) {
    environment()->Pop();
1973 1974
  } else if (ast_context()->IsTest()) {
    environment()->Poke(0, jsgraph()->FalseConstant());
1975 1976
  }
  compare_if.End();
1977 1978 1979 1980 1981
  // Skip plugging AST evaluation contexts of the test kind. This is to stay in
  // sync with full codegen which doesn't prepare the proper bailout point (see
  // the implementation of FullCodeGenerator::VisitForControl).
  if (ast_context()->IsTest()) return;
  ast_context()->ReplaceValue(expr);
1982 1983 1984
}


1985
LanguageMode AstGraphBuilder::language_mode() const {
1986
  return current_scope()->language_mode();
1987 1988
}

1989
VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(FeedbackSlot slot) const {
1990
  return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot);
1991 1992 1993
}


1994
void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
1995 1996 1997
  Visit(node->expression());
}

1998 1999 2000 2001
CallFrequency AstGraphBuilder::ComputeCallFrequency(FeedbackSlot slot) const {
  if (invocation_frequency_.IsUnknown() || slot.IsInvalid()) {
    return CallFrequency();
  }
2002 2003
  Handle<FeedbackVector> feedback_vector(info()->closure()->feedback_vector(),
                                         isolate());
2004
  CallICNexus nexus(feedback_vector, slot);
2005 2006
  return CallFrequency(nexus.ComputeCallFrequency() *
                       invocation_frequency_.value());
2007
}
2008

2009
Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
2010
  DCHECK(environment()->stack_height() >= arity);
2011
  Node** all = info()->zone()->NewArray<Node*>(arity);
2012 2013 2014 2015 2016 2017 2018 2019
  for (int i = arity - 1; i >= 0; --i) {
    all[i] = environment()->Pop();
  }
  Node* value = NewNode(op, arity, all);
  return value;
}


2020
Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
2021
  DeclarationScope* scope = info()->scope();
2022

2023
  // Allocate a new local context.
2024 2025 2026
  Node* local_context = scope->is_script_scope()
                            ? BuildLocalScriptContext(scope)
                            : BuildLocalFunctionContext(scope);
2027

2028
  if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
2029
    Node* receiver = environment()->RawParameterLookup(0);
2030 2031 2032 2033
    // Context variable (at bottom of the context chain).
    Variable* variable = scope->receiver();
    DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
    const Operator* op = javascript()->StoreContext(0, variable->index());
2034 2035
    Node* node = NewNode(op, receiver);
    NodeProperties::ReplaceContextInput(node, local_context);
2036 2037
  }

2038
  // Copy parameters into context if necessary.
2039
  int num_parameters = scope->num_parameters();
2040
  for (int i = 0; i < num_parameters; i++) {
2041
    Variable* variable = scope->parameter(i);
2042
    if (!variable->IsContextSlot()) continue;
2043
    Node* parameter = environment()->RawParameterLookup(i + 1);
2044
    // Context variable (at bottom of the context chain).
2045
    DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2046
    const Operator* op = javascript()->StoreContext(0, variable->index());
2047 2048
    Node* node = NewNode(op, parameter);
    NodeProperties::ReplaceContextInput(node, local_context);
2049 2050 2051 2052 2053 2054
  }

  return local_context;
}


2055
Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
2056
  DCHECK(scope->is_function_scope() || scope->is_eval_scope());
2057 2058 2059

  // Allocate a new local context.
  int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
2060 2061
  const Operator* op =
      javascript()->CreateFunctionContext(slot_count, scope->scope_type());
2062 2063 2064 2065 2066 2067
  Node* local_context = NewNode(op, GetFunctionClosure());

  return local_context;
}


2068
Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
2069
  DCHECK(scope->is_script_scope());
2070 2071

  // Allocate a new local context.
2072
  Handle<ScopeInfo> scope_info = scope->scope_info();
2073 2074
  const Operator* op = javascript()->CreateScriptContext(scope_info);
  Node* local_context = NewNode(op, GetFunctionClosure());
2075 2076 2077 2078 2079

  return local_context;
}


2080
Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
2081
  DCHECK(scope->is_block_scope());
2082 2083

  // Allocate a new local context.
2084
  Handle<ScopeInfo> scope_info = scope->scope_info();
2085 2086
  const Operator* op = javascript()->CreateBlockContext(scope_info);
  Node* local_context = NewNode(op, GetFunctionClosureForContext());
2087 2088 2089 2090 2091

  return local_context;
}


2092
Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
2093
  if (arguments == nullptr) return nullptr;
2094 2095

  // Allocate and initialize a new arguments object.
2096
  CreateArgumentsType type =
2097
      is_strict(language_mode()) || !info()->has_simple_parameters()
2098 2099 2100
          ? CreateArgumentsType::kUnmappedArguments
          : CreateArgumentsType::kMappedArguments;
  const Operator* op = javascript()->CreateArguments(type);
2101
  Node* object = NewNode(op, GetFunctionClosure());
2102

2103 2104
  // Assign the object to the {arguments} variable. This should never lazy
  // deopt, so it is fine to send invalid bailout id.
2105
  DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
2106
  BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair());
2107 2108 2109
  return object;
}

2110
Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
2111
                                               Node* not_hole) {
2112 2113 2114 2115 2116 2117
  IfBuilder hole_check(this);
  Node* the_hole = jsgraph()->TheHoleConstant();
  Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
                        value, the_hole);
  hole_check.If(check);
  hole_check.Then();
2118
  Node* error = BuildThrowReferenceError(variable);
2119 2120 2121 2122 2123 2124 2125 2126
  environment()->Push(error);
  hole_check.Else();
  environment()->Push(not_hole);
  hole_check.End();
  return environment()->Pop();
}

Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
2127
                                               Node* for_hole) {
2128 2129 2130 2131 2132 2133 2134 2135
  IfBuilder hole_check(this);
  Node* the_hole = jsgraph()->TheHoleConstant();
  Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
                        value, the_hole);
  hole_check.If(check);
  hole_check.Then();
  environment()->Push(for_hole);
  hole_check.Else();
2136
  Node* error = BuildThrowReferenceError(variable);
2137 2138 2139 2140 2141
  environment()->Push(error);
  hole_check.End();
  return environment()->Pop();
}

2142
Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
2143
                                         const VectorSlotPair& feedback,
2144
                                         TypeofMode typeof_mode) {
2145
  Node* the_hole = jsgraph()->TheHoleConstant();
2146
  switch (variable->location()) {
2147
    case VariableLocation::UNALLOCATED: {
2148
      // Global var, const, or let variable.
2149
      Handle<Name> name = variable->name();
2150
      if (Node* node = TryLoadGlobalConstant(name)) return node;
2151
      Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
2152
      return value;
2153
    }
2154
    case VariableLocation::PARAMETER:
2155 2156 2157 2158 2159 2160
    case VariableLocation::LOCAL: {
      // Local var, const, or let variable.
      Node* value = environment()->Lookup(variable);
      if (variable->binding_needs_init()) {
        // Perform check for uninitialized let/const variables.
        if (value->op() == the_hole->op()) {
2161
          value = BuildThrowReferenceError(variable);
2162
        } else if (value->opcode() == IrOpcode::kPhi) {
2163
          value = BuildHoleCheckThenThrow(value, variable, value);
2164 2165 2166 2167
        }
      }
      return value;
    }
2168
    case VariableLocation::CONTEXT: {
2169 2170
      // Context variable (potentially up the context chain).
      int depth = current_scope()->ContextChainLength(variable->scope());
2171 2172 2173 2174 2175
      // TODO(mstarzinger): The {maybe_assigned} flag computed during variable
      // resolution is highly inaccurate and cannot be trusted. We are only
      // taking this information into account when asm.js compilation is used.
      bool immutable = variable->maybe_assigned() == kNotAssigned &&
                       info()->is_function_context_specializing();
2176
      const Operator* op =
2177
          javascript()->LoadContext(depth, variable->index(), immutable);
2178 2179 2180 2181 2182 2183
      Node* value = NewNode(op);
      // TODO(titzer): initialization checks are redundant for already
      // initialized immutable context loads, but only specialization knows.
      // Maybe specializer should be a parameter to the graph builder?
      if (variable->binding_needs_init()) {
        // Perform check for uninitialized let/const variables.
2184
        value = BuildHoleCheckThenThrow(value, variable, value);
2185 2186
      }
      return value;
2187
    }
2188
    case VariableLocation::LOOKUP:
2189 2190
    case VariableLocation::MODULE:
      UNREACHABLE();
2191 2192 2193 2194
  }
  UNREACHABLE();
}

2195
Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
2196
  switch (variable->location()) {
2197
    case VariableLocation::UNALLOCATED: {
2198 2199 2200
      // Global var, const, or let variable.
      Node* global = BuildLoadGlobalObject();
      Node* name = jsgraph()->Constant(variable->name());
2201 2202 2203
      Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode()));
      const Operator* op = javascript()->DeleteProperty();
      Node* result = NewNode(op, global, name, mode);
2204
      return result;
2205
    }
2206 2207 2208
    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL:
    case VariableLocation::CONTEXT: {
2209
      // Local var, const, or let variable or context variable.
2210
      return jsgraph()->BooleanConstant(variable->is_this());
2211
    }
2212
    case VariableLocation::LOOKUP:
2213 2214
    case VariableLocation::MODULE:
      UNREACHABLE();
2215 2216 2217 2218
  }
  UNREACHABLE();
}

2219 2220 2221
Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
                                               Token::Value op,
                                               const VectorSlotPair& feedback) {
2222 2223
  Node* the_hole = jsgraph()->TheHoleConstant();
  VariableMode mode = variable->mode();
2224
  switch (variable->location()) {
2225
    case VariableLocation::UNALLOCATED: {
2226
      // Global var, const, or let variable.
2227
      Handle<Name> name = variable->name();
2228
      Node* store = BuildGlobalStore(name, value, feedback);
2229
      return store;
2230
    }
2231 2232
    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL:
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244
      // Local var, const, or let variable.
      if (mode == LET && op == Token::INIT) {
        // No initialization check needed because scoping guarantees it. Note
        // that we still perform a lookup to keep the variable live, because
        // baseline code might contain debug code that inspects the variable.
        Node* current = environment()->Lookup(variable);
        CHECK_NOT_NULL(current);
      } else if (mode == LET && op != Token::INIT &&
                 variable->binding_needs_init()) {
        // Perform an initialization check for let declared variables.
        Node* current = environment()->Lookup(variable);
        if (current->op() == the_hole->op()) {
2245
          return BuildThrowReferenceError(variable);
2246
        } else if (current->opcode() == IrOpcode::kPhi) {
2247
          BuildHoleCheckThenThrow(current, variable, value);
2248 2249 2250 2251 2252 2253 2254
        }
      } else if (mode == CONST && op == Token::INIT) {
        // Perform an initialization check for const {this} variables.
        // Note that the {this} variable is the only const variable being able
        // to trigger bind operations outside the TDZ, via {super} calls.
        Node* current = environment()->Lookup(variable);
        if (current->op() != the_hole->op() && variable->is_this()) {
2255
          value = BuildHoleCheckElseThrow(current, variable, value);
2256 2257 2258
        }
      } else if (mode == CONST && op != Token::INIT &&
                 variable->is_sloppy_function_name()) {
2259 2260 2261
        // Non-initializing assignment to sloppy function names is
        // - exception in strict mode.
        // - ignored in sloppy mode.
2262
        DCHECK(!variable->binding_needs_init());
2263
        if (variable->throw_on_const_assignment(language_mode())) {
2264
          return BuildThrowConstAssignError();
2265 2266
        }
        return value;
2267 2268 2269 2270
      } else if (mode == CONST && op != Token::INIT) {
        if (variable->binding_needs_init()) {
          Node* current = environment()->Lookup(variable);
          if (current->op() == the_hole->op()) {
2271
            return BuildThrowReferenceError(variable);
2272
          } else if (current->opcode() == IrOpcode::kPhi) {
2273
            BuildHoleCheckThenThrow(current, variable, value);
2274 2275 2276
          }
        }
        // Assignment to const is exception in all modes.
2277
        return BuildThrowConstAssignError();
2278 2279 2280
      }
      environment()->Bind(variable, value);
      return value;
2281
    case VariableLocation::CONTEXT: {
2282
      // Context variable (potentially up the context chain).
2283 2284 2285 2286 2287 2288
      int depth = current_scope()->ContextChainLength(variable->scope());
      if (mode == LET && op != Token::INIT && variable->binding_needs_init()) {
        // Perform an initialization check for let declared variables.
        const Operator* op =
            javascript()->LoadContext(depth, variable->index(), false);
        Node* current = NewNode(op);
2289
        value = BuildHoleCheckThenThrow(current, variable, value);
2290 2291 2292 2293 2294 2295 2296 2297
      } else if (mode == CONST && op == Token::INIT) {
        // Perform an initialization check for const {this} variables.
        // Note that the {this} variable is the only const variable being able
        // to trigger bind operations outside the TDZ, via {super} calls.
        if (variable->is_this()) {
          const Operator* op =
              javascript()->LoadContext(depth, variable->index(), false);
          Node* current = NewNode(op);
2298
          value = BuildHoleCheckElseThrow(current, variable, value);
2299 2300 2301
        }
      } else if (mode == CONST && op != Token::INIT &&
                 variable->is_sloppy_function_name()) {
2302 2303 2304
        // Non-initializing assignment to sloppy function names is
        // - exception in strict mode.
        // - ignored in sloppy mode.
2305
        DCHECK(!variable->binding_needs_init());
2306
        if (variable->throw_on_const_assignment(language_mode())) {
2307
          return BuildThrowConstAssignError();
2308 2309
        }
        return value;
2310 2311 2312 2313 2314
      } else if (mode == CONST && op != Token::INIT) {
        if (variable->binding_needs_init()) {
          const Operator* op =
              javascript()->LoadContext(depth, variable->index(), false);
          Node* current = NewNode(op);
2315
          BuildHoleCheckThenThrow(current, variable, value);
2316 2317
        }
        // Assignment to const is exception in all modes.
2318
        return BuildThrowConstAssignError();
2319
      }
2320
      const Operator* op = javascript()->StoreContext(depth, variable->index());
2321
      return NewNode(op, value);
2322
    }
2323
    case VariableLocation::LOOKUP:
2324 2325
    case VariableLocation::MODULE:
      UNREACHABLE();
2326 2327 2328 2329 2330
  }
  UNREACHABLE();
}


2331
Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
2332
                                      const VectorSlotPair& feedback) {
2333
  const Operator* op = javascript()->LoadProperty(feedback);
2334
  Node* node = NewNode(op, object, key);
2335
  return node;
2336 2337 2338 2339
}


Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
2340
                                      const VectorSlotPair& feedback) {
2341
  const Operator* op = javascript()->LoadNamed(name, feedback);
2342
  Node* node = NewNode(op, object);
2343
  return node;
2344 2345 2346
}


2347
Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
2348
                                       const VectorSlotPair& feedback) {
2349 2350
  DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()),
            language_mode());
2351
  const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
2352
  Node* node = NewNode(op, object, key, value);
2353
  return node;
2354 2355 2356 2357
}


Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
2358
                                       Node* value,
2359
                                       const VectorSlotPair& feedback) {
2360 2361
  DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()),
            language_mode());
2362
  const Operator* op =
2363
      javascript()->StoreNamed(language_mode(), name, feedback);
2364
  Node* node = NewNode(op, object, value);
2365
  return node;
2366 2367
}

2368 2369 2370 2371 2372 2373 2374 2375 2376
Node* AstGraphBuilder::BuildNamedStoreOwn(Node* object, Handle<Name> name,
                                          Node* value,
                                          const VectorSlotPair& feedback) {
  DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
            feedback.vector()->GetKind(feedback.slot()));
  const Operator* op = javascript()->StoreNamedOwn(name, feedback);
  Node* node = NewNode(op, object, value);
  return node;
}
2377

2378
Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
2379
                                       const VectorSlotPair& feedback,
2380
                                       TypeofMode typeof_mode) {
2381
  DCHECK_EQ(feedback.vector()->GetTypeofMode(feedback.slot()), typeof_mode);
2382
  const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
2383
  Node* node = NewNode(op);
2384
  return node;
2385 2386 2387
}


2388
Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
2389
                                        const VectorSlotPair& feedback) {
2390
  const Operator* op =
2391
      javascript()->StoreGlobal(language_mode(), name, feedback);
2392
  Node* node = NewNode(op, value);
2393
  return node;
2394 2395
}

2396
Node* AstGraphBuilder::BuildLoadGlobalObject() {
2397
  return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
2398 2399 2400
}


2401
Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
2402 2403
  const Operator* op =
      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
2404 2405 2406 2407
  Node* native_context = NewNode(op);
  Node* result = NewNode(javascript()->LoadContext(0, index, true));
  NodeProperties::ReplaceContextInput(result, native_context);
  return result;
2408 2409
}

2410
Node* AstGraphBuilder::BuildToBoolean(Node* input) {
2411
  if (Node* node = TryFastToBoolean(input)) return node;
2412
  ToBooleanHints hints = ToBooleanHint::kAny;
2413
  return NewNode(javascript()->ToBoolean(hints), input);
2414 2415
}

2416
Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
2417
                                          LiteralProperty* property,
2418 2419
                                          int slot_number) {
  Expression* expr = property->value();
2420
  if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
2421
  Handle<Name> name = isolate()->factory()->home_object_symbol();
2422 2423
  VectorSlotPair feedback =
      CreateVectorSlotPair(property->GetSlot(slot_number));
2424
  Node* store = BuildNamedStore(value, name, home_object, feedback);
2425 2426 2427
  return store;
}

2428
Node* AstGraphBuilder::BuildThrowError(Node* exception) {
2429
  const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
2430
  Node* call = NewNode(op, exception);
2431
  Node* control = NewNode(common()->Throw());
2432
  UpdateControlDependencyToLeaveFunction(control);
2433
  return call;
2434 2435
}

2436
Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) {
2437 2438 2439
  Node* variable_name = jsgraph()->Constant(variable->name());
  const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
  Node* call = NewNode(op, variable_name);
2440
  Node* control = NewNode(common()->Throw());
2441 2442 2443 2444
  UpdateControlDependencyToLeaveFunction(control);
  return call;
}

2445
Node* AstGraphBuilder::BuildThrowConstAssignError() {
2446
  const Operator* op =
2447
      javascript()->CallRuntime(Runtime::kThrowConstAssignError);
2448
  Node* call = NewNode(op);
2449
  Node* control = NewNode(common()->Throw());
2450
  UpdateControlDependencyToLeaveFunction(control);
2451
  return call;
2452 2453
}

2454

2455
Node* AstGraphBuilder::BuildReturn(Node* return_value) {
2456 2457 2458 2459 2460
  // Emit tracing call if requested to do so.
  if (FLAG_trace) {
    return_value =
        NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
  }
2461
  Node* pop_node = jsgraph()->ZeroConstant();
2462
  Node* control = NewNode(common()->Return(), pop_node, return_value);
2463 2464 2465 2466 2467 2468
  UpdateControlDependencyToLeaveFunction(control);
  return control;
}


Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
2469
  NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
2470
  Node* control = NewNode(common()->Throw());
2471
  UpdateControlDependencyToLeaveFunction(control);
2472 2473 2474
  return control;
}

2475
Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
2476
  const Operator* js_op;
2477
  BinaryOperationHint hint = BinaryOperationHint::kAny;
2478 2479
  switch (op) {
    case Token::BIT_OR:
2480
      js_op = javascript()->BitwiseOr();
2481 2482
      break;
    case Token::BIT_AND:
2483
      js_op = javascript()->BitwiseAnd();
2484 2485
      break;
    case Token::BIT_XOR:
2486
      js_op = javascript()->BitwiseXor();
2487 2488
      break;
    case Token::SHL:
2489
      js_op = javascript()->ShiftLeft();
2490 2491
      break;
    case Token::SAR:
2492
      js_op = javascript()->ShiftRight();
2493 2494
      break;
    case Token::SHR:
2495
      js_op = javascript()->ShiftRightLogical();
2496 2497
      break;
    case Token::ADD:
2498
      js_op = javascript()->Add(hint);
2499 2500
      break;
    case Token::SUB:
2501
      js_op = javascript()->Subtract();
2502 2503
      break;
    case Token::MUL:
2504
      js_op = javascript()->Multiply();
2505 2506
      break;
    case Token::DIV:
2507
      js_op = javascript()->Divide();
2508 2509
      break;
    case Token::MOD:
2510
      js_op = javascript()->Modulus();
2511 2512 2513
      break;
    default:
      UNREACHABLE();
2514
      js_op = nullptr;
2515 2516 2517 2518 2519
  }
  return NewNode(js_op, left, right);
}


2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554
Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
  // Optimize global constants like "undefined", "Infinity", and "NaN".
  Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
  if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
  return nullptr;
}

Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
  switch (input->opcode()) {
    case IrOpcode::kNumberConstant: {
      NumberMatcher m(input);
      return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
    }
    case IrOpcode::kHeapConstant: {
      Handle<HeapObject> object = HeapObjectMatcher(input).Value();
      return jsgraph_->BooleanConstant(object->BooleanValue());
    }
    case IrOpcode::kJSEqual:
    case IrOpcode::kJSStrictEqual:
    case IrOpcode::kJSLessThan:
    case IrOpcode::kJSLessThanOrEqual:
    case IrOpcode::kJSGreaterThan:
    case IrOpcode::kJSGreaterThanOrEqual:
    case IrOpcode::kJSToBoolean:
    case IrOpcode::kJSDeleteProperty:
    case IrOpcode::kJSHasProperty:
    case IrOpcode::kJSInstanceOf:
      return input;
    default:
      break;
  }
  return nullptr;
}


2555 2556
bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
  if (info()->osr_ast_id() == stmt->OsrEntryId()) {
2557
    info()->set_osr_expr_stack_height(environment()->stack_height());
2558 2559 2560
    return true;
  }
  return false;
2561 2562 2563
}


2564 2565
BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
    IterationStatement* stmt) {
2566
  if (loop_assignment_analysis_ == nullptr) return nullptr;
2567
  return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
2568
}
2569

2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582

Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
  if (size > input_buffer_size_) {
    size = size + kInputBufferSizeIncrement + input_buffer_size_;
    input_buffer_ = local_zone()->NewArray<Node*>(size);
    input_buffer_size_ = size;
  }
  return input_buffer_;
}


Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
                                Node** value_inputs, bool incomplete) {
2583
  DCHECK_EQ(op->ValueInputCount(), value_input_count);
2584 2585

  bool has_context = OperatorProperties::HasContextInput(op);
2586
  bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
2587 2588 2589 2590 2591 2592
  bool has_control = op->ControlInputCount() == 1;
  bool has_effect = op->EffectInputCount() == 1;

  DCHECK(op->ControlInputCount() < 2);
  DCHECK(op->EffectInputCount() < 2);

2593
  Node* result = nullptr;
2594
  if (!has_context && !has_frame_state && !has_control && !has_effect) {
2595 2596 2597 2598
    result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
  } else {
    int input_count_with_deps = value_input_count;
    if (has_context) ++input_count_with_deps;
2599
    if (has_frame_state) ++input_count_with_deps;
2600 2601 2602 2603 2604 2605 2606 2607
    if (has_control) ++input_count_with_deps;
    if (has_effect) ++input_count_with_deps;
    Node** buffer = EnsureInputBufferSize(input_count_with_deps);
    memcpy(buffer, value_inputs, kPointerSize * value_input_count);
    Node** current_input = buffer + value_input_count;
    if (has_context) {
      *current_input++ = current_context();
    }
2608
    if (has_frame_state) {
2609 2610
      DCHECK(!info()->is_deoptimization_enabled());
      *current_input++ = GetEmptyFrameState();
2611 2612 2613 2614 2615 2616 2617 2618
    }
    if (has_effect) {
      *current_input++ = environment_->GetEffectDependency();
    }
    if (has_control) {
      *current_input++ = environment_->GetControlDependency();
    }
    result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
2619 2620
    if (!environment()->IsMarkedAsUnreachable()) {
      // Update the current control dependency for control-producing nodes.
2621
      if (result->op()->ControlOutputCount() > 0) {
2622 2623
        environment_->UpdateControlDependency(result);
      }
2624 2625 2626 2627
      // Update the current effect dependency for effect-producing nodes.
      if (result->op()->EffectOutputCount() > 0) {
        environment_->UpdateEffectDependency(result);
      }
2628 2629 2630 2631 2632 2633 2634 2635 2636 2637
    }
  }

  return result;
}


void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
  if (environment()->IsMarkedAsUnreachable()) return;
  environment()->MarkAsUnreachable();
2638
  exit_controls_.push_back(exit);
2639 2640 2641 2642 2643
}


void AstGraphBuilder::Environment::Merge(Environment* other) {
  DCHECK(values_.size() == other->values_.size());
2644
  DCHECK(contexts_.size() == other->contexts_.size());
2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657

  // Nothing to do if the other environment is dead.
  if (other->IsMarkedAsUnreachable()) return;

  // Resurrect a dead environment by copying the contents of the other one and
  // placing a singleton merge as the new control dependency.
  if (this->IsMarkedAsUnreachable()) {
    Node* other_control = other->control_dependency_;
    Node* inputs[] = {other_control};
    control_dependency_ =
        graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
    effect_dependency_ = other->effect_dependency_;
    values_ = other->values_;
2658
    contexts_ = other->contexts_;
2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678
    return;
  }

  // Create a merge of the control dependencies of both environments and update
  // the current environment's control dependency accordingly.
  Node* control = builder_->MergeControl(this->GetControlDependency(),
                                         other->GetControlDependency());
  UpdateControlDependency(control);

  // Create a merge of the effect dependencies of both environments and update
  // the current environment's effect dependency accordingly.
  Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
                                       other->GetEffectDependency(), control);
  UpdateEffectDependency(effect);

  // Introduce Phi nodes for values that have differing input at merge points,
  // potentially extending an existing Phi node if possible.
  for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
    values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
  }
2679 2680 2681 2682
  for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
    contexts_[i] =
        builder_->MergeValue(contexts_[i], other->contexts_[i], control);
  }
2683 2684
}

2685 2686 2687 2688 2689 2690 2691
void AstGraphBuilder::Environment::PrepareForOsrEntry() {
  int size = static_cast<int>(values()->size());
  Graph* graph = builder_->graph();

  // Set the control and effect to the OSR loop entry.
  Node* osr_loop_entry = graph->NewNode(builder_->common()->OsrLoopEntry(),
                                        graph->start(), graph->start());
2692
  Node* effect = osr_loop_entry;
2693
  UpdateControlDependency(osr_loop_entry);
2694
  UpdateEffectDependency(effect);
2695

2696 2697 2698 2699 2700 2701
  // Set OSR values.
  for (int i = 0; i < size; ++i) {
    values()->at(i) =
        graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
  }

2702 2703 2704 2705 2706
  // Set the innermost context.
  const Operator* op_inner =
      builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
  contexts()->back() = graph->NewNode(op_inner, osr_loop_entry);

2707 2708
  // The innermost context is the OSR value, and the outer contexts are
  // reconstructed by dynamically walking up the context chain.
2709
  const Operator* load_op =
2710
      builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
2711
  Node* osr_context = contexts()->back();
2712
  int last = static_cast<int>(contexts()->size() - 1);
2713
  for (int i = last - 1; i >= 0; i--) {
2714
    osr_context = effect = graph->NewNode(load_op, osr_context, effect);
2715 2716
    contexts()->at(i) = osr_context;
  }
2717
  UpdateEffectDependency(effect);
2718
}
2719

2720
void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned) {
2721 2722 2723 2724 2725 2726
  int size = static_cast<int>(values()->size());

  Node* control = builder_->NewLoop();
  if (assigned == nullptr) {
    // Assume that everything is updated in the loop.
    for (int i = 0; i < size; ++i) {
2727
      values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739
    }
  } else {
    // Only build phis for those locals assigned in this loop.
    for (int i = 0; i < size; ++i) {
      if (i < assigned->length() && !assigned->Contains(i)) continue;
      Node* phi = builder_->NewPhi(1, values()->at(i), control);
      values()->at(i) = phi;
    }
  }
  Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
  UpdateEffectDependency(effect);

2740 2741 2742 2743 2744 2745 2746 2747
  // Connect the loop to end via Terminate if it's not marked as unreachable.
  if (!IsMarkedAsUnreachable()) {
    // Connect the Loop node to end via a Terminate node.
    Node* terminate = builder_->graph()->NewNode(
        builder_->common()->Terminate(), effect, control);
    builder_->exit_controls_.push_back(terminate);
  }

2748 2749
  if (builder_->info()->is_osr()) {
    // Introduce phis for all context values in the case of an OSR graph.
2750 2751 2752
    for (size_t i = 0; i < contexts()->size(); ++i) {
      Node* context = contexts()->at(i);
      contexts()->at(i) = builder_->NewPhi(1, context, control);
2753 2754
    }
  }
2755 2756 2757 2758
}


Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
2759
  const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781
  Node** buffer = EnsureInputBufferSize(count + 1);
  MemsetPointer(buffer, input, count);
  buffer[count] = control;
  return graph()->NewNode(phi_op, count + 1, buffer, true);
}


Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
  const Operator* phi_op = common()->EffectPhi(count);
  Node** buffer = EnsureInputBufferSize(count + 1);
  MemsetPointer(buffer, input, count);
  buffer[count] = control;
  return graph()->NewNode(phi_op, count + 1, buffer, true);
}


Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
  int inputs = control->op()->ControlInputCount() + 1;
  if (control->opcode() == IrOpcode::kLoop) {
    // Control node for loop exists, add input.
    const Operator* op = common()->Loop(inputs);
    control->AppendInput(graph_zone(), other);
2782
    NodeProperties::ChangeOp(control, op);
2783 2784 2785 2786
  } else if (control->opcode() == IrOpcode::kMerge) {
    // Control node for merge exists, add input.
    const Operator* op = common()->Merge(inputs);
    control->AppendInput(graph_zone(), other);
2787
    NodeProperties::ChangeOp(control, op);
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803
  } else {
    // Control node is a singleton, introduce a merge.
    const Operator* op = common()->Merge(inputs);
    Node* inputs[] = {control, other};
    control = graph()->NewNode(op, arraysize(inputs), inputs, true);
  }
  return control;
}


Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
  int inputs = control->op()->ControlInputCount();
  if (value->opcode() == IrOpcode::kEffectPhi &&
      NodeProperties::GetControlInput(value) == control) {
    // Phi already exists, add input.
    value->InsertInput(graph_zone(), inputs - 1, other);
2804
    NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819
  } else if (value != other) {
    // Phi does not exist yet, introduce one.
    value = NewEffectPhi(inputs, value, control);
    value->ReplaceInput(inputs - 1, other);
  }
  return value;
}


Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
  int inputs = control->op()->ControlInputCount();
  if (value->opcode() == IrOpcode::kPhi &&
      NodeProperties::GetControlInput(value) == control) {
    // Phi already exists, add input.
    value->InsertInput(graph_zone(), inputs - 1, other);
2820 2821
    NodeProperties::ChangeOp(
        value, common()->Phi(MachineRepresentation::kTagged, inputs));
2822 2823 2824 2825 2826 2827 2828 2829
  } else if (value != other) {
    // Phi does not exist yet, introduce one.
    value = NewPhi(inputs, value, control);
    value->ReplaceInput(inputs - 1, other);
  }
  return value;
}

2830 2831
AstGraphBuilderWithPositions::AstGraphBuilderWithPositions(
    Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
2832
    CallFrequency invocation_frequency, LoopAssignmentAnalysis* loop_assignment,
2833
    SourcePositionTable* source_positions, int inlining_id)
2834
    : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency,
2835
                      loop_assignment),
2836 2837 2838
      source_positions_(source_positions),
      start_position_(info->shared_info()->start_position(), inlining_id) {}

2839 2840 2841
}  // namespace compiler
}  // namespace internal
}  // namespace v8