Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc
index 98337be..b6fdd3a 100644
--- a/src/crankshaft/hydrogen.cc
+++ b/src/crankshaft/hydrogen.cc
@@ -34,6 +34,7 @@
 #include "src/crankshaft/hydrogen-uint32-analysis.h"
 #include "src/crankshaft/lithium-allocator.h"
 #include "src/crankshaft/typing.h"
+#include "src/field-type.h"
 #include "src/full-codegen/full-codegen.h"
 #include "src/ic/call-optimization.h"
 #include "src/ic/ic.h"
@@ -687,33 +688,28 @@
   return value ? GetConstantTrue() : GetConstantFalse();
 }
 
+#define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value,         \
+                            undetectable)                                   \
+  HConstant* HGraph::GetConstant##Name() {                                  \
+    if (!constant_##name##_.is_set()) {                                     \
+      HConstant* constant = new (zone()) HConstant(                         \
+          Unique<Object>::CreateImmovable(                                  \
+              isolate()->factory()->name##_value()),                        \
+          Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()), \
+          false, Representation::Tagged(), htype, true, boolean_value,      \
+          undetectable, ODDBALL_TYPE);                                      \
+      constant->InsertAfter(entry_block()->first());                        \
+      constant_##name##_.set(constant);                                     \
+    }                                                                       \
+    return ReinsertConstantIfNecessary(constant_##name##_.get());           \
+  }
 
-#define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
-HConstant* HGraph::GetConstant##Name() {                                       \
-  if (!constant_##name##_.is_set()) {                                          \
-    HConstant* constant = new(zone()) HConstant(                               \
-        Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
-        Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),      \
-        false,                                                                 \
-        Representation::Tagged(),                                              \
-        htype,                                                                 \
-        true,                                                                  \
-        boolean_value,                                                         \
-        false,                                                                 \
-        ODDBALL_TYPE);                                                         \
-    constant->InsertAfter(entry_block()->first());                             \
-    constant_##name##_.set(constant);                                          \
-  }                                                                            \
-  return ReinsertConstantIfNecessary(constant_##name##_.get());                \
-}
-
-
-DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false)
-DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true)
-DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false)
-DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false)
-DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false)
-
+DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false,
+                    true)
+DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true, false)
+DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false, false)
+DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false, false)
+DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false, true)
 
 #undef DEFINE_GET_CONSTANT
 
@@ -1185,7 +1181,7 @@
 
 
 HGraph* HGraphBuilder::CreateGraph() {
-  graph_ = new(zone()) HGraph(info_);
+  graph_ = new (zone()) HGraph(info_, descriptor_);
   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
   CompilationPhase phase("H_Block building", info_);
   set_current_block(graph()->entry_block());
@@ -1275,6 +1271,14 @@
 }
 
 
+HValue* HGraphBuilder::BuildEnumLength(HValue* map) {
+  NoObservableSideEffectsScope scope(this);
+  HValue* bit_field3 =
+      Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
+  return BuildDecodeField<Map::EnumLengthBits>(bit_field3);
+}
+
+
 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
   if (obj->type().IsHeapObject()) return obj;
   return Add<HCheckHeapObject>(obj);
@@ -1671,10 +1675,10 @@
   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
 }
 
-
-HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
-    HValue* receiver, HValue* elements, HValue* key, HValue* hash,
-    LanguageMode language_mode) {
+HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
+                                                           HValue* elements,
+                                                           HValue* key,
+                                                           HValue* hash) {
   HValue* capacity =
       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
                       nullptr, nullptr, FAST_ELEMENTS);
@@ -1717,11 +1721,8 @@
     // element == undefined means "not found". Call the runtime.
     // TODO(jkummerow): walk the prototype chain instead.
     Add<HPushArguments>(receiver, key);
-    Push(Add<HCallRuntime>(
-        Runtime::FunctionForId(is_strong(language_mode)
-                                   ? Runtime::kKeyedGetPropertyStrong
-                                   : Runtime::kKeyedGetProperty),
-        2));
+    Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
+                           2));
   }
   if_undefined.Else();
   {
@@ -1780,11 +1781,8 @@
                          FAST_ELEMENTS));
     details_compare.Else();
     Add<HPushArguments>(receiver, key);
-    Push(Add<HCallRuntime>(
-        Runtime::FunctionForId(is_strong(language_mode)
-                                   ? Runtime::kKeyedGetPropertyStrong
-                                   : Runtime::kKeyedGetProperty),
-        2));
+    Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
+                           2));
     details_compare.End();
 
     found_key_match.Else();
@@ -1819,7 +1817,7 @@
   // Allocate the JSIteratorResult object.
   HValue* result =
       Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
-                     NOT_TENURED, JS_ITERATOR_RESULT_TYPE);
+                     NOT_TENURED, JS_OBJECT_TYPE);
 
   // Initialize the JSIteratorResult object.
   HValue* native_context = BuildGetNativeContext();
@@ -2052,6 +2050,20 @@
   return Pop();
 }
 
+HValue* HGraphBuilder::BuildToNumber(HValue* input) {
+  if (input->type().IsTaggedNumber()) {
+    return input;
+  }
+  Callable callable = CodeFactory::ToNumber(isolate());
+  HValue* stub = Add<HConstant>(callable.code());
+  HValue* values[] = {context(), input};
+  HCallWithDescriptor* instr =
+      Add<HCallWithDescriptor>(stub, 0, callable.descriptor(),
+                               Vector<HValue*>(values, arraysize(values)));
+  instr->set_type(HType::TaggedNumber());
+  return instr;
+}
+
 
 HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
   NoObservableSideEffectsScope scope(this);
