Update V8 to version 4.1.0.21

This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.

Original commit message:

Version 4.1.0.21 (cherry-pick)

Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412

Unlink pages from the space page list after evacuation.

BUG=430201
LOG=N
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/953813002

Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}

---

FPIIM-449

Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
index 74fb0ae..cde5e71 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -5,10 +5,12 @@
 #include "src/compiler/ast-graph-builder.h"
 
 #include "src/compiler.h"
+#include "src/compiler/ast-loop-assignment-analyzer.h"
 #include "src/compiler/control-builders.h"
 #include "src/compiler/machine-operator.h"
-#include "src/compiler/node-properties.h"
+#include "src/compiler/node-matchers.h"
 #include "src/compiler/node-properties-inl.h"
+#include "src/compiler/node-properties.h"
 #include "src/full-codegen.h"
 #include "src/parser.h"
 #include "src/scopes.h"
@@ -17,14 +19,16 @@
 namespace internal {
 namespace compiler {
 
-AstGraphBuilder::AstGraphBuilder(CompilationInfo* info, JSGraph* jsgraph)
-    : StructuredGraphBuilder(jsgraph->graph(), jsgraph->common()),
+AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
+                                 JSGraph* jsgraph, LoopAssignmentAnalysis* loop)
+    : StructuredGraphBuilder(local_zone, jsgraph->graph(), jsgraph->common()),
       info_(info),
       jsgraph_(jsgraph),
-      globals_(0, info->zone()),
+      globals_(0, local_zone),
       breakable_(NULL),
-      execution_context_(NULL) {
-  InitializeAstVisitor(info->zone());
+      execution_context_(NULL),
+      loop_assignment_analysis_(loop) {
+  InitializeAstVisitor(local_zone);
 }
 
 
@@ -62,20 +66,29 @@
   Environment env(this, scope, graph()->start());
   set_environment(&env);
 
+  // Initialize the incoming context.
+  Node* outer_context = GetFunctionContext();
+  set_current_context(outer_context);
+
+  // Build receiver check for sloppy mode if necessary.
+  // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
+  Node* original_receiver = env.Lookup(scope->receiver());
+  Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver);
+  env.Bind(scope->receiver(), patched_receiver);
+
   // Build node to initialize local function context.
   Node* closure = GetFunctionClosure();
-  Node* outer = GetFunctionContext();
-  Node* inner = BuildLocalFunctionContext(outer, closure);
+  Node* inner_context = BuildLocalFunctionContext(outer_context, closure);
 
   // Push top-level function scope for the function body.
-  ContextScope top_context(this, scope, inner);
+  ContextScope top_context(this, scope, inner_context);
 
   // Build the arguments object if it is used.
   BuildArgumentsObject(scope->arguments());
 
   // Emit tracing call if requested to do so.
   if (FLAG_trace) {
-    NewNode(javascript()->Runtime(Runtime::kTraceEnter, 0));
+    NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0));
   }
 
   // Visit implicit declaration of the function name.
@@ -86,8 +99,8 @@
   // Visit declarations within the function scope.
   VisitDeclarations(scope->declarations());
 
-  // TODO(mstarzinger): This should do an inlined stack check.
-  Node* node = NewNode(javascript()->Runtime(Runtime::kStackGuard, 0));
+  // Build a stack-check before the body.
+  Node* node = BuildStackCheck();
   PrepareFrameState(node, BailoutId::FunctionEntry());
 
   // Visit statements in the function body.
@@ -98,7 +111,7 @@
   if (FLAG_trace) {
     // TODO(mstarzinger): Only traces implicit return.
     Node* return_value = jsgraph()->UndefinedConstant();
-    NewNode(javascript()->Runtime(Runtime::kTraceExit, 1), return_value);
+    NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
   }
 
   // Return 'undefined' in case we can fall off the end.
@@ -129,26 +142,6 @@
 }
 
 
