Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index a42da50..8a05777 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -62,10 +62,11 @@
       size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale);  \
       dispatch_table_[index] = code->entry();                                  \
       TraceCodegen(code);                                                      \
-      LOG_CODE_EVENT(                                                          \
+      PROFILE(                                                                 \
           isolate_,                                                            \
           CodeCreateEvent(                                                     \
-              Logger::BYTECODE_HANDLER_TAG, AbstractCode::cast(*code),         \
+              CodeEventListener::BYTECODE_HANDLER_TAG,                         \
+              AbstractCode::cast(*code),                                       \
               Bytecodes::ToString(Bytecode::k##Name, operand_scale).c_str())); \
     }                                                                          \
   }
@@ -180,9 +181,8 @@
 bool Interpreter::IsDispatchTableInitialized() {
   if (FLAG_trace_ignition || FLAG_trace_ignition_codegen ||
       FLAG_trace_ignition_dispatches) {
-    // Regenerate table to add bytecode tracing operations,
-    // print the assembly code generated by TurboFan,
-    // or instrument handlers with dispatch counters.
+    // Regenerate table to add bytecode tracing operations, print the assembly
+    // code generated by TurboFan or instrument handlers with dispatch counters.
     return false;
   }
   return dispatch_table_[0] != nullptr;
@@ -250,7 +250,8 @@
                                     NewStringType::kNormal)
                 .ToLocalChecked();
         Local<v8::Number> counter_object = v8::Number::New(isolate, counter);
-        CHECK(counters_row->Set(context, to_name_object, counter_object)
+        CHECK(counters_row
+                  ->DefineOwnProperty(context, to_name_object, counter_object)
                   .IsJust());
       }
     }
@@ -261,7 +262,9 @@
                                 NewStringType::kNormal)
             .ToLocalChecked();
 
-    CHECK(counters_map->Set(context, from_name_object, counters_row).IsJust());
+    CHECK(
+        counters_map->DefineOwnProperty(context, from_name_object, counters_row)
+            .IsJust());
   }
 
   return counters_map;
@@ -286,19 +289,14 @@
   __ Dispatch();
 }
 
-void Interpreter::DoLoadConstant(InterpreterAssembler* assembler) {
-  Node* index = __ BytecodeOperandIdx(0);
-  Node* constant = __ LoadConstantPoolEntry(index);
-  __ SetAccumulator(constant);
-  __ Dispatch();
-}
-
-
 // LdaConstant <idx>
 //
 // Load constant literal at |idx| in the constant pool into the accumulator.
 void Interpreter::DoLdaConstant(InterpreterAssembler* assembler) {
-  DoLoadConstant(assembler);
+  Node* index = __ BytecodeOperandIdx(0);
+  Node* constant = __ LoadConstantPoolEntry(index);
+  __ SetAccumulator(constant);
+  __ Dispatch();
 }
 
 // LdaUndefined
@@ -311,6 +309,16 @@
   __ Dispatch();
 }
 
+// LdrUndefined <reg>
+//
+// Loads undefined into the accumulator and |reg|.
+void Interpreter::DoLdrUndefined(InterpreterAssembler* assembler) {
+  Node* undefined_value =
+      __ HeapConstant(isolate_->factory()->undefined_value());
+  Node* destination = __ BytecodeOperandReg(0);
+  __ StoreRegister(undefined_value, destination);
+  __ Dispatch();
+}
 
 // LdaNull
 //
@@ -321,7 +329,6 @@
   __ Dispatch();
 }
 
-
 // LdaTheHole
 //
 // Load TheHole into the accumulator.
@@ -331,7 +338,6 @@
   __ Dispatch();
 }
 
-
 // LdaTrue
 //
 // Load True into the accumulator.
@@ -341,7 +347,6 @@
   __ Dispatch();
 }
 
-
 // LdaFalse
 //
 // Load False into the accumulator.
@@ -351,7 +356,6 @@
   __ Dispatch();
 }
 
-
 // Ldar <src>
 //
 // Load accumulator with value from register <src>.
@@ -362,7 +366,6 @@
   __ Dispatch();
 }
 
-
 // Star <dst>
 //
 // Store accumulator to register <dst>.
@@ -373,7 +376,6 @@
   __ Dispatch();
 }
 