@@ -2578,8 +2590,8 @@
         HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
     HValue* base_pointer = Add<HLoadNamedField>(
         elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
-    HValue* backing_store = AddUncasted<HAdd>(
-        external_pointer, base_pointer, Strength::WEAK, AddOfExternalAndTagged);
+    HValue* backing_store = AddUncasted<HAdd>(external_pointer, base_pointer,
+                                              AddOfExternalAndTagged);
 
     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
       NoObservableSideEffectsScope no_effects(this);
@@ -3171,37 +3183,24 @@
                                     HIfContinuation* continuation,
                                     MapEmbedding map_embedding) {
   IfBuilder if_nil(this);
-  bool some_case_handled = false;
-  bool some_case_missing = false;
-
-  if (type->Maybe(Type::Null())) {
-    if (some_case_handled) if_nil.Or();
-    if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
-    some_case_handled = true;
-  } else {
-    some_case_missing = true;
-  }
-
-  if (type->Maybe(Type::Undefined())) {
-    if (some_case_handled) if_nil.Or();
-    if_nil.If<HCompareObjectEqAndBranch>(value,
-                                         graph()->GetConstantUndefined());
-    some_case_handled = true;
-  } else {
-    some_case_missing = true;
-  }
 
   if (type->Maybe(Type::Undetectable())) {
-    if (some_case_handled) if_nil.Or();
     if_nil.If<HIsUndetectableAndBranch>(value);
-    some_case_handled = true;
   } else {
-    some_case_missing = true;
-  }
+    bool maybe_null = type->Maybe(Type::Null());
+    if (maybe_null) {
+      if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
+    }
 
-  if (some_case_missing) {
+    if (type->Maybe(Type::Undefined())) {
+      if (maybe_null) if_nil.Or();
+      if_nil.If<HCompareObjectEqAndBranch>(value,
+                                           graph()->GetConstantUndefined());
+    }
+
     if_nil.Then();
     if_nil.Else();
+
     if (type->NumClasses() == 1) {
       BuildCheckHeapObject(value);
       // For ICs, the map checked below is a sentinel map that gets replaced by
@@ -3547,14 +3546,14 @@
 
 
 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
-    : HGraphBuilder(info),
+    : HGraphBuilder(info, CallInterfaceDescriptor()),
       function_state_(NULL),
       initial_function_state_(this, info, NORMAL_RETURN, 0),
       ast_context_(NULL),
       break_scope_(NULL),
       inlined_count_(0),
       globals_(10, info->zone()),
-      osr_(new(info->zone()) HOsrBuilder(this)) {
+      osr_(new (info->zone()) HOsrBuilder(this)) {
   // This is not initialized in the initializer list because the
   // constructor for the initial state relies on function_state_ == NULL
   // to know it's the initial state.
@@ -3641,7 +3640,7 @@
 }
 
 
-HGraph::HGraph(CompilationInfo* info)
+HGraph::HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor)
     : isolate_(info->isolate()),
       next_block_id_(0),
       entry_block_(NULL),
@@ -3651,6 +3650,7 @@
       uint32_instructions_(NULL),
       osr_(NULL),
       info_(info),
+      descriptor_(descriptor),
       zone_(info->zone()),
       is_recursive_(false),
       use_optimistic_licm_(false),
@@ -3660,10 +3660,9 @@
       no_side_effects_scope_count_(0),
       disallow_adding_new_values_(false) {
   if (info->IsStub()) {
-    CallInterfaceDescriptor descriptor =
-        info->code_stub()->GetCallInterfaceDescriptor();
-    start_environment_ =
-        new (zone_) HEnvironment(zone_, descriptor.GetRegisterParameterCount());
+    // For stubs, explicitly add the context to the environment.
+    start_environment_ = new (zone_)
+        HEnvironment(zone_, descriptor.GetRegisterParameterCount() + 1);
   } else {
     if (info->is_tracking_positions()) {
       info->TraceInlinedFunction(info->shared_info(), SourcePosition::Unknown(),
@@ -4675,12 +4674,11 @@
   }
 
   AddInstruction(arguments_object);
-  graph()->SetArgumentsObject(arguments_object);
 
   // Handle the arguments and arguments shadow variables specially (they do
   // not have declarations).
   if (scope->arguments() != NULL) {
-    environment()->Bind(scope->arguments(), graph()->GetArgumentsObject());
+    environment()->Bind(scope->arguments(), arguments_object);
   }
 
   int rest_index;
@@ -4736,8 +4734,11 @@
         }
         AddInstruction(function);
         // Allocate a block context and store it to the stack frame.
-        HInstruction* inner_context = Add<HAllocateBlockContext>(
-            outer_context, function, scope->GetScopeInfo(isolate()));
+        HValue* scope_info = Add<HConstant>(scope->GetScopeInfo(isolate()));
+        Add<HPushArguments>(scope_info, function);
+        HInstruction* inner_context = Add<HCallRuntime>(
+            Runtime::FunctionForId(Runtime::kPushBlockContext), 2);
+        inner_context->SetFlag(HValue::kHasNoObservableSideEffects);
         HInstruction* instr = Add<HStoreFrameContext>(inner_context);
         set_scope(scope);
         environment()->BindContext(inner_context);
@@ -4955,9 +4956,8 @@
     // will always evaluate to true, in a value context the return value needs
     // to be a JSObject.
     if (context->IsTest()) {
-      TestContext* test = TestContext::cast(context);
       CHECK_ALIVE(VisitForEffect(stmt->expression()));
-      Goto(test->if_true(), state);
+      context->ReturnValue(graph()->GetConstantTrue());
     } else if (context->IsEffect()) {
       CHECK_ALIVE(VisitForEffect(stmt->expression()));
       Goto(function_return(), state);
@@ -5283,10 +5283,6 @@
   DCHECK(current_block() != NULL);
   DCHECK(current_block()->HasPredecessor());
 
-  if (!FLAG_optimize_for_in) {
-    return Bailout(kForInStatementOptimizationIsDisabled);
-  }
-
   if (!stmt->each()->IsVariableProxy() ||
       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
     return Bailout(kForInStatementWithNonLocalEachVariable);
@@ -5312,57 +5308,73 @@
 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
                                             Variable* each_var,
                                             HValue* enumerable) {
-  HInstruction* map;
-  HInstruction* array;
-  HInstruction* enum_length;
+  Handle<Map> meta_map = isolate()->factory()->meta_map();
   bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
+  BuildCheckHeapObject(enumerable);
+  Add<HCheckInstanceType>(enumerable, HCheckInstanceType::IS_JS_RECEIVER);
+  Add<HSimulate>(stmt->ToObjectId());
   if (fast) {
-    map = Add<HForInPrepareMap>(enumerable);
-    Add<HSimulate>(stmt->PrepareId());
+    HForInPrepareMap* map = Add<HForInPrepareMap>(enumerable);
+    Push(map);
+    Add<HSimulate>(stmt->EnumId());
+    Drop(1);
+    Add<HCheckMaps>(map, meta_map);
 
-    array = Add<HForInCacheArray>(enumerable, map,
-                                  DescriptorArray::kEnumCacheBridgeCacheIndex);
-    enum_length = Add<HMapEnumLength>(map);
+    HForInCacheArray* array = Add<HForInCacheArray>(
+        enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
+    HValue* enum_length = BuildEnumLength(map);
 
-    HInstruction* index_cache = Add<HForInCacheArray>(
+    HForInCacheArray* index_cache = Add<HForInCacheArray>(
         enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
-    HForInCacheArray::cast(array)
-        ->set_index_cache(HForInCacheArray::cast(index_cache));
-  } else {
-    Add<HSimulate>(stmt->PrepareId());
-    {
-      NoObservableSideEffectsScope no_effects(this);
-      BuildJSObjectCheck(enumerable, 0);
-    }
-    Add<HSimulate>(stmt->ToObjectId());
+    array->set_index_cache(index_cache);
 
-    map = graph()->GetConstant1();
-    Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast;
+    Push(map);
+    Push(array);
+    Push(enum_length);
+    Add<HSimulate>(stmt->PrepareId());
+  } else {
+    Runtime::FunctionId function_id = Runtime::kForInEnumerate;
     Add<HPushArguments>(enumerable);
-    array = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
+    HCallRuntime* array =
+        Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
     Push(array);
     Add<HSimulate>(stmt->EnumId());
     Drop(1);
-    Handle<Map> array_map = isolate()->factory()->fixed_array_map();
-    HValue* check = Add<HCheckMaps>(array, array_map);
-    enum_length = AddLoadFixedArrayLength(array, check);
+
+    IfBuilder if_fast(this);
+    if_fast.If<HCompareMap>(array, meta_map);
+    if_fast.Then();
+    {
+      HValue* cache_map = array;
+      HForInCacheArray* cache = Add<HForInCacheArray>(
+          enumerable, cache_map, DescriptorArray::kEnumCacheBridgeCacheIndex);
+      HValue* enum_length = BuildEnumLength(cache_map);
+      Push(cache_map);
+      Push(cache);
+      Push(enum_length);
+      Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
+    }
+    if_fast.Else();
+    {
+      Push(graph()->GetConstant1());
+      Push(array);
+      Push(AddLoadFixedArrayLength(array));
+      Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
+    }
   }
 
-  HInstruction* start_index = Add<HConstant>(0);
-
-  Push(map);
-  Push(array);
-  Push(enum_length);
-  Push(start_index);
+  Push(graph()->GetConstant0());
 
   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
 
   // Reload the values to ensure we have up-to-date values inside of the loop.
   // This is relevant especially for OSR where the values don't come from the
   // computation above, but from the OSR entry block.
-  enumerable = environment()->ExpressionStackAt(4);
   HValue* index = environment()->ExpressionStackAt(0);
   HValue* limit = environment()->ExpressionStackAt(1);
+  HValue* array = environment()->ExpressionStackAt(2);
+  HValue* type = environment()->ExpressionStackAt(3);
+  enumerable = environment()->ExpressionStackAt(4);
 
   // Check that we still have more keys.
   HCompareNumericAndBranch* compare_index =
@@ -5382,32 +5394,67 @@
 
   set_current_block(loop_body);
 
-  HValue* key =
-      Add<HLoadKeyed>(environment()->ExpressionStackAt(2),  // Enum cache.
-                      index, index, nullptr, FAST_ELEMENTS);
+  // Compute the next enumerated value.
+  HValue* key = Add<HLoadKeyed>(array, index, index, nullptr, FAST_ELEMENTS);
 
+  HBasicBlock* continue_block = nullptr;
   if (fast) {
-    // Check if the expected map still matches that of the enumerable.
-    // If not just deoptimize.
-    Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3));
-    Bind(each_var, key);
-  } else {
-    Add<HPushArguments>(enumerable, key);
-    Runtime::FunctionId function_id = Runtime::kForInFilter;
-    key = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
-    Push(key);
+    // Check if expected map still matches that of the enumerable.
+    Add<HCheckMapValue>(enumerable, type);
     Add<HSimulate>(stmt->FilterId());
+  } else {
+    // We need the continue block here to be able to skip over invalidated keys.
+    continue_block = graph()->CreateBasicBlock();
+
+    // We cannot use the IfBuilder here, since we need to be able to jump
+    // over the loop body in case of undefined result from %ForInFilter,
+    // and the poor soul that is the IfBuilder get's really confused about
+    // such "advanced control flow requirements".
+    HBasicBlock* if_fast = graph()->CreateBasicBlock();
+    HBasicBlock* if_slow = graph()->CreateBasicBlock();
+    HBasicBlock* if_slow_pass = graph()->CreateBasicBlock();
+    HBasicBlock* if_slow_skip = graph()->CreateBasicBlock();
+    HBasicBlock* if_join = graph()->CreateBasicBlock();
+
+    // Check if expected map still matches that of the enumerable.
+    HValue* enumerable_map =
+        Add<HLoadNamedField>(enumerable, nullptr, HObjectAccess::ForMap());
+    FinishCurrentBlock(
+        New<HCompareObjectEqAndBranch>(enumerable_map, type, if_fast, if_slow));
+    set_current_block(if_fast);
+    {
+      // The enum cache for enumerable is still valid, no need to check key.
+      Push(key);
+      Goto(if_join);
+    }
+    set_current_block(if_slow);
+    {
+      // Check if key is still valid for enumerable.
+      Add<HPushArguments>(enumerable, key);
+      Runtime::FunctionId function_id = Runtime::kForInFilter;
+      Push(Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2));
+      Add<HSimulate>(stmt->FilterId());
+      FinishCurrentBlock(New<HCompareObjectEqAndBranch>(
+          Top(), graph()->GetConstantUndefined(), if_slow_skip, if_slow_pass));
+    }
+    set_current_block(if_slow_pass);
+    { Goto(if_join); }
+    set_current_block(if_slow_skip);
+    {
+      // The key is no longer valid for enumerable, skip it.
+      Drop(1);
+      Goto(continue_block);
+    }
+    if_join->SetJoinId(stmt->FilterId());
+    set_current_block(if_join);
     key = Pop();
-    Bind(each_var, key);
-    IfBuilder if_undefined(this);
-    if_undefined.If<HCompareObjectEqAndBranch>(key,
-                                               graph()->GetConstantUndefined());
-    if_undefined.ThenDeopt(Deoptimizer::kUndefined);
-    if_undefined.End();
-    Add<HSimulate>(stmt->AssignmentId());
   }
 
+  Bind(each_var, key);
+  Add<HSimulate>(stmt->AssignmentId());
+
   BreakAndContinueInfo break_info(stmt, scope(), 5);
+  break_info.set_continue_block(continue_block);
   {
     BreakAndContinueScope push(&break_info, this);
     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
@@ -5420,7 +5467,10 @@
     set_current_block(body_exit);
 
     HValue* current_index = Pop();
-    Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
+    HValue* increment =
+        AddUncasted<HAdd>(current_index, graph()->GetConstant1());
+    increment->ClearFlag(HValue::kCanOverflow);
+    Push(increment);
     body_exit = current_block();
   }
 
@@ -5638,7 +5688,7 @@
           Handle<Context> script_context = ScriptContextTable::GetContext(
               script_contexts, lookup.context_index);
           Handle<Object> current_value =
-              FixedArray::get(script_context, lookup.slot_index);
+              FixedArray::get(*script_context, lookup.slot_index, isolate());
 
           // If the values is not the hole, it will stay initialized,
           // so no need to generate a check.
@@ -6069,9 +6119,7 @@
 
   for (int i = 0; i < length; i++) {
     Expression* subexpr = subexprs->at(i);
-    if (subexpr->IsSpread()) {
-      return Bailout(kSpread);
-    }
+    DCHECK(!subexpr->IsSpread());
 
     // If the subexpression is a literal or a simple materialized literal it
     // is already set in the cloned array.
@@ -6221,6 +6269,13 @@
   return instr;
 }
 
+Handle<FieldType>
+HOptimizedGraphBuilder::PropertyAccessInfo::GetFieldTypeFromMap(
+    Handle<Map> map) const {
+  DCHECK(IsFound());
+  DCHECK(number_ < map->NumberOfOwnDescriptors());
+  return handle(map->instance_descriptors()->GetFieldType(number_), isolate());
+}
 
 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
     PropertyAccessInfo* info) {
@@ -6316,15 +6371,15 @@
     Object* raw_accessor =
         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
                  : Handle<AccessorPair>::cast(accessors)->setter();
-    if (!raw_accessor->IsJSFunction()) return false;
-    Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
-    if (accessor->shared()->IsApiFunction()) {
-      CallOptimization call_optimization(accessor);
-      if (call_optimization.is_simple_api_call()) {
-        CallOptimization::HolderLookup holder_lookup;
-        api_holder_ =
-            call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
-      }
+    if (!raw_accessor->IsJSFunction() &&
+        !raw_accessor->IsFunctionTemplateInfo())
+      return false;
+    Handle<Object> accessor = handle(HeapObject::cast(raw_accessor));
+    CallOptimization call_optimization(accessor);
+    if (call_optimization.is_simple_api_call()) {
+      CallOptimization::HolderLookup holder_lookup;
+      api_holder_ =
+          call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
     }
     accessor_ = accessor;
   } else if (IsDataConstant()) {
@@ -6342,35 +6397,24 @@
   field_type_ = HType::Tagged();
 
   // Figure out the field type from the accessor map.
-  Handle<HeapType> field_type = GetFieldTypeFromMap(map);
+  Handle<FieldType> field_type = GetFieldTypeFromMap(map);
 
   // Collect the (stable) maps from the field type.
-  int num_field_maps = field_type->NumClasses();
-  if (num_field_maps > 0) {
+  if (field_type->IsClass()) {
     DCHECK(access_.representation().IsHeapObject());
-    field_maps_.Reserve(num_field_maps, zone());
-    HeapType::Iterator<Map> it = field_type->Classes();
-    while (!it.Done()) {
-      Handle<Map> field_map = it.Current();
-      if (!field_map->is_stable()) {
-        field_maps_.Clear();
-        break;
-      }
+    Handle<Map> field_map = field_type->AsClass();
+    if (field_map->is_stable()) {
       field_maps_.Add(field_map, zone());
-      it.Advance();
     }
   }
 
   if (field_maps_.is_empty()) {
     // Store is not safe if the field map was cleared.
-    return IsLoad() || !field_type->Is(HeapType::None());
+    return IsLoad() || !field_type->IsNone();
   }
 
-  field_maps_.Sort();
-  DCHECK_EQ(num_field_maps, field_maps_.length());
-
-  // Determine field HType from field HeapType.
-  field_type_ = HType::FromType<HeapType>(field_type);
+  // Determine field HType from field type.
+  field_type_ = HType::FromFieldType(field_type, zone());
   DCHECK(field_type_.IsHeapObject());
 
   // Add dependency on the map that introduced the field.
@@ -6381,6 +6425,10 @@
 
 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
   Handle<Map> map = this->map();
+  if (name_->IsPrivate()) {
+    NotFound();
+    return !map->has_hidden_prototype();
+  }
 
   while (map->prototype()->IsJSObject()) {
     holder_ = handle(JSObject::cast(map->prototype()));
@@ -6573,7 +6621,8 @@
       Push(value);
     }
 
-    if (info->NeedsWrappingFor(info->accessor())) {
+    if (info->accessor()->IsJSFunction() &&
+        info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) {
       HValue* function = Add<HConstant>(info->accessor());
       PushArgumentsFromEnvironment(argument_count);
       return New<HCallFunction>(function, argument_count,
@@ -6587,7 +6636,12 @@
     }
 
     PushArgumentsFromEnvironment(argument_count);
-    return BuildCallConstantFunction(info->accessor(), argument_count);
+    if (!info->accessor()->IsJSFunction()) {
+      Bailout(kInliningBailedOut);
+      return nullptr;
+    }
+    return BuildCallConstantFunction(Handle<JSFunction>::cast(info->accessor()),
+                                     argument_count);
   }
 
   DCHECK(info->IsDataConstant());
@@ -6744,18 +6798,48 @@
   }
 }
 
-
-static bool ComputeReceiverTypes(Expression* expr,
-                                 HValue* receiver,
+static bool ComputeReceiverTypes(Expression* expr, HValue* receiver,
                                  SmallMapList** t,
-                                 Zone* zone) {
+                                 HOptimizedGraphBuilder* builder) {
+  Zone* zone = builder->zone();
   SmallMapList* maps = expr->GetReceiverTypes();
   *t = maps;
   bool monomorphic = expr->IsMonomorphic();
   if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
-    Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
-    maps->FilterForPossibleTransitions(root_map);
-    monomorphic = maps->length() == 1;
+    if (maps->length() > 0) {
+      Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
+      maps->FilterForPossibleTransitions(root_map);
+      monomorphic = maps->length() == 1;
+    } else {
+      // No type feedback, see if we can infer the type. This is safely
+      // possible if the receiver had a known map at some point, and no
+      // map-changing stores have happened to it since.
+      Handle<Map> candidate_map = receiver->GetMonomorphicJSObjectMap();
+      if (candidate_map->is_observed()) return false;
+      for (HInstruction* current = builder->current_block()->last();
+           current != nullptr; current = current->previous()) {
+        if (current->IsBlockEntry()) break;
+        if (current->CheckChangesFlag(kMaps)) {
+          // Only allow map changes that store the candidate map. We don't
+          // need to care which object the map is being written into.
+          if (!current->IsStoreNamedField()) break;
+          HStoreNamedField* map_change = HStoreNamedField::cast(current);
+          if (!map_change->value()->IsConstant()) break;
+          HConstant* map_constant = HConstant::cast(map_change->value());
+          if (!map_constant->representation().IsTagged()) break;
+          Handle<Object> map = map_constant->handle(builder->isolate());
+          if (!map.is_identical_to(candidate_map)) break;
+        }
+        if (current == receiver) {
+          // We made it all the way back to the receiver without encountering
+          // a map change! So we can assume that the receiver still has the
+          // candidate_map we know about.
+          maps->Add(candidate_map, zone);
+          monomorphic = true;
+          break;
+        }
+      }
+    }
   }
   return monomorphic && CanInlinePropertyAccess(maps->first());
 }
@@ -6846,7 +6930,7 @@
           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
 
       Handle<Object> current_value =
-          FixedArray::get(script_context, lookup.slot_index);
+          FixedArray::get(*script_context, lookup.slot_index, isolate());
 
       // If the values is not the hole, it will stay initialized,
       // so no need to generate a check.
@@ -7246,14 +7330,14 @@
       // use a generic Keyed Load if we are using the type vector, because
       // it has to share information with full code.
       HConstant* key = Add<HConstant>(name);
-      HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
-          object, key, function_language_mode(), PREMONOMORPHIC);
+      HLoadKeyedGeneric* result =
+          New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC);
       result->SetVectorAndSlot(vector, slot);
       return result;
     }
 
-    HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
-        object, name, function_language_mode(), PREMONOMORPHIC);
+    HLoadNamedGeneric* result =
+        New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
     result->SetVectorAndSlot(vector, slot);
     return result;
   } else {
@@ -7287,8 +7371,8 @@
     HValue* object, HValue* key, HValue* value) {
   if (access_type == LOAD) {
     InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
-    HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
-        object, key, function_language_mode(), initial_state);
+    HLoadKeyedGeneric* result =
+        New<HLoadKeyedGeneric>(object, key, initial_state);
     // HLoadKeyedGeneric with vector ics benefits from being encoded as
     // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
     if (initial_state != MEGAMORPHIC) {
@@ -7370,8 +7454,8 @@
 
 
 static bool CanInlineElementAccess(Handle<Map> map) {
-  return map->IsJSObjectMap() && !map->has_dictionary_elements() &&
-         !map->has_sloppy_arguments_elements() &&
+  return map->IsJSObjectMap() &&
+         (map->has_fast_elements() || map->has_fixed_typed_array_elements()) &&
          !map->has_indexed_interceptor() && !map->is_access_check_needed();
 }
 
@@ -7664,7 +7748,7 @@
   HInstruction* instr = NULL;
 
   SmallMapList* maps;
-  bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());
+  bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, this);
 
   bool force_generic = false;
   if (expr->GetKeyType() == PROPERTY) {
@@ -7790,7 +7874,7 @@
       result = New<HConstant>(argument_count);
     }
   } else {
-    Push(graph()->GetArgumentsObject());
+    CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
     HValue* key = Pop();
     Drop(1);  // Arguments object.
@@ -7821,7 +7905,7 @@
     Expression* expr, FeedbackVectorSlot slot, HValue* object,
     Handle<Name> name, HValue* value, bool is_uninitialized) {
   SmallMapList* maps;
-  ComputeReceiverTypes(expr, object, &maps, zone());
+  ComputeReceiverTypes(expr, object, &maps, this);
   DCHECK(maps != NULL);
 
   if (maps->length() > 0) {
@@ -8341,10 +8425,12 @@
   CompilationInfo target_info(&parse_info);
   Handle<SharedFunctionInfo> target_shared(target->shared());
 
-  if (IsClassConstructor(target_shared->kind())) {
+  if (inlining_kind != CONSTRUCT_CALL_RETURN &&
+      IsClassConstructor(target_shared->kind())) {
     TraceInline(target, caller, "target is classConstructor");
     return false;
   }
+
   if (target_shared->HasDebugInfo()) {
     TraceInline(target, caller, "target is being debugged");
     return false;
@@ -8531,7 +8617,7 @@
       // return value will always evaluate to true, in a value context the
       // return value is the newly allocated receiver.
       if (call_context()->IsTest()) {
-        Goto(inlined_test_context()->if_true(), state);
+        inlined_test_context()->ReturnValue(graph()->GetConstantTrue());
       } else if (call_context()->IsEffect()) {
         Goto(function_return(), state);
       } else {
@@ -8554,7 +8640,7 @@
       // Falling off the end of a normal inlined function. This basically means
       // returning undefined.
       if (call_context()->IsTest()) {
-        Goto(inlined_test_context()->if_false(), state);
+        inlined_test_context()->ReturnValue(graph()->GetConstantFalse());
       } else if (call_context()->IsEffect()) {
         Goto(function_return(), state);
       } else {
@@ -8617,24 +8703,25 @@
                    CONSTRUCT_CALL_RETURN);
 }
 
-
-bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
+bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter,
                                              Handle<Map> receiver_map,
                                              BailoutId ast_id,
                                              BailoutId return_id) {
   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
-  return TryInline(getter, 0, NULL, ast_id, return_id, GETTER_CALL_RETURN);
+  return getter->IsJSFunction() &&
+         TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id,
+                   GETTER_CALL_RETURN);
 }
 
-
-bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
+bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
                                              Handle<Map> receiver_map,
                                              BailoutId id,
                                              BailoutId assignment_id,
                                              HValue* implicit_return_value) {
   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
-  return TryInline(setter, 1, implicit_return_value, id, assignment_id,
-                   SETTER_CALL_RETURN);
+  return setter->IsJSFunction() &&
+         TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value,
+                   id, assignment_id, SETTER_CALL_RETURN);
 }
 
 
@@ -8694,7 +8781,8 @@
   Isolate* isolate = jsarray_map->GetIsolate();
   Handle<Name> length_string = isolate->factory()->length_string();
   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
-  int number = descriptors->SearchWithCache(*length_string, *jsarray_map);
+  int number =
+      descriptors->SearchWithCache(isolate, *length_string, *jsarray_map);
   DCHECK_NE(DescriptorArray::kNotFound, number);
   return descriptors->GetDetails(number).IsReadOnly();
 }
@@ -9058,6 +9146,7 @@
     case kArrayLastIndexOf: {
       if (receiver_map.is_null()) return false;
       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
+      if (!receiver_map->prototype()->IsJSObject()) return false;
       ElementsKind kind = receiver_map->elements_kind();
       if (!IsFastElementsKind(kind)) return false;
       if (receiver_map->is_observed()) return false;
@@ -9127,8 +9216,7 @@
                           kCallApiMethod);
 }
 
-
-bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
+bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function,
                                                 Handle<Map> receiver_map,
                                                 BailoutId ast_id) {
   SmallMapList receiver_maps(1, zone());
@@ -9141,8 +9229,7 @@
                           kCallApiGetter);
 }
 