-// Helper to find an existing shared function info in the baseline code for the
-// given function literal. Used to canonicalize SharedFunctionInfo objects.
-static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
-    Code* unoptimized_code, FunctionLiteral* expr) {
-  int start_position = expr->start_position();
-  for (RelocIterator it(unoptimized_code); !it.done(); it.next()) {
-    RelocInfo* rinfo = it.rinfo();
-    if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
-    Object* obj = rinfo->target_object();
-    if (obj->IsSharedFunctionInfo()) {
-      SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
-      if (shared->start_position() == start_position) {
-        return Handle<SharedFunctionInfo>(shared);
-      }
-    }
-  }
-  return Handle<SharedFunctionInfo>();
-}
-
-
 StructuredGraphBuilder::Environment* AstGraphBuilder::CopyEnvironment(
     StructuredGraphBuilder::Environment* env) {
   return new (zone()) Environment(*reinterpret_cast<Environment*>(env));
@@ -329,24 +322,40 @@
 
 void AstGraphBuilder::VisitForValue(Expression* expr) {
   AstValueContext for_value(this);
-  if (!HasStackOverflow()) {
+  if (!CheckStackOverflow()) {
     expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
   }
 }
 
 
 void AstGraphBuilder::VisitForEffect(Expression* expr) {
   AstEffectContext for_effect(this);
-  if (!HasStackOverflow()) {
+  if (!CheckStackOverflow()) {
     expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
   }
 }
 
 
 void AstGraphBuilder::VisitForTest(Expression* expr) {
   AstTestContext for_condition(this);
-  if (!HasStackOverflow()) {
+  if (!CheckStackOverflow()) {
     expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
+  }
+}
+
+
+void AstGraphBuilder::Visit(Expression* expr) {
+  // Reuses enclosing AstContext.
+  if (!CheckStackOverflow()) {
+    expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
   }
 }
 
@@ -360,8 +369,8 @@
       Handle<Oddball> value = variable->binding_needs_init()
                                   ? isolate()->factory()->the_hole_value()
                                   : isolate()->factory()->undefined_value();
-      globals()->Add(variable->name(), zone());
-      globals()->Add(value, zone());
+      globals()->push_back(variable->name());
+      globals()->push_back(value);
       break;
     }
     case Variable::PARAMETER:
@@ -392,8 +401,8 @@
           Compiler::BuildFunctionInfo(decl->fun(), info()->script(), info());
       // Check for stack-overflow exception.
       if (function.is_null()) return SetStackOverflow();
-      globals()->Add(variable->name(), zone());
-      globals()->Add(function, zone());
+      globals()->push_back(variable->name());
+      globals()->push_back(function);
       break;
     }
     case Variable::PARAMETER:
@@ -580,7 +589,7 @@
 
 void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   LoopBuilder while_loop(this);
-  while_loop.BeginLoop();
+  while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
   VisitIterationBody(stmt, &while_loop, 0);
   while_loop.EndBody();
   VisitForTest(stmt->cond());
@@ -592,7 +601,7 @@
 
 void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
   LoopBuilder while_loop(this);
-  while_loop.BeginLoop();
+  while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
   VisitForTest(stmt->cond());
   Node* condition = environment()->Pop();
   while_loop.BreakUnless(condition);
@@ -605,11 +614,13 @@
 void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
   LoopBuilder for_loop(this);
   VisitIfNotNull(stmt->init());
-  for_loop.BeginLoop();
+  for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
   if (stmt->cond() != NULL) {
     VisitForTest(stmt->cond());
     Node* condition = environment()->Pop();
     for_loop.BreakUnless(condition);
+  } else {
+    for_loop.BreakUnless(jsgraph()->TrueConstant());
   }
   VisitIterationBody(stmt, &for_loop, 0);
   for_loop.EndBody();
@@ -639,24 +650,27 @@
     // Convert object to jsobject.
     // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
     obj = NewNode(javascript()->ToObject(), obj);
+    PrepareFrameState(obj, stmt->ToObjectId(), OutputFrameStateCombine::Push());
     environment()->Push(obj);
     // TODO(dcarney): should do a fast enum cache check here to skip runtime.
     environment()->Push(obj);
     Node* cache_type = ProcessArguments(
-        javascript()->Runtime(Runtime::kGetPropertyNamesFast, 1), 1);
+        javascript()->CallRuntime(Runtime::kGetPropertyNamesFast, 1), 1);
+    PrepareFrameState(cache_type, stmt->EnumId(),
+                      OutputFrameStateCombine::Push());
     // TODO(dcarney): these next runtime calls should be removed in favour of
     //                a few simplified instructions.
     environment()->Push(obj);
     environment()->Push(cache_type);
     Node* cache_pair =
-        ProcessArguments(javascript()->Runtime(Runtime::kForInInit, 2), 2);
+        ProcessArguments(javascript()->CallRuntime(Runtime::kForInInit, 2), 2);
     // cache_type may have been replaced.
     Node* cache_array = NewNode(common()->Projection(0), cache_pair);
     cache_type = NewNode(common()->Projection(1), cache_pair);
     environment()->Push(cache_type);
     environment()->Push(cache_array);
     Node* cache_length = ProcessArguments(
-        javascript()->Runtime(Runtime::kForInCacheArrayLength, 2), 2);
+        javascript()->CallRuntime(Runtime::kForInCacheArrayLength, 2), 2);
     {
       // TODO(dcarney): this check is actually supposed to be for the
       //                empty enum case only.
@@ -676,7 +690,7 @@
         environment()->Push(jsgraph()->ZeroConstant());
         // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
         LoopBuilder for_loop(this);
-        for_loop.BeginLoop();
+        for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
         // Check loop termination condition.
         Node* index = environment()->Peek(0);
         Node* exit_cond =
@@ -692,8 +706,8 @@
         environment()->Push(cache_array);
         environment()->Push(cache_type);
         environment()->Push(index);
-        Node* pair =
-            ProcessArguments(javascript()->Runtime(Runtime::kForInNext, 4), 4);
+        Node* pair = ProcessArguments(
+            javascript()->CallRuntime(Runtime::kForInNext, 4), 4);
         Node* value = NewNode(common()->Projection(0), pair);
         Node* should_filter = NewNode(common()->Projection(1), pair);
         environment()->Push(value);
@@ -719,7 +733,7 @@
           // result is either the string key or Smi(0) indicating the property
           // is gone.
           Node* res = ProcessArguments(
-              javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3);
+              javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), 3);
           // TODO(jarin): provide real bailout id.
           PrepareFrameState(res, BailoutId::None());
           Node* property_missing = NewNode(javascript()->StrictEqual(), res,
@@ -785,7 +799,7 @@
 
 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   // TODO(turbofan): Do we really need a separate reloc-info for this?
-  Node* node = NewNode(javascript()->Runtime(Runtime::kDebugBreak, 0));
+  Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0));
   PrepareFrameState(node, stmt->DebugBreakId());
 }
 