-
 // Mov <src> <dst>
 //
 // Stores the value of register <src> to register <dst>.
@@ -385,48 +387,58 @@
   __ Dispatch();
 }
 
-
-void Interpreter::DoLoadGlobal(Callable ic, InterpreterAssembler* assembler) {
+Node* Interpreter::BuildLoadGlobal(Callable ic,
+                                   InterpreterAssembler* assembler) {
   // Get the global object.
   Node* context = __ GetContext();
-  Node* native_context =
-      __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
-  Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX);
 
-  // Load the global via the LoadIC.
+  // Load the global via the LoadGlobalIC.
   Node* code_target = __ HeapConstant(ic.code());
-  Node* constant_index = __ BytecodeOperandIdx(0);
-  Node* name = __ LoadConstantPoolEntry(constant_index);
-  Node* raw_slot = __ BytecodeOperandIdx(1);
+  Node* raw_slot = __ BytecodeOperandIdx(0);
   Node* smi_slot = __ SmiTag(raw_slot);
   Node* type_feedback_vector = __ LoadTypeFeedbackVector();
-  Node* result = __ CallStub(ic.descriptor(), code_target, context, global,
-                             name, smi_slot, type_feedback_vector);
-  __ SetAccumulator(result);
-  __ Dispatch();
+  return __ CallStub(ic.descriptor(), code_target, context, smi_slot,
+                     type_feedback_vector);
 }
 
-// LdaGlobal <name_index> <slot>
+// LdaGlobal <slot>
 //
 // Load the global with name in constant pool entry <name_index> into the
 // accumulator using FeedBackVector slot <slot> outside of a typeof.
 void Interpreter::DoLdaGlobal(InterpreterAssembler* assembler) {
-  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
-                                                   UNINITIALIZED);
-  DoLoadGlobal(ic, assembler);
+  Callable ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF);
+  Node* result = BuildLoadGlobal(ic, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
 }
 
-// LdaGlobalInsideTypeof <name_index> <slot>
+// LdrGlobal <slot> <reg>
+//
+// Load the global with name in constant pool entry <name_index> into
+// register <reg> using FeedBackVector slot <slot> outside of a typeof.
+void Interpreter::DoLdrGlobal(InterpreterAssembler* assembler) {
+  Callable ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF);
+  Node* result = BuildLoadGlobal(ic, assembler);
+  Node* destination = __ BytecodeOperandReg(1);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
+}
+
+// LdaGlobalInsideTypeof <slot>
 //
 // Load the global with name in constant pool entry <name_index> into the
 // accumulator using FeedBackVector slot <slot> inside of a typeof.
 void Interpreter::DoLdaGlobalInsideTypeof(InterpreterAssembler* assembler) {
-  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF,
-                                                   UNINITIALIZED);
-  DoLoadGlobal(ic, assembler);
+  Callable ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate_, INSIDE_TYPEOF);
+  Node* result = BuildLoadGlobal(ic, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
 }
 
-void Interpreter::DoStoreGlobal(Callable ic, InterpreterAssembler* assembler) {
+void Interpreter::DoStaGlobal(Callable ic, InterpreterAssembler* assembler) {
   // Get the global object.
   Node* context = __ GetContext();
   Node* native_context =
@@ -446,40 +458,51 @@
   __ Dispatch();
 }
 
-
 // StaGlobalSloppy <name_index> <slot>
 //
 // Store the value in the accumulator into the global with name in constant pool
 // entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
 void Interpreter::DoStaGlobalSloppy(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
-  DoStoreGlobal(ic, assembler);
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY);
+  DoStaGlobal(ic, assembler);
 }
 