-
-bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
+bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function,
                                                 Handle<Map> receiver_map,
                                                 BailoutId ast_id) {
   SmallMapList receiver_maps(1, zone());
@@ -9155,15 +9242,14 @@
                           kCallApiSetter);
 }
 
-
-bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
-                                               HValue* receiver,
-                                               SmallMapList* receiver_maps,
-                                               int argc,
-                                               BailoutId ast_id,
-                                               ApiCallType call_type) {
-  if (function->context()->native_context() !=
-      top_info()->closure()->context()->native_context()) {
+bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<Object> function,
+                                              HValue* receiver,
+                                              SmallMapList* receiver_maps,
+                                              int argc, BailoutId ast_id,
+                                              ApiCallType call_type) {
+  if (function->IsJSFunction() &&
+      Handle<JSFunction>::cast(function)->context()->native_context() !=
+          top_info()->closure()->context()->native_context()) {
     return false;
   }
   CallOptimization optimization(function);
@@ -9178,8 +9264,11 @@
     // Cannot embed a direct reference to the global proxy map
     // as it maybe dropped on deserialization.
     CHECK(!isolate()->serializer_enabled());
+    DCHECK(function->IsJSFunction());
     DCHECK_EQ(0, receiver_maps->length());
-    receiver_maps->Add(handle(function->global_proxy()->map()), zone());
+    receiver_maps->Add(
+        handle(Handle<JSFunction>::cast(function)->global_proxy()->map()),
+        zone());
   }
   CallOptimization::HolderLookup holder_lookup =
       CallOptimization::kHolderNotFound;
@@ -9259,7 +9348,8 @@
 
   HInstruction* call = nullptr;
   if (!is_function) {
-    CallApiAccessorStub stub(isolate(), is_store, call_data_undefined);
+    CallApiAccessorStub stub(isolate(), is_store, call_data_undefined,
+                             !optimization.is_constant_call());
     Handle<Code> code = stub.GetCode();
     HConstant* code_value = Add<HConstant>(code);
     ApiAccessorDescriptor descriptor(isolate());
@@ -9643,6 +9733,9 @@
 
 
 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
+  if (expr->tail_call_mode() == TailCallMode::kAllow) {
+    return Bailout(kTailCall);
+  }
   DCHECK(!HasStackOverflow());
   DCHECK(current_block() != NULL);
   DCHECK(current_block()->HasPredecessor());
@@ -9657,7 +9750,7 @@
     HValue* receiver = Top();
 
     SmallMapList* maps;
-    ComputeReceiverTypes(expr, receiver, &maps, zone());
+    ComputeReceiverTypes(expr, receiver, &maps, this);
 
     if (prop->key()->IsPropertyName() && maps->length() > 0) {
       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
@@ -9852,7 +9945,7 @@
 // Checks whether allocation using the given constructor can be inlined.
 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
   return constructor->has_initial_map() &&
-         !IsClassConstructor(constructor->shared()->kind()) &&
+         !IsSubclassConstructor(constructor->shared()->kind()) &&
          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
          constructor->initial_map()->instance_size() <
              HAllocate::kMaxInlineSize;
@@ -10105,31 +10198,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateDataViewInitialize(
-    CallRuntime* expr) {
-  ZoneList<Expression*>* arguments = expr->arguments();
-
-  DCHECK(arguments->length()== 4);
-  CHECK_ALIVE(VisitForValue(arguments->at(0)));
-  HValue* obj = Pop();
-
-  CHECK_ALIVE(VisitForValue(arguments->at(1)));
-  HValue* buffer = Pop();
-
-  CHECK_ALIVE(VisitForValue(arguments->at(2)));
-  HValue* byte_offset = Pop();
-
-  CHECK_ALIVE(VisitForValue(arguments->at(3)));
-  HValue* byte_length = Pop();
-
-  {
-    NoObservableSideEffectsScope scope(this);
-    BuildArrayBufferViewInitialization<JSDataView>(
-        obj, buffer, byte_offset, byte_length);
-  }
-}
-
-
 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
     ExternalArrayType array_type,
     bool is_zero_byte_offset,
@@ -10227,7 +10295,7 @@
 
     HValue* backing_store = AddUncasted<HAdd>(
         Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
-        elements, Strength::WEAK, AddOfExternalAndTagged);
+        elements, AddOfExternalAndTagged);
 
     HValue* key = builder.BeginBody(
         Add<HConstant>(static_cast<int32_t>(0)),
@@ -10612,8 +10680,7 @@
   HConstant* delta = (expr->op() == Token::INC)
       ? graph()->GetConstant1()
       : graph()->GetConstantMinus1();
-  HInstruction* instr =
-      AddUncasted<HAdd>(Top(), delta, strength(function_language_mode()));
+  HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
   if (instr->IsAdd()) {
     HAdd* add = HAdd::cast(instr);
     add->set_observed_input_representation(1, rep);
@@ -10855,7 +10922,7 @@
     Maybe<HConstant*> number =
         constant->CopyToTruncatedNumber(isolate(), zone());
     if (number.IsJust()) {
-      *expected = Type::Number(zone());
+      *expected = Type::Number();
       return AddInstruction(number.FromJust());
     }
   }
@@ -10869,20 +10936,20 @@
 
   // Separate the number type from the rest.
   Type* expected_obj =
-      Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
+      Type::Intersect(expected_type, Type::NonNumber(), zone());
   Type* expected_number =
-      Type::Intersect(expected_type, Type::Number(zone()), zone());
+      Type::Intersect(expected_type, Type::Number(), zone());
 
   // We expect to get a number.
   // (We need to check first, since Type::None->Is(Type::Any()) == true.
   if (expected_obj->Is(Type::None())) {
-    DCHECK(!expected_number->Is(Type::None(zone())));
+    DCHECK(!expected_number->Is(Type::None()));
     return value;
   }
 
-  if (expected_obj->Is(Type::Undefined(zone()))) {
+  if (expected_obj->Is(Type::Undefined())) {
     // This is already done by HChange.
-    *expected = Type::Union(expected_number, Type::Number(zone()), zone());
+    *expected = Type::Union(expected_number, Type::Number(), zone());
     return value;
   }
 
@@ -10907,8 +10974,7 @@
   }
   HValue* result = HGraphBuilder::BuildBinaryOperation(
       expr->op(), left, right, left_type, right_type, result_type,
-      fixed_right_arg, allocation_mode, strength(function_language_mode()),
-      expr->id());
+      fixed_right_arg, allocation_mode, expr->id());
   // Add a simulate after instructions with observable side effects, and
   // after phis, which are the result of BuildBinaryOperation when we
   // inlined some complex subgraph.
@@ -10924,11 +10990,12 @@
   return result;
 }
 
-
-HValue* HGraphBuilder::BuildBinaryOperation(
-    Token::Value op, HValue* left, HValue* right, Type* left_type,
-    Type* right_type, Type* result_type, Maybe<int> fixed_right_arg,
-    HAllocationMode allocation_mode, Strength strength, BailoutId opt_id) {
+HValue* HGraphBuilder::BuildBinaryOperation(Token::Value op, HValue* left,
+                                            HValue* right, Type* left_type,
+                                            Type* right_type, Type* result_type,
+                                            Maybe<int> fixed_right_arg,
+                                            HAllocationMode allocation_mode,
+                                            BailoutId opt_id) {
   bool maybe_string_add = false;
   if (op == Token::ADD) {
     // If we are adding constant string with something for which we don't have
@@ -10957,7 +11024,7 @@
     Add<HDeoptimize>(
         Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
         Deoptimizer::SOFT);
-    left_type = Type::Any(zone());
+    left_type = Type::Any();
     left_rep = RepresentationFor(left_type);
     maybe_string_add = op == Token::ADD;
   }
@@ -10966,12 +11033,12 @@
     Add<HDeoptimize>(
         Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
         Deoptimizer::SOFT);
-    right_type = Type::Any(zone());
+    right_type = Type::Any();
     right_rep = RepresentationFor(right_type);
     maybe_string_add = op == Token::ADD;
   }
 
-  if (!maybe_string_add && !is_strong(strength)) {
+  if (!maybe_string_add) {
     left = TruncateToNumber(left, &left_type);
     right = TruncateToNumber(right, &right_type);
   }
@@ -10979,43 +11046,36 @@
   // Special case for string addition here.
   if (op == Token::ADD &&
       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
-    if (is_strong(strength)) {
-      // In strong mode, if the one side of an addition is a string,
-      // the other side must be a string too.
+    // Validate type feedback for left argument.
+    if (left_type->Is(Type::String())) {
       left = BuildCheckString(left);
+    }
+
+    // Validate type feedback for right argument.
+    if (right_type->Is(Type::String())) {
       right = BuildCheckString(right);
-    } else {
-      // Validate type feedback for left argument.
-      if (left_type->Is(Type::String())) {
-        left = BuildCheckString(left);
-      }
+    }
 
-      // Validate type feedback for right argument.
-      if (right_type->Is(Type::String())) {
-        right = BuildCheckString(right);
-      }
+    // Convert left argument as necessary.
+    if (left_type->Is(Type::Number())) {
+      DCHECK(right_type->Is(Type::String()));
+      left = BuildNumberToString(left, left_type);
+    } else if (!left_type->Is(Type::String())) {
+      DCHECK(right_type->Is(Type::String()));
+      return AddUncasted<HStringAdd>(
+          left, right, allocation_mode.GetPretenureMode(),
+          STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
+    }
 
-      // Convert left argument as necessary.
-      if (left_type->Is(Type::Number())) {
-        DCHECK(right_type->Is(Type::String()));
-        left = BuildNumberToString(left, left_type);
-      } else if (!left_type->Is(Type::String())) {
-        DCHECK(right_type->Is(Type::String()));
-        return AddUncasted<HStringAdd>(
-            left, right, allocation_mode.GetPretenureMode(),
-            STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
-      }
-
-      // Convert right argument as necessary.
-      if (right_type->Is(Type::Number())) {
-        DCHECK(left_type->Is(Type::String()));
-        right = BuildNumberToString(right, right_type);
-      } else if (!right_type->Is(Type::String())) {
-        DCHECK(left_type->Is(Type::String()));
-        return AddUncasted<HStringAdd>(
-            left, right, allocation_mode.GetPretenureMode(),
-            STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
-      }
+    // Convert right argument as necessary.
+    if (right_type->Is(Type::Number())) {
+      DCHECK(left_type->Is(Type::String()));
+      right = BuildNumberToString(right, right_type);
+    } else if (!right_type->Is(Type::String())) {
+      DCHECK(left_type->Is(Type::String()));
+      return AddUncasted<HStringAdd>(
+          left, right, allocation_mode.GetPretenureMode(),
+          STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
     }
 
     // Fast paths for empty constant strings.
@@ -11064,6 +11124,16 @@
         allocation_mode.feedback_site());
   }
 
+  // Special case for +x here.
+  if (op == Token::MUL) {
+    if (left->EqualsInteger32Constant(1)) {
+      return BuildToNumber(right);
+    }
+    if (right->EqualsInteger32Constant(1)) {
+      return BuildToNumber(left);
+    }
+  }
+
   if (graph()->info()->IsStub()) {
     left = EnforceNumberType(left, left_type);
     right = EnforceNumberType(right, right_type);
@@ -11084,78 +11154,51 @@
       default:
         UNREACHABLE();
       case Token::ADD:
-        function_id =
-            is_strong(strength) ? Runtime::kAdd_Strong : Runtime::kAdd;
+        function_id = Runtime::kAdd;
         break;
       case Token::SUB:
-        function_id = is_strong(strength) ? Runtime::kSubtract_Strong
-                                          : Runtime::kSubtract;
+        function_id = Runtime::kSubtract;
         break;
       case Token::MUL:
-        function_id = is_strong(strength) ? Runtime::kMultiply_Strong
-                                          : Runtime::kMultiply;
+        function_id = Runtime::kMultiply;
         break;
       case Token::DIV:
-        function_id =
-            is_strong(strength) ? Runtime::kDivide_Strong : Runtime::kDivide;
+        function_id = Runtime::kDivide;
         break;
       case Token::MOD:
-        function_id =
-            is_strong(strength) ? Runtime::kModulus_Strong : Runtime::kModulus;
+        function_id = Runtime::kModulus;
         break;
       case Token::BIT_OR:
-        function_id = is_strong(strength) ? Runtime::kBitwiseOr_Strong
-                                          : Runtime::kBitwiseOr;
+        function_id = Runtime::kBitwiseOr;
         break;
       case Token::BIT_AND:
-        function_id = is_strong(strength) ? Runtime::kBitwiseAnd_Strong
-                                          : Runtime::kBitwiseAnd;
+        function_id = Runtime::kBitwiseAnd;
         break;
       case Token::BIT_XOR:
-        function_id = is_strong(strength) ? Runtime::kBitwiseXor_Strong
-                                          : Runtime::kBitwiseXor;
+        function_id = Runtime::kBitwiseXor;
         break;
       case Token::SAR:
-        function_id = is_strong(strength) ? Runtime::kShiftRight_Strong
-                                          : Runtime::kShiftRight;
+        function_id = Runtime::kShiftRight;
         break;
       case Token::SHR:
-        function_id = is_strong(strength) ? Runtime::kShiftRightLogical_Strong
-                                          : Runtime::kShiftRightLogical;
+        function_id = Runtime::kShiftRightLogical;
         break;
       case Token::SHL:
-        function_id = is_strong(strength) ? Runtime::kShiftLeft_Strong
-                                          : Runtime::kShiftLeft;
+        function_id = Runtime::kShiftLeft;
         break;
     }
     Add<HPushArguments>(left, right);
     instr = AddUncasted<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
   } else {
-    if (is_strong(strength) && Token::IsBitOp(op)) {
-      // TODO(conradw): This is not efficient, but is necessary to prevent
-      // conversion of oddball values to numbers in strong mode. It would be
-      // better to prevent the conversion rather than adding a runtime check.
-      IfBuilder if_builder(this);
-      if_builder.If<HHasInstanceTypeAndBranch>(left, ODDBALL_TYPE);
-      if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE);
-      if_builder.Then();
-      Add<HCallRuntime>(
-          Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
-          0);
-      if (!graph()->info()->IsStub()) {
-        Add<HSimulate>(opt_id, REMOVABLE_SIMULATE);
-      }
-      if_builder.End();
-    }
     switch (op) {
       case Token::ADD:
-        instr = AddUncasted<HAdd>(left, right, strength);
+        instr = AddUncasted<HAdd>(left, right);
         break;
       case Token::SUB:
-        instr = AddUncasted<HSub>(left, right, strength);
+        instr = AddUncasted<HSub>(left, right);
         break;
       case Token::MUL:
-        instr = AddUncasted<HMul>(left, right, strength);
+        instr = AddUncasted<HMul>(left, right);
         break;
       case Token::MOD: {
         if (fixed_right_arg.IsJust() &&
@@ -11168,38 +11211,38 @@
           if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation);
           right = fixed_right;
         }
-        instr = AddUncasted<HMod>(left, right, strength);
+        instr = AddUncasted<HMod>(left, right);
         break;
       }
       case Token::DIV:
-        instr = AddUncasted<HDiv>(left, right, strength);
+        instr = AddUncasted<HDiv>(left, right);
         break;
       case Token::BIT_XOR:
       case Token::BIT_AND:
-        instr = AddUncasted<HBitwise>(op, left, right, strength);
+        instr = AddUncasted<HBitwise>(op, left, right);
         break;
       case Token::BIT_OR: {
         HValue *operand, *shift_amount;
         if (left_type->Is(Type::Signed32()) &&
             right_type->Is(Type::Signed32()) &&
             MatchRotateRight(left, right, &operand, &shift_amount)) {
-          instr = AddUncasted<HRor>(operand, shift_amount, strength);
+          instr = AddUncasted<HRor>(operand, shift_amount);
         } else {
-          instr = AddUncasted<HBitwise>(op, left, right, strength);
+          instr = AddUncasted<HBitwise>(op, left, right);
         }
         break;
       }
       case Token::SAR:
-        instr = AddUncasted<HSar>(left, right, strength);
+        instr = AddUncasted<HSar>(left, right);
         break;
       case Token::SHR:
-        instr = AddUncasted<HShr>(left, right, strength);
+        instr = AddUncasted<HShr>(left, right);
         if (instr->IsShr() && CanBeZero(right)) {
           graph()->RecordUint32Instruction(instr);
         }
         break;
       case Token::SHL:
-        instr = AddUncasted<HShl>(left, right, strength);
+        instr = AddUncasted<HShl>(left, right);
         break;
       default:
         UNREACHABLE();
@@ -11520,7 +11563,7 @@
     Add<HDeoptimize>(
         Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
         Deoptimizer::SOFT);
-    combined_type = left_type = right_type = Type::Any(zone());
+    combined_type = left_type = right_type = Type::Any();
   }
 
   Representation left_rep = RepresentationFor(left_type);
@@ -11657,8 +11700,7 @@
     return result;
   } else {
     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
-      HCompareGeneric* result = Add<HCompareGeneric>(
-          left, right, op, strength(function_language_mode()));
+      HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
       result->set_observed_input_representation(1, left_rep);
       result->set_observed_input_representation(2, right_rep);
       if (result->HasObservableSideEffects()) {
@@ -11674,8 +11716,8 @@
       HBranch* branch = New<HBranch>(result);
       return branch;
     } else {
-      HCompareNumericAndBranch* result = New<HCompareNumericAndBranch>(
-          left, right, op, strength(function_language_mode()));
+      HCompareNumericAndBranch* result =
+          New<HCompareNumericAndBranch>(left, right, op);
       result->set_observed_input_representation(left_rep, right_rep);
       if (top_info()->is_tracking_positions()) {
         result->SetOperandPositions(zone(), left_position, right_position);
@@ -11706,7 +11748,8 @@
   } else {
     DCHECK_EQ(Token::EQ, expr->op());
     Type* type = expr->combined_type()->Is(Type::None())
-        ? Type::Any(zone()) : expr->combined_type();
+                     ? Type::Any()
+                     : expr->combined_type();
     HIfContinuation continuation;
     BuildCompareNil(value, type, &continuation);
     return ast_context()->ReturnContinuation(&continuation, expr->id());
@@ -12149,8 +12192,8 @@
 }
 
 
-void HOptimizedGraphBuilder::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* node) {
+void HOptimizedGraphBuilder::VisitRewritableExpression(
+    RewritableExpression* node) {
   CHECK_ALIVE(Visit(node->expression()));
 }
 
@@ -12178,25 +12221,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 1);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  HValue* value = Pop();
-  HHasInstanceTypeAndBranch* result = New<HHasInstanceTypeAndBranch>(
-      value, FIRST_FUNCTION_TYPE, LAST_FUNCTION_TYPE);
-  return ast_context()->ReturnControl(result, call->id());
-}
-
-
-void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 1);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  HValue* value = Pop();
-  HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
-  return ast_context()->ReturnControl(result, call->id());
-}
-
-
 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
   DCHECK(call->arguments()->length() == 1);
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12264,6 +12288,30 @@
 }
 
 
+void HOptimizedGraphBuilder::GenerateToName(CallRuntime* call) {
+  DCHECK_EQ(1, call->arguments()->length());
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  HValue* input = Pop();
+  if (input->type().IsSmi()) {
+    HValue* result = BuildNumberToString(input, Type::SignedSmall());
+    return ast_context()->ReturnValue(result);
+  } else if (input->type().IsTaggedNumber()) {
+    HValue* result = BuildNumberToString(input, Type::Number());
+    return ast_context()->ReturnValue(result);
+  } else if (input->type().IsString()) {
+    return ast_context()->ReturnValue(input);
+  } else {
+    Callable callable = CodeFactory::ToName(isolate());
+    HValue* stub = Add<HConstant>(callable.code());
+    HValue* values[] = {context(), input};
+    HInstruction* result =
+        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
+                                 Vector<HValue*>(values, arraysize(values)));
+    return ast_context()->ReturnInstruction(result, call->id());
+  }
+}
+
+
 void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
   DCHECK_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12276,11 +12324,11 @@
 void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
   DCHECK_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  Callable callable = CodeFactory::ToString(isolate());
   HValue* input = Pop();
   if (input->type().IsString()) {
     return ast_context()->ReturnValue(input);
   } else {
+    Callable callable = CodeFactory::ToString(isolate());
     HValue* stub = Add<HConstant>(callable.code());
     HValue* values[] = {context(), input};
     HInstruction* result =
@@ -12310,16 +12358,13 @@
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   Callable callable = CodeFactory::ToNumber(isolate());
   HValue* input = Pop();
-  if (input->type().IsTaggedNumber()) {
-    return ast_context()->ReturnValue(input);
-  } else {
-    HValue* stub = Add<HConstant>(callable.code());
-    HValue* values[] = {context(), input};
-    HInstruction* result =
-        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
-                                 Vector<HValue*>(values, arraysize(values)));
-    return ast_context()->ReturnInstruction(result, call->id());
+  HValue* result = BuildToNumber(input);
+  if (result->HasObservableSideEffects()) {
+    if (!ast_context()->IsEffect()) Push(result);
+    Add<HSimulate>(call->id(), REMOVABLE_SIMULATE);
+    if (!ast_context()->IsEffect()) result = Pop();
   }
+  return ast_context()->ReturnValue(result);
 }
 
 