@@ -795,8 +809,8 @@
 
   // Build a new shared function info if we cannot find one in the baseline
   // code. We also have a stack overflow if the recursive compilation did.
-  Handle<SharedFunctionInfo> shared_info =
-      SearchSharedFunctionInfo(info()->shared_info()->code(), expr);
+  expr->InitializeSharedInfo(handle(info()->shared_info()->code()));
+  Handle<SharedFunctionInfo> shared_info = expr->shared_info();
   if (shared_info.is_null()) {
     shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info());
     CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
@@ -804,16 +818,14 @@
 
   // Create node to instantiate a new closure.
   Node* info = jsgraph()->Constant(shared_info);
-  Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant()
-                                      : jsgraph()->FalseConstant();
-  const Operator* op = javascript()->Runtime(Runtime::kNewClosure, 3);
+  Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure());
+  const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3);
   Node* value = NewNode(op, context, info, pretenure);
   ast_context()->ProduceValue(value);
 }
 
 
 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
-  // TODO(arv): Implement.
   UNREACHABLE();
 }
 
@@ -838,7 +850,8 @@
 
 
 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
-  Node* value = BuildVariableLoad(expr->var(), expr->id());
+  VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
+  Node* value = BuildVariableLoad(expr->var(), expr->id(), pair);
   ast_context()->ProduceValue(value);
 }
 
@@ -859,8 +872,9 @@
   Node* pattern = jsgraph()->Constant(expr->pattern());
   Node* flags = jsgraph()->Constant(expr->flags());
   const Operator* op =
-      javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4);
+      javascript()->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
+  PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(literal);
 }
 
@@ -875,8 +889,11 @@
   Node* literal_index = jsgraph()->Constant(expr->literal_index());
   Node* constants = jsgraph()->Constant(expr->constant_properties());
   Node* flags = jsgraph()->Constant(expr->ComputeFlags());
-  const Operator* op = javascript()->Runtime(Runtime::kCreateObjectLiteral, 4);
+  const Operator* op =
+      javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
   Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
+  PrepareFrameState(literal, expr->CreateLiteralId(),
+                    OutputFrameStateCombine::Push());
 
   // The object is expected on the operand stack during computation of the
   // property values and is the value of the entire expression.
@@ -924,7 +941,8 @@
         Node* receiver = environment()->Pop();
         if (property->emit_store()) {
           Node* strict = jsgraph()->Constant(SLOPPY);
-          const Operator* op = javascript()->Runtime(Runtime::kSetProperty, 4);
+          const Operator* op =
+              javascript()->CallRuntime(Runtime::kSetProperty, 4);
           NewNode(op, receiver, key, value, strict);
         }
         break;
@@ -935,8 +953,12 @@
         Node* value = environment()->Pop();
         Node* receiver = environment()->Pop();
         if (property->emit_store()) {
-          const Operator* op = javascript()->Runtime(Runtime::kSetPrototype, 2);
-          NewNode(op, receiver, value);
+          const Operator* op =
+              javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
+          Node* set_prototype = NewNode(op, receiver, value);
+          // SetPrototype should not lazy deopt on an object
+          // literal.
+          PrepareFrameState(set_prototype, BailoutId::None());
         }
         break;
       }
@@ -961,14 +983,16 @@
     Node* name = environment()->Pop();
     Node* attr = jsgraph()->Constant(NONE);
     const Operator* op =
-        javascript()->Runtime(Runtime::kDefineAccessorPropertyUnchecked, 5);
+        javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
     Node* call = NewNode(op, literal, name, getter, setter, attr);
-    PrepareFrameState(call, it->first->id());
+    // This should not lazy deopt on a new literal.
+    PrepareFrameState(call, BailoutId::None());
   }
 
   // Transform literals that contain functions to fast properties.
   if (expr->has_function()) {
-    const Operator* op = javascript()->Runtime(Runtime::kToFastProperties, 1);
+    const Operator* op =
+        javascript()->CallRuntime(Runtime::kToFastProperties, 1);
     NewNode(op, literal);
   }
 
@@ -986,7 +1010,8 @@
   Node* literal_index = jsgraph()->Constant(expr->literal_index());
   Node* constants = jsgraph()->Constant(expr->constant_elements());
   Node* flags = jsgraph()->Constant(expr->ComputeFlags());
-  const Operator* op = javascript()->Runtime(Runtime::kCreateArrayLiteral, 4);
+  const Operator* op =
+      javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
   Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
 
   // The array and the literal index are both expected on the operand stack