-
 // StaGlobalStrict <name_index> <slot>
 //
 // Store the value in the accumulator into the global with name in constant pool
 // entry <name_index> using FeedBackVector slot <slot> in strict mode.
 void Interpreter::DoStaGlobalStrict(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
-  DoStoreGlobal(ic, assembler);
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT);
+  DoStaGlobal(ic, assembler);
+}
+
+compiler::Node* Interpreter::BuildLoadContextSlot(
+    InterpreterAssembler* assembler) {
+  Node* reg_index = __ BytecodeOperandReg(0);
+  Node* context = __ LoadRegister(reg_index);
+  Node* slot_index = __ BytecodeOperandIdx(1);
+  return __ LoadContextSlot(context, slot_index);
 }
 
 // LdaContextSlot <context> <slot_index>
 //
 // Load the object in |slot_index| of |context| into the accumulator.
 void Interpreter::DoLdaContextSlot(InterpreterAssembler* assembler) {
-  Node* reg_index = __ BytecodeOperandReg(0);
-  Node* context = __ LoadRegister(reg_index);
-  Node* slot_index = __ BytecodeOperandIdx(1);
-  Node* result = __ LoadContextSlot(context, slot_index);
+  Node* result = BuildLoadContextSlot(assembler);
   __ SetAccumulator(result);
   __ Dispatch();
 }
 
+// LdrContextSlot <context> <slot_index> <reg>
+//
+// Load the object in <slot_index> of <context> into register <reg>.
+void Interpreter::DoLdrContextSlot(InterpreterAssembler* assembler) {
+  Node* result = BuildLoadContextSlot(assembler);
+  Node* destination = __ BytecodeOperandReg(2);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
+}
+
 // StaContextSlot <context> <slot_index>
 //
 // Stores the object in the accumulator into |slot_index| of |context|.
@@ -492,8 +515,8 @@
   __ Dispatch();
 }
 