@@ -12372,48 +12417,6 @@
 }
 
 
-// Support for arguments.length and arguments[?].
-void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 0);
-  HInstruction* result = NULL;
-  if (function_state()->outer() == NULL) {
-    HInstruction* elements = Add<HArgumentsElements>(false);
-    result = New<HArgumentsLength>(elements);
-  } else {
-    // Number of arguments without receiver.
-    int argument_count = environment()->
-        arguments_environment()->parameter_count() - 1;
-    result = New<HConstant>(argument_count);
-  }
-  return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
-void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 1);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  HValue* index = Pop();
-  HInstruction* result = NULL;
-  if (function_state()->outer() == NULL) {
-    HInstruction* elements = Add<HArgumentsElements>(false);
-    HInstruction* length = Add<HArgumentsLength>(elements);
-    HInstruction* checked_index = Add<HBoundsCheck>(index, length);
-    result = New<HAccessArgumentsAt>(elements, length, checked_index);
-  } else {
-    EnsureArgumentsArePushedForAccess();
-
-    // Number of arguments without receiver.
-    HInstruction* elements = function_state()->arguments_elements();
-    int argument_count = environment()->
-        arguments_environment()->parameter_count() - 1;
-    HInstruction* length = Add<HConstant>(argument_count);
-    HInstruction* checked_key = Add<HBoundsCheck>(index, length);
-    result = New<HAccessArgumentsAt>(elements, length, checked_key);
-  }
-  return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
   DCHECK(call->arguments()->length() == 1);
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12442,27 +12445,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateJSValueGetValue(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 1);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  HValue* value = Pop();
-  HInstruction* result = Add<HLoadNamedField>(
-      value, nullptr,
-      HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset));
-  return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
-void HOptimizedGraphBuilder::GenerateIsDate(CallRuntime* call) {
-  DCHECK_EQ(1, call->arguments()->length());
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  HValue* value = Pop();
-  HHasInstanceTypeAndBranch* result =
-      New<HHasInstanceTypeAndBranch>(value, JS_DATE_TYPE);
-  return ast_context()->ReturnControl(result, call->id());
-}
-
-
 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
     CallRuntime* call) {
   DCHECK(call->arguments()->length() == 3);
@@ -12495,43 +12477,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 2);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
-  HValue* value = Pop();
-  HValue* object = Pop();
-
-  // Check if object is a JSValue.
-  IfBuilder if_objectisvalue(this);
-  if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
-  if_objectisvalue.Then();
-  {
-    // Create in-object property store to kValueOffset.
-    Add<HStoreNamedField>(object,
-        HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
-        value);
-    if (!ast_context()->IsEffect()) {
-      Push(value);
-    }
-    Add<HSimulate>(call->id(), FIXED_SIMULATE);
-  }
-  if_objectisvalue.Else();
-  {
-    // Nothing to do in this case.
-    if (!ast_context()->IsEffect()) {
-      Push(value);
-    }
-    Add<HSimulate>(call->id(), FIXED_SIMULATE);
-  }
-  if_objectisvalue.End();
-  if (!ast_context()->IsEffect()) {
-    Drop(1);
-  }
-  return ast_context()->ReturnValue(value);
-}
-
-
 // Fast support for charCodeAt(n).
 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   DCHECK(call->arguments()->length() == 2);