@@ -1086,23 +1111,31 @@
     Node* old_value = NULL;
     switch (assign_type) {
       case VARIABLE: {
-        Variable* variable = expr->target()->AsVariableProxy()->var();
-        old_value = BuildVariableLoad(variable, expr->target()->id());
+        VariableProxy* proxy = expr->target()->AsVariableProxy();
+        VectorSlotPair pair =
+            CreateVectorSlotPair(proxy->VariableFeedbackSlot());
+        old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair);
         break;
       }
       case NAMED_PROPERTY: {
         Node* object = environment()->Top();
         Unique<Name> name =
             MakeUnique(property->key()->AsLiteral()->AsPropertyName());
-        old_value = NewNode(javascript()->LoadNamed(name), object);
-        PrepareFrameState(old_value, property->LoadId(), kPushOutput);
+        VectorSlotPair pair =
+            CreateVectorSlotPair(property->PropertyFeedbackSlot());
+        old_value = NewNode(javascript()->LoadNamed(name, pair), object);
+        PrepareFrameState(old_value, property->LoadId(),
+                          OutputFrameStateCombine::Push());
         break;
       }
       case KEYED_PROPERTY: {
         Node* key = environment()->Top();
         Node* object = environment()->Peek(1);
-        old_value = NewNode(javascript()->LoadProperty(), object, key);
-        PrepareFrameState(old_value, property->LoadId(), kPushOutput);
+        VectorSlotPair pair =
+            CreateVectorSlotPair(property->PropertyFeedbackSlot());
+        old_value = NewNode(javascript()->LoadProperty(pair), object, key);
+        PrepareFrameState(old_value, property->LoadId(),
+                          OutputFrameStateCombine::Push());
         break;
       }
     }
@@ -1111,7 +1144,8 @@
     Node* right = environment()->Pop();
     Node* left = environment()->Pop();
     Node* value = BuildBinaryOp(left, right, expr->binary_op());
-    PrepareFrameState(value, expr->binary_operation()->id(), kPushOutput);
+    PrepareFrameState(value, expr->binary_operation()->id(),
+                      OutputFrameStateCombine::Push());
     environment()->Push(value);
   } else {
     VisitForValue(expr->value());
@@ -1122,8 +1156,8 @@
   switch (assign_type) {
     case VARIABLE: {
       Variable* variable = expr->target()->AsVariableProxy()->var();
-      BuildVariableAssignment(variable, value, expr->op(),
-                              expr->AssignmentId());
+      BuildVariableAssignment(variable, value, expr->op(), expr->AssignmentId(),
+                              ast_context()->GetStateCombine());
       break;
     }
     case NAMED_PROPERTY: {
@@ -1132,7 +1166,8 @@
           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
       Node* store =
           NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
-      PrepareFrameState(store, expr->AssignmentId());
+      PrepareFrameState(store, expr->AssignmentId(),
+                        ast_context()->GetStateCombine());
       break;
     }
     case KEYED_PROPERTY: {
@@ -1140,7 +1175,8 @@
       Node* object = environment()->Pop();
       Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
                             key, value);
-      PrepareFrameState(store, expr->AssignmentId());
+      PrepareFrameState(store, expr->AssignmentId(),
+                        ast_context()->GetStateCombine());
       break;
     }
   }
@@ -1162,25 +1198,27 @@
 void AstGraphBuilder::VisitThrow(Throw* expr) {
   VisitForValue(expr->exception());
   Node* exception = environment()->Pop();
-  const Operator* op = javascript()->Runtime(Runtime::kThrow, 1);
+  const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
   Node* value = NewNode(op, exception);
+  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
 }
 
 
 void AstGraphBuilder::VisitProperty(Property* expr) {
   Node* value;
+  VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
   if (expr->key()->IsPropertyName()) {
     VisitForValue(expr->obj());
     Node* object = environment()->Pop();
     Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName());
-    value = NewNode(javascript()->LoadNamed(name), object);
+    value = NewNode(javascript()->LoadNamed(name, pair), object);
   } else {
     VisitForValue(expr->obj());
     VisitForValue(expr->key());
     Node* key = environment()->Pop();
     Node* object = environment()->Pop();
-    value = NewNode(javascript()->LoadProperty(), object, key);
+    value = NewNode(javascript()->LoadProperty(pair), object, key);
   }
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
@@ -1199,8 +1237,10 @@
   bool possibly_eval = false;
   switch (call_type) {
     case Call::GLOBAL_CALL: {
-      Variable* variable = callee->AsVariableProxy()->var();
-      callee_value = BuildVariableLoad(variable, expr->expression()->id());
+      VariableProxy* proxy = callee->AsVariableProxy();
+      VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
+      callee_value =
+          BuildVariableLoad(proxy->var(), expr->expression()->id(), pair);
       receiver_value = jsgraph()->UndefinedConstant();
       break;
     }
@@ -1208,26 +1248,33 @@
       Variable* variable = callee->AsVariableProxy()->var();
       DCHECK(variable->location() == Variable::LOOKUP);
       Node* name = jsgraph()->Constant(variable->name());
-      const Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2);
+      const Operator* op =
+          javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
       Node* pair = NewNode(op, current_context(), name);
       callee_value = NewNode(common()->Projection(0), pair);
       receiver_value = NewNode(common()->Projection(1), pair);