-void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id,
-                                   InterpreterAssembler* assembler) {
+void Interpreter::DoLdaLookupSlot(Runtime::FunctionId function_id,
+                                  InterpreterAssembler* assembler) {
   Node* index = __ BytecodeOperandIdx(0);
   Node* name = __ LoadConstantPoolEntry(index);
   Node* context = __ GetContext();
@@ -507,7 +530,7 @@
 // Lookup the object with the name in constant pool entry |name_index|
 // dynamically.
 void Interpreter::DoLdaLookupSlot(InterpreterAssembler* assembler) {
-  DoLoadLookupSlot(Runtime::kLoadLookupSlot, assembler);
+  DoLdaLookupSlot(Runtime::kLoadLookupSlot, assembler);
 }
 
 // LdaLookupSlotInsideTypeof <name_index>
@@ -515,11 +538,11 @@
 // Lookup the object with the name in constant pool entry |name_index|
 // dynamically without causing a NoReferenceError.
 void Interpreter::DoLdaLookupSlotInsideTypeof(InterpreterAssembler* assembler) {
-  DoLoadLookupSlot(Runtime::kLoadLookupSlotInsideTypeof, assembler);
+  DoLdaLookupSlot(Runtime::kLoadLookupSlotInsideTypeof, assembler);
 }
 
-void Interpreter::DoStoreLookupSlot(LanguageMode language_mode,
-                                    InterpreterAssembler* assembler) {
+void Interpreter::DoStaLookupSlot(LanguageMode language_mode,
+                                  InterpreterAssembler* assembler) {
   Node* value = __ GetAccumulator();
   Node* index = __ BytecodeOperandIdx(0);
   Node* name = __ LoadConstantPoolEntry(index);
@@ -537,19 +560,19 @@
 // Store the object in accumulator to the object with the name in constant
 // pool entry |name_index| in sloppy mode.
 void Interpreter::DoStaLookupSlotSloppy(InterpreterAssembler* assembler) {
-  DoStoreLookupSlot(LanguageMode::SLOPPY, assembler);
+  DoStaLookupSlot(LanguageMode::SLOPPY, assembler);
 }
 
-
 // StaLookupSlotStrict <name_index>
 //
 // Store the object in accumulator to the object with the name in constant
 // pool entry |name_index| in strict mode.
 void Interpreter::DoStaLookupSlotStrict(InterpreterAssembler* assembler) {
-  DoStoreLookupSlot(LanguageMode::STRICT, assembler);
+  DoStaLookupSlot(LanguageMode::STRICT, assembler);
 }
 
-void Interpreter::DoLoadIC(Callable ic, InterpreterAssembler* assembler) {
+Node* Interpreter::BuildLoadNamedProperty(Callable ic,
+                                          InterpreterAssembler* assembler) {
   Node* code_target = __ HeapConstant(ic.code());
   Node* register_index = __ BytecodeOperandReg(0);
   Node* object = __ LoadRegister(register_index);
@@ -559,23 +582,35 @@
   Node* smi_slot = __ SmiTag(raw_slot);
   Node* type_feedback_vector = __ LoadTypeFeedbackVector();
   Node* context = __ GetContext();
-  Node* result = __ CallStub(ic.descriptor(), code_target, context, object,
-                             name, smi_slot, type_feedback_vector);
+  return __ CallStub(ic.descriptor(), code_target, context, object, name,
+                     smi_slot, type_feedback_vector);
+}
+
+// LdaNamedProperty <object> <name_index> <slot>
+//
+// Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
+// constant pool entry <name_index>.
+void Interpreter::DoLdaNamedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadNamedProperty(ic, assembler);
   __ SetAccumulator(result);
   __ Dispatch();
 }
 
-// LoadIC <object> <name_index> <slot>
+// LdrNamedProperty <object> <name_index> <slot> <reg>
 //
 // Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
-// constant pool entry <name_index>.
-void Interpreter::DoLoadIC(InterpreterAssembler* assembler) {
-  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
-                                                   UNINITIALIZED);
-  DoLoadIC(ic, assembler);
+// constant pool entry <name_index> and puts the result into register <reg>.
+void Interpreter::DoLdrNamedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadNamedProperty(ic, assembler);
+  Node* destination = __ BytecodeOperandReg(3);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
 }
 
-void Interpreter::DoKeyedLoadIC(Callable ic, InterpreterAssembler* assembler) {
+Node* Interpreter::BuildLoadKeyedProperty(Callable ic,
+                                          InterpreterAssembler* assembler) {
   Node* code_target = __ HeapConstant(ic.code());
   Node* reg_index = __ BytecodeOperandReg(0);
   Node* object = __ LoadRegister(reg_index);
@@ -584,20 +619,31 @@
   Node* smi_slot = __ SmiTag(raw_slot);
   Node* type_feedback_vector = __ LoadTypeFeedbackVector();
   Node* context = __ GetContext();
-  Node* result = __ CallStub(ic.descriptor(), code_target, context, object,
-                             name, smi_slot, type_feedback_vector);
-  __ SetAccumulator(result);
-  __ Dispatch();
+  return __ CallStub(ic.descriptor(), code_target, context, object, name,
+                     smi_slot, type_feedback_vector);
 }
 
 // KeyedLoadIC <object> <slot>
 //
 // Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
 // in the accumulator.
-void Interpreter::DoKeyedLoadIC(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(isolate_, UNINITIALIZED);
-  DoKeyedLoadIC(ic, assembler);
+void Interpreter::DoLdaKeyedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadKeyedProperty(ic, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
+}
+
+// LdrKeyedProperty <object> <slot> <reg>
+//
+// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
+// in the accumulator and puts the result in register <reg>.
+void Interpreter::DoLdrKeyedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadKeyedProperty(ic, assembler);
+  Node* destination = __ BytecodeOperandReg(2);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
 }
 
 void Interpreter::DoStoreIC(Callable ic, InterpreterAssembler* assembler) {
@@ -616,27 +662,23 @@
   __ Dispatch();
 }
 
-
-// StoreICSloppy <object> <name_index> <slot>
+// StaNamedPropertySloppy <object> <name_index> <slot>
 //
 // Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
 // the name in constant pool entry <name_index> with the value in the
 // accumulator.
-void Interpreter::DoStoreICSloppy(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
+void Interpreter::DoStaNamedPropertySloppy(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY);
   DoStoreIC(ic, assembler);
 }
 
-
-// StoreICStrict <object> <name_index> <slot>
+// StaNamedPropertyStrict <object> <name_index> <slot>
 //
 // Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
 // the name in constant pool entry <name_index> with the value in the
 // accumulator.
-void Interpreter::DoStoreICStrict(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
+void Interpreter::DoStaNamedPropertyStrict(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT);
   DoStoreIC(ic, assembler);
 }
 
@@ -656,25 +698,21 @@
   __ Dispatch();
 }
 
-
-// KeyedStoreICSloppy <object> <key> <slot>
+// StaKeyedPropertySloppy <object> <key> <slot>
 //
 // Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object>
 // and the key <key> with the value in the accumulator.
-void Interpreter::DoKeyedStoreICSloppy(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
+void Interpreter::DoStaKeyedPropertySloppy(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY);
   DoKeyedStoreIC(ic, assembler);
 }
 
-
-// KeyedStoreICStore <object> <key> <slot>
+// StaKeyedPropertyStrict <object> <key> <slot>
 //
 // Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object>
 // and the key <key> with the value in the accumulator.
-void Interpreter::DoKeyedStoreICStrict(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
+void Interpreter::DoStaKeyedPropertyStrict(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT);
   DoKeyedStoreIC(ic, assembler);
 }
 
@@ -691,7 +729,6 @@
   __ Dispatch();
 }
 
-
 // PopContext <context>
 //
 // Pops the current context and sets <context> as the new context.
@@ -702,33 +739,6 @@
   __ Dispatch();
 }
 
-void Interpreter::DoBinaryOp(Callable callable,
-                             InterpreterAssembler* assembler) {
-  // TODO(bmeurer): Collect definition side type feedback for various
-  // binary operations.
-  Node* target = __ HeapConstant(callable.code());
-  Node* reg_index = __ BytecodeOperandReg(0);
-  Node* lhs = __ LoadRegister(reg_index);
-  Node* rhs = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* result = __ CallStub(callable.descriptor(), target, context, lhs, rhs);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
-
-void Interpreter::DoBinaryOp(Runtime::FunctionId function_id,
-                             InterpreterAssembler* assembler) {
-  // TODO(rmcilroy): Call ICs which back-patch bytecode with type specialized
-  // operations, instead of calling builtins directly.
-  Node* reg_index = __ BytecodeOperandReg(0);
-  Node* lhs = __ LoadRegister(reg_index);
-  Node* rhs = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* result = __ CallRuntime(function_id, context, lhs, rhs);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
-
 template <class Generator>
 void Interpreter::DoBinaryOp(InterpreterAssembler* assembler) {
   Node* reg_index = __ BytecodeOperandReg(0);
@@ -747,7 +757,6 @@
   DoBinaryOp<AddStub>(assembler);
 }
 
-
 // Sub <src>
 //
 // Subtract register <src> from accumulator.
@@ -755,7 +764,6 @@
   DoBinaryOp<SubtractStub>(assembler);
 }
 
-
 // Mul <src>
 //
 // Multiply accumulator by register <src>.
@@ -763,7 +771,6 @@
   DoBinaryOp<MultiplyStub>(assembler);
 }
 
-
 // Div <src>
 //
 // Divide register <src> by accumulator.
@@ -771,7 +778,6 @@
   DoBinaryOp<DivideStub>(assembler);
 }
 