@@ -12568,25 +12513,18 @@
 }
 
 
-// Fast support for object equality testing.
-void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 2);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
-  HValue* right = Pop();
-  HValue* left = Pop();
-  HCompareObjectEqAndBranch* result =
-      New<HCompareObjectEqAndBranch>(left, right);
-  return ast_context()->ReturnControl(result, call->id());
-}
-
-
 // Fast support for SubString.
 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   DCHECK_EQ(3, call->arguments()->length());
   CHECK_ALIVE(VisitExpressions(call->arguments()));
   PushArgumentsFromEnvironment(call->arguments()->length());
-  HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
+  Callable callable = CodeFactory::SubString(isolate());
+  HValue* stub = Add<HConstant>(callable.code());
+  HValue* values[] = {context()};
+  HInstruction* result = New<HCallWithDescriptor>(
+      stub, call->arguments()->length(), callable.descriptor(),
+      Vector<HValue*>(values, arraysize(values)));
+  result->set_type(HType::String());
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -12596,7 +12534,12 @@
   DCHECK_EQ(4, call->arguments()->length());
   CHECK_ALIVE(VisitExpressions(call->arguments()));
   PushArgumentsFromEnvironment(call->arguments()->length());
-  HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
+  Callable callable = CodeFactory::RegExpExec(isolate());
+  HValue* stub = Add<HConstant>(callable.code());
+  HValue* values[] = {context()};
+  HInstruction* result = New<HCallWithDescriptor>(
+      stub, call->arguments()->length(), callable.descriptor(),
+      Vector<HValue*>(values, arraysize(values)));
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -12669,7 +12612,7 @@
   DCHECK_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   HValue* number = Pop();
-  HValue* result = BuildNumberToString(number, Type::Any(zone()));
+  HValue* result = BuildNumberToString(number, Type::Any());
   return ast_context()->ReturnValue(result);
 }
 
@@ -12929,16 +12872,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
-  // Simply returning undefined here would be semantically correct and even
-  // avoid the bailout. Nevertheless, some ancient benchmarks like SunSpider's
-  // string-fasta would tank, because fullcode contains an optimized version.
-  // Obviously the fullcode => Crankshaft => bailout => fullcode dance is
-  // faster... *sigh*
-  return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
-}
-
-
 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
     CallRuntime* call) {
   Add<HDebugBreak>();