+
+      PrepareFrameState(pair, expr->EvalOrLookupId(),
+                        OutputFrameStateCombine::Push(2));
       break;
     }
     case Call::PROPERTY_CALL: {
       Property* property = callee->AsProperty();
       VisitForValue(property->obj());
       Node* object = environment()->Top();
+      VectorSlotPair pair =
+          CreateVectorSlotPair(property->PropertyFeedbackSlot());
       if (property->key()->IsPropertyName()) {
         Unique<Name> name =
             MakeUnique(property->key()->AsLiteral()->AsPropertyName());
-        callee_value = NewNode(javascript()->LoadNamed(name), object);
+        callee_value = NewNode(javascript()->LoadNamed(name, pair), object);
       } else {
         VisitForValue(property->key());
         Node* key = environment()->Pop();
-        callee_value = NewNode(javascript()->LoadProperty(), object, key);
+        callee_value = NewNode(javascript()->LoadProperty(pair), object, key);
       }
-      PrepareFrameState(callee_value, property->LoadId(), kPushOutput);
+      PrepareFrameState(callee_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       receiver_value = environment()->Pop();
       // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
       // object for sloppy callees. This could also be modeled explicitly here,
@@ -1235,6 +1282,11 @@
       flags = CALL_AS_METHOD;
       break;
     }
+    case Call::SUPER_CALL: {
+      // todo(dslomov): implement super calls in turbofan.
+      UNIMPLEMENTED();
+      break;
+    }
     case Call::POSSIBLY_EVAL_CALL:
       possibly_eval = true;
     // Fall through.
@@ -1270,9 +1322,11 @@
     Node* strict = jsgraph()->Constant(strict_mode());
     Node* position = jsgraph()->Constant(info()->scope()->start_position());
     const Operator* op =
-        javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 6);
+        javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
     Node* pair =
         NewNode(op, callee, source, function, receiver, strict, position);
+    PrepareFrameState(pair, expr->EvalOrLookupId(),
+                      OutputFrameStateCombine::PokeAt(arg_count + 1));
     Node* new_callee = NewNode(common()->Projection(0), pair);
     Node* new_receiver = NewNode(common()->Projection(1), pair);
 
@@ -1282,7 +1336,7 @@
   }
 
   // Create node to perform the function call.
-  const Operator* call = javascript()->Call(args->length() + 2, flags);
+  const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
   Node* value = ProcessArguments(call, args->length() + 2);
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
@@ -1297,7 +1351,7 @@
   VisitForValues(args);
 
   // Create node to perform the construct call.
-  const Operator* call = javascript()->CallNew(args->length() + 1);
+  const Operator* call = javascript()->CallConstruct(args->length() + 1);
   Node* value = ProcessArguments(call, args->length() + 1);
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
@@ -1312,10 +1366,13 @@
   CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
   Node* receiver_value = BuildLoadBuiltinsObject();
   Unique<String> unique = MakeUnique(name);
-  Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value);
+  VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot());
+  Node* callee_value =
+      NewNode(javascript()->LoadNamed(unique, pair), receiver_value);
   // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
   // refuses to optimize functions with jsruntime calls).
-  PrepareFrameState(callee_value, BailoutId::None(), kPushOutput);
+  PrepareFrameState(callee_value, BailoutId::None(),
+                    OutputFrameStateCombine::Push());
   environment()->Push(callee_value);
   environment()->Push(receiver_value);
 
@@ -1324,7 +1381,7 @@
   VisitForValues(args);
 
   // Create node to perform the JS runtime call.
-  const Operator* call = javascript()->Call(args->length() + 2, flags);
+  const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
   Node* value = ProcessArguments(call, args->length() + 2);
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
@@ -1347,7 +1404,7 @@
 
   // Create node to perform the runtime call.
   Runtime::FunctionId functionId = function->function_id;
-  const Operator* call = javascript()->Runtime(functionId, args->length());
+  const Operator* call = javascript()->CallRuntime(functionId, args->length());
   Node* value = ProcessArguments(call, args->length());
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
@@ -1386,8 +1443,10 @@
   int stack_depth = -1;
   switch (assign_type) {
     case VARIABLE: {
-      Variable* variable = expr->expression()->AsVariableProxy()->var();
-      old_value = BuildVariableLoad(variable, expr->expression()->id());
+      VariableProxy* proxy = expr->expression()->AsVariableProxy();
+      VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
+      old_value =
+          BuildVariableLoad(proxy->var(), expr->expression()->id(), pair);
       stack_depth = 0;
       break;
     }
@@ -1396,8 +1455,11 @@
       Node* object = environment()->Top();
       Unique<Name> name =
           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
-      old_value = NewNode(javascript()->LoadNamed(name), object);
-      PrepareFrameState(old_value, property->LoadId(), kPushOutput);
+      VectorSlotPair pair =
+          CreateVectorSlotPair(property->PropertyFeedbackSlot());
+      old_value = NewNode(javascript()->LoadNamed(name, pair), object);
+      PrepareFrameState(old_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       stack_depth = 1;
       break;
     }
@@ -1406,8 +1468,11 @@
       VisitForValue(property->key());
       Node* key = environment()->Top();
       Node* object = environment()->Peek(1);
-      old_value = NewNode(javascript()->LoadProperty(), object, key);
-      PrepareFrameState(old_value, property->LoadId(), kPushOutput);
+      VectorSlotPair pair =
+          CreateVectorSlotPair(property->PropertyFeedbackSlot());
+      old_value = NewNode(javascript()->LoadProperty(pair), object, key);
+      PrepareFrameState(old_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       stack_depth = 2;
       break;
     }
@@ -1548,20 +1613,21 @@
 
 
 void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
-  DCHECK(globals()->is_empty());
+  DCHECK(globals()->empty());
   AstVisitor::VisitDeclarations(declarations);
-  if (globals()->is_empty()) return;
-  Handle<FixedArray> data =
-      isolate()->factory()->NewFixedArray(globals()->length(), TENURED);
-  for (int i = 0; i < globals()->length(); ++i) data->set(i, *globals()->at(i));
+  if (globals()->empty()) return;
+  int array_index = 0;
+  Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
+      static_cast<int>(globals()->size()), TENURED);
+  for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
   int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
                       DeclareGlobalsNativeFlag::encode(info()->is_native()) |
                       DeclareGlobalsStrictMode::encode(strict_mode());
   Node* flags = jsgraph()->Constant(encoded_flags);
   Node* pairs = jsgraph()->Constant(data);