-
 // Mod <src>
 //
 // Modulo register <src> by accumulator.
@@ -779,7 +785,6 @@
   DoBinaryOp<ModulusStub>(assembler);
 }
 
-
 // BitwiseOr <src>
 //
 // BitwiseOr register <src> to accumulator.
@@ -787,7 +792,6 @@
   DoBinaryOp<BitwiseOrStub>(assembler);
 }
 
-
 // BitwiseXor <src>
 //
 // BitwiseXor register <src> to accumulator.
@@ -795,7 +799,6 @@
   DoBinaryOp<BitwiseXorStub>(assembler);
 }
 
-
 // BitwiseAnd <src>
 //
 // BitwiseAnd register <src> to accumulator.
@@ -803,7 +806,6 @@
   DoBinaryOp<BitwiseAndStub>(assembler);
 }
 
-
 // ShiftLeft <src>
 //
 // Left shifts register <src> by the count specified in the accumulator.
@@ -814,7 +816,6 @@
   DoBinaryOp<ShiftLeftStub>(assembler);
 }
 
-
 // ShiftRight <src>
 //
 // Right shifts register <src> by the count specified in the accumulator.
@@ -825,7 +826,6 @@
   DoBinaryOp<ShiftRightStub>(assembler);
 }
 
-
 // ShiftRightLogical <src>
 //
 // Right Shifts register <src> by the count specified in the accumulator.
@@ -836,6 +836,17 @@
   DoBinaryOp<ShiftRightLogicalStub>(assembler);
 }
 