-  const Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3);
+  const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals, 3);
   NewNode(op, current_context(), pairs, flags);
-  globals()->Rewind(0);
+  globals()->clear();
 }
 
 
@@ -1585,7 +1651,8 @@
     // deleting "this" is allowed in all language modes.
     Variable* variable = expr->expression()->AsVariableProxy()->var();
     DCHECK(strict_mode() == SLOPPY || variable->is_this());
-    value = BuildVariableDelete(variable);
+    value = BuildVariableDelete(variable, expr->id(),
+                                ast_context()->GetStateCombine());
   } else if (expr->expression()->IsProperty()) {
     Property* property = expr->expression()->AsProperty();
     VisitForValue(property->obj());
@@ -1593,6 +1660,7 @@
     Node* key = environment()->Pop();
     Node* object = environment()->Pop();
     value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key);
+    PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   } else {
     VisitForEffect(expr->expression());
     value = jsgraph()->TrueConstant();
@@ -1613,9 +1681,10 @@
   if (expr->expression()->IsVariableProxy()) {
     // 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.
-    Variable* variable = expr->expression()->AsVariableProxy()->var();
-    operand =
-        BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL);
+    VariableProxy* proxy = expr->expression()->AsVariableProxy();
+    VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
+    operand = BuildVariableLoad(proxy->var(), expr->expression()->id(), pair,
+                                NOT_CONTEXTUAL);
   } else {
     VisitForValue(expr->expression());
     operand = environment()->Pop();
@@ -1666,6 +1735,17 @@
 }
 
 
+StrictMode AstGraphBuilder::strict_mode() const {
+  return info()->strict_mode();
+}
+
+
+VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
+    FeedbackVectorICSlot slot) const {
+  return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
+}
+
+
 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
   DCHECK(environment()->stack_height() >= arity);
   Node** all = info()->zone()->NewArray<Node*>(arity);
@@ -1677,10 +1757,36 @@
 }
 
 
+Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) {
+  // Sloppy mode functions and builtins need to replace the receiver with the
+  // global proxy when called as functions (without an explicit receiver
+  // object). Otherwise there is nothing left to do here.
+  if (info()->strict_mode() != SLOPPY || info()->is_native()) return receiver;
+
+  // There is no need to perform patching if the receiver is never used. Note
+  // that scope predicates are purely syntactical, a call to eval might still
+  // inspect the receiver value.
+  if (!info()->scope()->uses_this() && !info()->scope()->inner_uses_this() &&
+      !info()->scope()->calls_sloppy_eval()) {
+    return receiver;
+  }
+
+  IfBuilder receiver_check(this);
+  Node* undefined = jsgraph()->UndefinedConstant();
+  Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined);
+  receiver_check.If(check);
+  receiver_check.Then();
+  environment()->Push(BuildLoadGlobalProxy());
+  receiver_check.Else();
+  environment()->Push(receiver);
+  receiver_check.End();
+  return environment()->Pop();
+}
+
+
 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) {
   int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
   if (heap_slots <= 0) return context;
-  set_current_context(context);
 
   // Allocate a new local context.
   const Operator* op = javascript()->CreateFunctionContext();
@@ -1710,7 +1816,7 @@
 
   // Allocate and initialize a new arguments object.
   Node* callee = GetFunctionClosure();
-  const Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1);
+  const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1);
   Node* object = NewNode(op, callee);
 
   // Assign the object to the arguments variable.
@@ -1738,13 +1844,14 @@
 
 
 Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
-                                           Node* not_hole) {
+                                           Node* not_hole,
+                                           BailoutId bailout_id) {
   IfBuilder hole_check(this);
   Node* the_hole = jsgraph()->TheHoleConstant();
   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
   hole_check.If(check);
   hole_check.Then();
-  environment()->Push(BuildThrowReferenceError(variable));
+  environment()->Push(BuildThrowReferenceError(variable, bailout_id));
   hole_check.Else();
   environment()->Push(not_hole);
   hole_check.End();
@@ -1754,6 +1861,7 @@
 
 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
                                          BailoutId bailout_id,
+                                         const VectorSlotPair& feedback,
                                          ContextualMode contextual_mode) {
   Node* the_hole = jsgraph()->TheHoleConstant();
   VariableMode mode = variable->mode();
@@ -1762,9 +1870,10 @@
       // Global var, const, or let variable.
       Node* global = BuildLoadGlobalObject();
       Unique<Name> name = MakeUnique(variable->name());
-      const Operator* op = javascript()->LoadNamed(name, contextual_mode);
+      const Operator* op =
+          javascript()->LoadNamed(name, feedback, contextual_mode);
       Node* node = NewNode(op, global);
-      PrepareFrameState(node, bailout_id, kPushOutput);
+      PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push());
       return node;
     }
     case Variable::PARAMETER:
@@ -1782,9 +1891,9 @@
       } else if (mode == LET || mode == CONST) {
         // Perform check for uninitialized let/const variables.
         if (value->op() == the_hole->op()) {
-          value = BuildThrowReferenceError(variable);
+          value = BuildThrowReferenceError(variable, bailout_id);
         } else if (value->opcode() == IrOpcode::kPhi) {
-          value = BuildHoleCheckThrow(value, variable, value);
+          value = BuildHoleCheckThrow(value, variable, value, bailout_id);
         }
       }
       return value;
@@ -1805,7 +1914,7 @@
         value = BuildHoleCheckSilent(value, undefined, value);
       } else if (mode == LET || mode == CONST) {
         // Perform check for uninitialized let/const variables.
-        value = BuildHoleCheckThrow(value, variable, value);
+        value = BuildHoleCheckThrow(value, variable, value, bailout_id);
       }
       return value;
     }
@@ -1816,8 +1925,9 @@
           (contextual_mode == CONTEXTUAL)
               ? Runtime::kLoadLookupSlot
               : Runtime::kLoadLookupSlotNoReferenceError;
-      const Operator* op = javascript()->Runtime(function_id, 2);
+      const Operator* op = javascript()->CallRuntime(function_id, 2);
       Node* pair = NewNode(op, current_context(), name);
+      PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1));
       return NewNode(common()->Projection(0), pair);
     }
   }
@@ -1826,26 +1936,32 @@
 }
 
 
-Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
+Node* AstGraphBuilder::BuildVariableDelete(
+    Variable* variable, BailoutId bailout_id,
+    OutputFrameStateCombine state_combine) {
   switch (variable->location()) {
     case Variable::UNALLOCATED: {
       // Global var, const, or let variable.
       Node* global = BuildLoadGlobalObject();
       Node* name = jsgraph()->Constant(variable->name());
       const Operator* op = javascript()->DeleteProperty(strict_mode());
-      return NewNode(op, global, name);
+      Node* result = NewNode(op, global, name);
+      PrepareFrameState(result, bailout_id, state_combine);
+      return result;
     }
     case Variable::PARAMETER:
     case Variable::LOCAL:
     case Variable::CONTEXT:
       // Local var, const, or let variable or context variable.
-      return variable->is_this() ? jsgraph()->TrueConstant()
-                                 : jsgraph()->FalseConstant();
+      return jsgraph()->BooleanConstant(variable->is_this());
     case Variable::LOOKUP: {
       // Dynamic lookup of context variable (anywhere in the chain).
       Node* name = jsgraph()->Constant(variable->name());
-      const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2);
-      return NewNode(op, current_context(), name);
+      const Operator* op =
+          javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
+      Node* result = NewNode(op, current_context(), name);
+      PrepareFrameState(result, bailout_id, state_combine);
+      return result;
     }
   }
   UNREACHABLE();
@@ -1853,9 +1969,9 @@
 }
 
 
-Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
-                                               Token::Value op,
-                                               BailoutId bailout_id) {
+Node* AstGraphBuilder::BuildVariableAssignment(
+    Variable* variable, Node* value, Token::Value op, BailoutId bailout_id,
+    OutputFrameStateCombine combine) {
   Node* the_hole = jsgraph()->TheHoleConstant();
   VariableMode mode = variable->mode();
   switch (variable->location()) {
@@ -1865,7 +1981,7 @@
       Unique<Name> name = MakeUnique(variable->name());
       const Operator* op = javascript()->StoreNamed(strict_mode(), name);
       Node* store = NewNode(op, global, value);
-      PrepareFrameState(store, bailout_id);
+      PrepareFrameState(store, bailout_id, combine);
       return store;
     }
     case Variable::PARAMETER:
@@ -1878,7 +1994,12 @@
           value = BuildHoleCheckSilent(current, value, current);
         }
       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
-        // Non-initializing assignments to legacy const is ignored.
+        // Non-initializing assignments to legacy const is
+        // - exception in strict mode.
+        // - ignored in sloppy mode.
+        if (strict_mode() == STRICT) {
+          return BuildThrowConstAssignError(bailout_id);
+        }
         return value;
       } else if (mode == LET && op != Token::INIT_LET) {
         // Perform an initialization check for let declared variables.
@@ -1887,13 +2008,13 @@
         // temporal dead zone of a let declared variable.
         Node* current = environment()->Lookup(variable);
         if (current->op() == the_hole->op()) {
-          value = BuildThrowReferenceError(variable);
+          value = BuildThrowReferenceError(variable, bailout_id);
         } else if (value->opcode() == IrOpcode::kPhi) {
-          value = BuildHoleCheckThrow(current, variable, value);
+          value = BuildHoleCheckThrow(current, variable, value, bailout_id);
         }
       } else if (mode == CONST && op != Token::INIT_CONST) {
-        // All assignments to const variables are early errors.
-        UNREACHABLE();
+        // Non-initializing assignments to const is exception in all modes.
+        return BuildThrowConstAssignError(bailout_id);
       }
       environment()->Bind(variable, value);
       return value;
@@ -1907,17 +2028,22 @@
         Node* current = NewNode(op, current_context());
         value = BuildHoleCheckSilent(current, value, current);
       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
-        // Non-initializing assignments to legacy const is ignored.
+        // Non-initializing assignments to legacy const is
+        // - exception in strict mode.
+        // - ignored in sloppy mode.
+        if (strict_mode() == STRICT) {
+          return BuildThrowConstAssignError(bailout_id);
+        }
         return value;
       } else if (mode == LET && op != Token::INIT_LET) {
         // Perform an initialization check for let declared variables.
         const Operator* op =
             javascript()->LoadContext(depth, variable->index(), false);
         Node* current = NewNode(op, current_context());
-        value = BuildHoleCheckThrow(current, variable, value);
+        value = BuildHoleCheckThrow(current, variable, value, bailout_id);
       } else if (mode == CONST && op != Token::INIT_CONST) {
-        // All assignments to const variables are early errors.
-        UNREACHABLE();
+        // Non-initializing assignments to const is exception in all modes.
+        return BuildThrowConstAssignError(bailout_id);
       }
       const Operator* op = javascript()->StoreContext(depth, variable->index());
       return NewNode(op, current_context(), value);
@@ -1928,8 +2054,11 @@
       Node* strict = jsgraph()->Constant(strict_mode());
       // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
       // initializations of const declarations.
-      const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4);
-      return NewNode(op, value, current_context(), name, strict);
+      const Operator* op =
+          javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
+      Node* store = NewNode(op, value, current_context(), name, strict);
+      PrepareFrameState(store, bailout_id, combine);
+      return store;
     }
   }
   UNREACHABLE();
@@ -1938,7 +2067,6 @@
 
 
 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
-  // TODO(sigurds) Use simplified load here once it is ready.
   Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
                              jsgraph()->Int32Constant(offset - kHeapObjectTag));
   return field_load;
@@ -1961,17 +2089,61 @@
 }
 
 
-Node* AstGraphBuilder::BuildToBoolean(Node* value) {
-  // TODO(mstarzinger): Possible optimization is to NOP for boolean values.
-  return NewNode(javascript()->ToBoolean(), value);
+Node* AstGraphBuilder::BuildLoadGlobalProxy() {
+  Node* global = BuildLoadGlobalObject();
+  Node* proxy =
+      BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset);
+  return proxy;
 }
 
 
-Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) {
+Node* AstGraphBuilder::BuildToBoolean(Node* input) {
+  // TODO(titzer): this should be in a JSOperatorReducer.
+  switch (input->opcode()) {
+    case IrOpcode::kInt32Constant:
+      return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0));
+    case IrOpcode::kFloat64Constant:
+      return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0));
+    case IrOpcode::kNumberConstant:
+      return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0));
+    case IrOpcode::kHeapConstant: {
+      Handle<Object> object = HeapObjectMatcher<Object>(input).Value().handle();
+      if (object->IsTrue()) return jsgraph_->TrueConstant();
+      if (object->IsFalse()) return jsgraph_->FalseConstant();
+      // TODO(turbofan): other constants.
+      break;
+    }
+    default:
+      break;
+  }
+  if (NodeProperties::IsTyped(input)) {
+    Type* upper = NodeProperties::GetBounds(input).upper;
+    if (upper->Is(Type::Boolean())) return input;
+  }
+
+  return NewNode(javascript()->ToBoolean(), input);
+}
+
+
+Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
+                                                BailoutId bailout_id) {
   // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
   Node* variable_name = jsgraph()->Constant(variable->name());
-  const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1);
-  return NewNode(op, variable_name);
+  const Operator* op =
+      javascript()->CallRuntime(Runtime::kThrowReferenceError, 1);
+  Node* call = NewNode(op, variable_name);
+  PrepareFrameState(call, bailout_id);
+  return call;
+}
+
+
+Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
+  // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
+  const Operator* op =
+      javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0);
+  Node* call = NewNode(op);
+  PrepareFrameState(call, bailout_id);
+  return call;
 }
 
 
@@ -2019,6 +2191,24 @@
 }
 
 
+Node* AstGraphBuilder::BuildStackCheck() {
+  IfBuilder stack_check(this);
+  Node* limit =
+      NewNode(jsgraph()->machine()->Load(kMachPtr),
+              jsgraph()->ExternalConstant(
+                  ExternalReference::address_of_stack_limit(isolate())),
+              jsgraph()->ZeroConstant());
+  Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer());
+  Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack);
+  stack_check.If(tag, BranchHint::kTrue);
+  stack_check.Then();
+  stack_check.Else();
+  Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0));
+  stack_check.End();
+  return guard;
+}
+
+
 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
                                         OutputFrameStateCombine combine) {
   if (OperatorProperties::HasFrameStateInput(node->op())) {
@@ -2029,6 +2219,13 @@
   }
 }
 
+
+BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
+    IterationStatement* stmt) {
+  if (loop_assignment_analysis_ == NULL) return NULL;
+  return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
 }
-}
-}  // namespace v8::internal::compiler
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8