+void Interpreter::DoUnaryOp(Callable callable,
+                            InterpreterAssembler* assembler) {
+  Node* target = __ HeapConstant(callable.code());
+  Node* accumulator = __ GetAccumulator();
+  Node* context = __ GetContext();
+  Node* result =
+      __ CallStub(callable.descriptor(), target, context, accumulator);
+  __ SetAccumulator(result);
+  __ Dispatch();
+}
+
 template <class Generator>
 void Interpreter::DoUnaryOp(InterpreterAssembler* assembler) {
   Node* value = __ GetAccumulator();
@@ -845,6 +856,27 @@
   __ Dispatch();
 }
 
+// ToName
+//
+// Cast the object referenced by the accumulator to a name.
+void Interpreter::DoToName(InterpreterAssembler* assembler) {
+  DoUnaryOp(CodeFactory::ToName(isolate_), assembler);
+}
+
+// ToNumber
+//
+// Cast the object referenced by the accumulator to a number.
+void Interpreter::DoToNumber(InterpreterAssembler* assembler) {
+  DoUnaryOp(CodeFactory::ToNumber(isolate_), assembler);
+}
+
+// ToObject
+//
+// Cast the object referenced by the accumulator to a JSObject.
+void Interpreter::DoToObject(InterpreterAssembler* assembler) {
+  DoUnaryOp(CodeFactory::ToObject(isolate_), assembler);
+}
+
 // Inc
 //
 // Increments value in the accumulator by one.
@@ -859,14 +891,22 @@
   DoUnaryOp<DecStub>(assembler);
 }
 
-void Interpreter::DoLogicalNotOp(Node* value, InterpreterAssembler* assembler) {
+Node* Interpreter::BuildToBoolean(Node* value,
+                                  InterpreterAssembler* assembler) {
+  Node* context = __ GetContext();
+  return ToBooleanStub::Generate(assembler, value, context);
+}
+
+Node* Interpreter::BuildLogicalNot(Node* value,
+                                   InterpreterAssembler* assembler) {
+  Variable result(assembler, MachineRepresentation::kTagged);
   Label if_true(assembler), if_false(assembler), end(assembler);
   Node* true_value = __ BooleanConstant(true);
   Node* false_value = __ BooleanConstant(false);
   __ BranchIfWordEqual(value, true_value, &if_true, &if_false);
   __ Bind(&if_true);
   {
-    __ SetAccumulator(false_value);
+    result.Bind(false_value);
     __ Goto(&end);
   }
   __ Bind(&if_false);
@@ -875,24 +915,23 @@
       __ AbortIfWordNotEqual(value, false_value,
                              BailoutReason::kExpectedBooleanValue);
     }
-    __ SetAccumulator(true_value);
+    result.Bind(true_value);
     __ Goto(&end);
   }
   __ Bind(&end);
+  return result.value();
 }
 
-// ToBooleanLogicalNot
+// LogicalNot
 //
 // Perform logical-not on the accumulator, first casting the
 // accumulator to a boolean value if required.
+// ToBooleanLogicalNot
 void Interpreter::DoToBooleanLogicalNot(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
-  Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
-  DoLogicalNotOp(to_boolean_value, assembler);
+  Node* value = __ GetAccumulator();
+  Node* to_boolean_value = BuildToBoolean(value, assembler);
+  Node* result = BuildLogicalNot(to_boolean_value, assembler);
+  __ SetAccumulator(result);
   __ Dispatch();
 }
 
@@ -902,7 +941,8 @@
 // value.
 void Interpreter::DoLogicalNot(InterpreterAssembler* assembler) {
   Node* value = __ GetAccumulator();
-  DoLogicalNotOp(value, assembler);
+  Node* result = BuildLogicalNot(value, assembler);
+  __ SetAccumulator(result);
   __ Dispatch();
 }
 
@@ -911,14 +951,7 @@
 // Load the accumulator with the string representating type of the
 // object in the accumulator.
 void Interpreter::DoTypeOf(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::Typeof(isolate_);
-  Node* target = __ HeapConstant(callable.code());
-  Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* result =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
-  __ SetAccumulator(result);
-  __ Dispatch();
+  DoUnaryOp(CodeFactory::Typeof(isolate_), assembler);
 }
 
 void Interpreter::DoDelete(Runtime::FunctionId function_id,
@@ -932,7 +965,6 @@
   __ Dispatch();
 }
 
-
 // DeletePropertyStrict
 //
 // Delete the property specified in the accumulator from the object
@@ -941,7 +973,6 @@
   DoDelete(Runtime::kDeleteProperty_Strict, assembler);
 }
 
-
 // DeletePropertySloppy
 //
 // Delete the property specified in the accumulator from the object
@@ -967,7 +998,6 @@
   __ Dispatch();
 }
 
-
 // Call <callable> <receiver> <arg_count>
 //
 // Call a JSfunction or Callable in |callable| with the |receiver| and
@@ -995,7 +1025,6 @@
   __ Dispatch();
 }
 
-
 // CallRuntime <function_id> <first_arg> <arg_count>
 //
 // Call the runtime function |function_id| with the first argument in
@@ -1011,7 +1040,7 @@
 // |function_id| with the first argument in |first_arg| and |arg_count|
 // arguments in subsequent registers.
 void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) {
-  Node* function_id = __ BytecodeOperandRuntimeId(0);
+  Node* function_id = __ BytecodeOperandIntrinsicId(0);
   Node* first_arg_reg = __ BytecodeOperandReg(1);
   Node* arg_count = __ BytecodeOperandCount(2);
   Node* context = __ GetContext();
@@ -1042,7 +1071,6 @@
   __ Dispatch();
 }
 
-
 // CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
 //
 // Call the runtime function |function_id| which returns a pair, with the
@@ -1074,7 +1102,6 @@
   __ Dispatch();
 }
 
-
 // CallJSRuntime <context_index> <receiver> <arg_count>
 //
 // Call the JS runtime function that has the |context_index| with the receiver
@@ -1098,7 +1125,6 @@
   __ Dispatch();
 }
 
-
 // New <constructor> <first_arg> <arg_count>
 //
 // Call operator new with |constructor| and the first argument in
@@ -1113,109 +1139,67 @@
 //
 // Test if the value in the <src> register equals the accumulator.
 void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::Equal(isolate_), assembler);
+  DoBinaryOp<EqualStub>(assembler);
 }
 
-
 // TestNotEqual <src>
 //
 // Test if the value in the <src> register is not equal to the accumulator.
 void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::NotEqual(isolate_), assembler);
+  DoBinaryOp<NotEqualStub>(assembler);
 }
 
-
 // TestEqualStrict <src>
 //
 // Test if the value in the <src> register is strictly equal to the accumulator.
 void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::StrictEqual(isolate_), assembler);
+  DoBinaryOp<StrictEqualStub>(assembler);
 }
 
-
 // TestLessThan <src>
 //
 // Test if the value in the <src> register is less than the accumulator.
 void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::LessThan(isolate_), assembler);
+  DoBinaryOp<LessThanStub>(assembler);
 }
 
-
 // TestGreaterThan <src>
 //
 // Test if the value in the <src> register is greater than the accumulator.
 void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::GreaterThan(isolate_), assembler);
+  DoBinaryOp<GreaterThanStub>(assembler);
 }
 
-
 // TestLessThanOrEqual <src>
 //
 // Test if the value in the <src> register is less than or equal to the
 // accumulator.
 void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::LessThanOrEqual(isolate_), assembler);
+  DoBinaryOp<LessThanOrEqualStub>(assembler);
 }
 
-
 // TestGreaterThanOrEqual <src>
 //
 // Test if the value in the <src> register is greater than or equal to the
 // accumulator.
 void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::GreaterThanOrEqual(isolate_), assembler);
+  DoBinaryOp<GreaterThanOrEqualStub>(assembler);
 }
 
-
 // TestIn <src>
 //
 // Test if the object referenced by the register operand is a property of the
 // object referenced by the accumulator.
 void Interpreter::DoTestIn(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::HasProperty(isolate_), assembler);
+  DoBinaryOp<HasPropertyStub>(assembler);
 }
 
-
 // TestInstanceOf <src>
 //
 // Test if the object referenced by the <src> register is an an instance of type
 // referenced by the accumulator.
 void Interpreter::DoTestInstanceOf(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::InstanceOf(isolate_), assembler);
-}
-
-void Interpreter::DoTypeConversionOp(Callable callable,
-                                     InterpreterAssembler* assembler) {
-  Node* target = __ HeapConstant(callable.code());
-  Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* result =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
-
-// ToName
-//
-// Cast the object referenced by the accumulator to a name.
-void Interpreter::DoToName(InterpreterAssembler* assembler) {
-  DoTypeConversionOp(CodeFactory::ToName(isolate_), assembler);
-}
-
-
-// ToNumber
-//
-// Cast the object referenced by the accumulator to a number.
-void Interpreter::DoToNumber(InterpreterAssembler* assembler) {
-  DoTypeConversionOp(CodeFactory::ToNumber(isolate_), assembler);
-}
-
-
-// ToObject
-//
-// Cast the object referenced by the accumulator to a JSObject.
-void Interpreter::DoToObject(InterpreterAssembler* assembler) {
-  DoTypeConversionOp(CodeFactory::ToObject(isolate_), assembler);
+  DoBinaryOp<InstanceOfStub>(assembler);
 }
 
 // Jump <imm>
@@ -1289,12 +1273,8 @@
 // Jump by number of bytes represented by an immediate operand if the object
 // referenced by the accumulator is true when the object is cast to boolean.
 void Interpreter::DoJumpIfToBooleanTrue(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* relative_jump = __ BytecodeOperandImm(0);
   Node* true_value = __ BooleanConstant(true);
   __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
@@ -1307,12 +1287,8 @@
 // to boolean.
 void Interpreter::DoJumpIfToBooleanTrueConstant(
     InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* index = __ BytecodeOperandIdx(0);
   Node* constant = __ LoadConstantPoolEntry(index);
   Node* relative_jump = __ SmiUntag(constant);
@@ -1325,12 +1301,8 @@
 // Jump by number of bytes represented by an immediate operand if the object
 // referenced by the accumulator is false when the object is cast to boolean.
 void Interpreter::DoJumpIfToBooleanFalse(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* relative_jump = __ BytecodeOperandImm(0);
   Node* false_value = __ BooleanConstant(false);
   __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
@@ -1343,12 +1315,8 @@
 // to boolean.
 void Interpreter::DoJumpIfToBooleanFalseConstant(
     InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* index = __ BytecodeOperandIdx(0);
   Node* constant = __ LoadConstantPoolEntry(index);
   Node* relative_jump = __ SmiUntag(constant);
@@ -1579,7 +1547,6 @@
   }
 }
 
-
 // CreateUnmappedArguments
 //
 // Creates a new unmapped arguments object.
@@ -1639,7 +1606,6 @@
   __ Abort(kUnexpectedReturnFromThrow);
 }
 
-
 // ReThrow
 //
 // Re-throws the exception in the accumulator.
@@ -1651,7 +1617,6 @@
   __ Abort(kUnexpectedReturnFromThrow);
 }
 
-
 // Return
 //
 // Return the value in the accumulator.
@@ -1821,11 +1786,23 @@
 // SuspendGenerator <generator>
 //
 // Exports the register file and stores it into the generator.  Also stores the
-// current context and the state given in the accumulator into the generator.
+// current context, the state given in the accumulator, and the current bytecode
+// offset (for debugging purposes) into the generator.
 void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) {
   Node* generator_reg = __ BytecodeOperandReg(0);
   Node* generator = __ LoadRegister(generator_reg);
 
+  Label if_stepping(assembler, Label::kDeferred), ok(assembler);
+  Node* step_action_address = __ ExternalConstant(
+      ExternalReference::debug_last_step_action_address(isolate_));
+  Node* step_action = __ Load(MachineType::Int8(), step_action_address);
+  STATIC_ASSERT(StepIn > StepNext);
+  STATIC_ASSERT(StepFrame > StepNext);
+  STATIC_ASSERT(LastStepAction == StepFrame);
+  Node* step_next = __ Int32Constant(StepNext);
+  __ BranchIfInt32LessThanOrEqual(step_next, step_action, &if_stepping, &ok);
+  __ Bind(&ok);
+
   Node* array =
       __ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset);
   Node* context = __ GetContext();
@@ -1835,7 +1812,18 @@
   __ StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
   __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state);
 
+  Node* offset = __ SmiTag(__ BytecodeOffset());
+  __ StoreObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset,
+                      offset);
+
   __ Dispatch();
+
+  __ Bind(&if_stepping);
+  {
+    Node* context = __ GetContext();
+    __ CallRuntime(Runtime::kDebugRecordAsyncFunction, context, generator);
+    __ Goto(&ok);
+  }
 }
 
 // ResumeGenerator <generator>