Rollback of r15097, r15087 in trunk branch.

MIPS: Allow the deoptimizer translation to track de-materialized objects.

Allow the deoptimizer translation to track de-materialized objects.

R=hpayer@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/trunk@15136 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 1d4ed5f..fbb9c6e 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -929,7 +929,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
+  int value_count = hydrogen_env->length();
   LEnvironment* result = new(zone()) LEnvironment(
       hydrogen_env->closure(),
       hydrogen_env->frame_type(),
@@ -940,15 +940,13 @@
       outer,
       hydrogen_env->entry(),
       zone());
-  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < hydrogen_env->length(); ++i) {
+  for (int i = 0; i < value_count; ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
-      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -960,22 +958,6 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
-  if (needs_arguments_object_materialization) {
-    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
-        ? graph()->GetArgumentsObject()
-        : hydrogen_env->entry()->arguments_object();
-    ASSERT(arguments->IsLinked());
-    for (int i = 1; i < arguments->arguments_count(); ++i) {
-      HValue* value = arguments->arguments_values()->at(i);
-      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
-      ASSERT(HInstruction::cast(value)->IsLinked());
-      LOperand* op = UseAny(value);
-      result->AddValue(op,
-                       value->representation(),
-                       value->CheckFlag(HInstruction::kUint32));
-    }
-  }
-
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 253c63d..5acf360 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -580,15 +580,27 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation) {
+                                Translation* translation,
+                                int* pushed_arguments_index,
+                                int* pushed_arguments_count) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->translation_size();
+  int translation_size = environment->values()->length();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  WriteTranslation(environment->outer(), translation);
+  // Function parameters are arguments to the outermost environment. The
+  // arguments index points to the first element of a sequence of tagged
+  // values on the stack that represent the arguments. This needs to be
+  // kept in sync with the LArgumentsElements implementation.
+  *pushed_arguments_index = -environment->parameter_count();
+  *pushed_arguments_count = environment->parameter_count();
+
+  WriteTranslation(environment->outer(),
+                   translation,
+                   pushed_arguments_index,
+                   pushed_arguments_count);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -620,6 +632,23 @@
       break;
   }
 
+  // Inlined frames which push their arguments cause the index to be
+  // bumped and another stack area to be used for materialization,
+  // otherwise actual argument values are unknown for inlined frames.
+  bool arguments_known = true;
+  int arguments_index = *pushed_arguments_index;
+  int arguments_count = *pushed_arguments_count;
+  if (environment->entry() != NULL) {
+    arguments_known = environment->entry()->arguments_pushed();
+    arguments_index = arguments_index < 0
+        ? GetStackSlotCount() : arguments_index + arguments_count;
+    arguments_count = environment->entry()->arguments_count() + 1;
+    if (environment->entry()->arguments_pushed()) {
+      *pushed_arguments_index = arguments_index;
+      *pushed_arguments_count = arguments_count;
+    }
+  }
+
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -631,7 +660,10 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i));
+                         environment->HasUint32ValueAt(i),
+                         arguments_known,
+                         arguments_index,
+                         arguments_count);
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -640,36 +672,20 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false);
+            false,
+            arguments_known,
+            arguments_index,
+            arguments_count);
       }
     }
 
-    // TODO(mstarzinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    if (value == NULL) {
-      int arguments_count = environment->values()->length() - translation_size;
-      translation->BeginArgumentsObject(arguments_count);
-      for (int i = 0; i < arguments_count; ++i) {
-        LOperand* value = environment->values()->at(translation_size + i);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsRegister() ||
-               environment->spilled_registers()[value->index()] == NULL);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsDoubleRegister() ||
-               environment->spilled_double_registers()[value->index()] == NULL);
-        AddToTranslation(translation,
-                         value,
-                         environment->HasTaggedValueAt(translation_size + i),
-                         environment->HasUint32ValueAt(translation_size + i));
-      }
-      continue;
-    }
-
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i));
+                     environment->HasUint32ValueAt(i),
+                     arguments_known,
+                     arguments_index,
+                     arguments_count);
   }
 }
 
@@ -677,8 +693,17 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32) {
-  if (op->IsStackSlot()) {
+                                bool is_uint32,
+                                bool arguments_known,
+                                int arguments_index,
+                                int arguments_count) {
+  if (op == NULL) {
+    // TODO(twuerthinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    translation->StoreArgumentsObject(
+        arguments_known, arguments_index, arguments_count);
+  } else if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -785,6 +810,8 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
+    int args_index = 0;
+    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -792,7 +819,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation);
+    WriteTranslation(environment, &translation, &args_index, &args_count);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index aeba5ea..cecf152 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -171,7 +171,10 @@
                                  int additional_offset);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment, Translation* translation);
+  void WriteTranslation(LEnvironment* environment,
+                        Translation* translation,
+                        int* arguments_index,
+                        int* arguments_count);
 
   // Declare methods that deal with the individual node types.
 #define DECLARE_DO(type) void Do##type(L##type* node);
@@ -290,7 +293,10 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32);
+                        bool is_uint32,
+                        bool arguments_known,
+                        int arguments_index,
+                        int arguments_count);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
diff --git a/src/data-flow.h b/src/data-flow.h
index 8ceccf6..7eeb794 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -215,8 +215,6 @@
   };
 
   GrowableBitVector() : bits_(NULL) { }
-  GrowableBitVector(int length, Zone* zone)
-      : bits_(new(zone) BitVector(length, zone)) { }
 
   bool Contains(int value) const {
     if (!InBitsRange(value)) return false;
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 14c1d73..723d3f6 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -534,9 +534,8 @@
       output_count_(0),
       jsframe_count_(0),
       output_(NULL),
-      deferred_objects_tagged_values_(0),
-      deferred_objects_double_values_(0),
-      deferred_objects_(0),
+      deferred_arguments_objects_values_(0),
+      deferred_arguments_objects_(0),
       deferred_heap_numbers_(0),
       trace_(false) {
   // For COMPILED_STUBs called from builtins, the function pointer is a SMI
@@ -1567,14 +1566,15 @@
 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
   ASSERT_NE(DEBUGGER, bailout_type_);
 
-  // Handlify all tagged object values before triggering any allocation.
-  List<Handle<Object> > values(deferred_objects_tagged_values_.length());
-  for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) {
-    values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_));
+  // Handlify all argument object values before triggering any allocation.
+  List<Handle<Object> > values(deferred_arguments_objects_values_.length());
+  for (int i = 0; i < deferred_arguments_objects_values_.length(); ++i) {
+    values.Add(Handle<Object>(deferred_arguments_objects_values_[i],
+                              isolate_));
   }
 
   // Play it safe and clear all unhandlified values before we continue.
-  deferred_objects_tagged_values_.Clear();
+  deferred_arguments_objects_values_.Clear();
 
   // Materialize all heap numbers before looking at arguments because when the
   // output frames are used to materialize arguments objects later on they need
@@ -1591,18 +1591,6 @@
     Memory::Object_at(d.slot_address()) = *num;
   }
 
-  // Materialize all heap numbers required for arguments objects.
-  for (int i = 0; i < values.length(); i++) {
-    if (!values.at(i)->IsTheHole()) continue;
-    double double_value = deferred_objects_double_values_[i];
-    Handle<Object> num = isolate_->factory()->NewNumber(double_value);
-    if (trace_) {
-      PrintF("Materializing a new heap number %p [%e] for arguments object\n",
-             reinterpret_cast<void*>(*num), double_value);
-    }
-    values.Set(i, num);
-  }
-
   // Materialize arguments objects one frame at a time.
   for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
     if (frame_index != 0) it->Advance();
@@ -1611,9 +1599,9 @@
     Handle<JSObject> arguments;
     for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
       if (frame->GetExpression(i) == isolate_->heap()->arguments_marker()) {
-        ObjectMaterializationDescriptor descriptor =
-            deferred_objects_.RemoveLast();
-        const int length = descriptor.object_length();
+        ArgumentsObjectMaterializationDescriptor descriptor =
+            deferred_arguments_objects_.RemoveLast();
+        const int length = descriptor.arguments_length();
         if (arguments.is_null()) {
           if (frame->has_adapted_arguments()) {
             // Use the arguments adapter frame we just built to materialize the
@@ -1707,7 +1695,7 @@
 #endif
 
 
-static const char* TraceValueType(bool is_smi, bool is_native = false) {
+static const char* TraceValueType(bool is_smi, bool is_native) {
   if (is_native) {
     return "native";
   } else if (is_smi) {
@@ -1718,204 +1706,6 @@
 }
 
 
-void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
-                                    int object_opcode,
-                                    int field_index) {
-  disasm::NameConverter converter;
-  Address object_slot = deferred_objects_.last().slot_address();
-
-  // Ignore commands marked as duplicate and act on the first non-duplicate.
-  Translation::Opcode opcode =
-      static_cast<Translation::Opcode>(iterator->Next());
-  while (opcode == Translation::DUPLICATE) {
-    opcode = static_cast<Translation::Opcode>(iterator->Next());
-    iterator->Skip(Translation::NumberOfOperandsFor(opcode));
-    opcode = static_cast<Translation::Opcode>(iterator->Next());
-  }
-
-  switch (opcode) {
-    case Translation::BEGIN:
-    case Translation::JS_FRAME:
-    case Translation::ARGUMENTS_ADAPTOR_FRAME:
-    case Translation::CONSTRUCT_STUB_FRAME:
-    case Translation::GETTER_STUB_FRAME:
-    case Translation::SETTER_STUB_FRAME:
-    case Translation::COMPILED_STUB_FRAME:
-    case Translation::ARGUMENTS_OBJECT:
-    case Translation::DUPLICATE:
-      UNREACHABLE();
-      return;
-
-    case Translation::REGISTER: {
-      int input_reg = iterator->Next();
-      intptr_t input_value = input_->GetRegister(input_reg);
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("0x%08" V8PRIxPTR " ; %s ", input_value,
-               converter.NameOfCPURegister(input_reg));
-        reinterpret_cast<Object*>(input_value)->ShortPrint();
-        PrintF("\n");
-      }
-      AddObjectTaggedValue(input_value);
-      return;
-    }
-
-    case Translation::INT32_REGISTER: {
-      int input_reg = iterator->Next();
-      intptr_t value = input_->GetRegister(input_reg);
-      bool is_smi = Smi::IsValid(value);
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("%" V8PRIdPTR " ; %s (%s)\n", value,
-               converter.NameOfCPURegister(input_reg),
-               TraceValueType(is_smi));
-      }
-      if (is_smi) {
-        intptr_t tagged_value =
-            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
-        AddObjectTaggedValue(tagged_value);
-      } else {
-        double double_value = static_cast<double>(static_cast<int32_t>(value));
-        AddObjectDoubleValue(double_value);
-      }
-      return;
-    }
-
-    case Translation::UINT32_REGISTER: {
-      int input_reg = iterator->Next();
-      uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
-      bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("%" V8PRIdPTR " ; uint %s (%s)\n", value,
-               converter.NameOfCPURegister(input_reg),
-               TraceValueType(is_smi));
-      }
-      if (is_smi) {
-        intptr_t tagged_value =
-            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
-        AddObjectTaggedValue(tagged_value);
-      } else {
-        double double_value = static_cast<double>(static_cast<uint32_t>(value));
-        AddObjectDoubleValue(double_value);
-      }
-      return;
-    }
-
-    case Translation::DOUBLE_REGISTER: {
-      int input_reg = iterator->Next();
-      double value = input_->GetDoubleRegister(input_reg);
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("%e ; %s\n", value,
-               DoubleRegister::AllocationIndexToString(input_reg));
-      }
-      AddObjectDoubleValue(value);
-      return;
-    }
-
-    case Translation::STACK_SLOT: {
-      int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
-      intptr_t input_value = input_->GetFrameSlot(input_offset);
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("0x%08" V8PRIxPTR " ; [sp + %d] ", input_value, input_offset);
-        reinterpret_cast<Object*>(input_value)->ShortPrint();
-        PrintF("\n");
-      }
-      AddObjectTaggedValue(input_value);
-      return;
-    }
-
-    case Translation::INT32_STACK_SLOT: {
-      int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
-      intptr_t value = input_->GetFrameSlot(input_offset);
-      bool is_smi = Smi::IsValid(value);
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("%" V8PRIdPTR " ; [sp + %d] (%s)\n",
-               value, input_offset, TraceValueType(is_smi));
-      }
-      if (is_smi) {
-        intptr_t tagged_value =
-            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
-        AddObjectTaggedValue(tagged_value);
-      } else {
-        double double_value = static_cast<double>(static_cast<int32_t>(value));
-        AddObjectDoubleValue(double_value);
-      }
-      return;
-    }
-
-    case Translation::UINT32_STACK_SLOT: {
-      int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
-      uintptr_t value =
-          static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
-      bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("%" V8PRIdPTR " ; [sp + %d] (uint %s)\n",
-               value, input_offset, TraceValueType(is_smi));
-      }
-      if (is_smi) {
-        intptr_t tagged_value =
-            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
-        AddObjectTaggedValue(tagged_value);
-      } else {
-        double double_value = static_cast<double>(static_cast<uint32_t>(value));
-        AddObjectDoubleValue(double_value);
-      }
-      return;
-    }
-
-    case Translation::DOUBLE_STACK_SLOT: {
-      int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
-      double value = input_->GetDoubleFrameSlot(input_offset);
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        PrintF("%e ; [sp + %d]\n", value, input_offset);
-      }
-      AddObjectDoubleValue(value);
-      return;
-    }
-
-    case Translation::LITERAL: {
-      Object* literal = ComputeLiteral(iterator->Next());
-      if (trace_) {
-        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
-               reinterpret_cast<intptr_t>(object_slot),
-               field_index);
-        literal->ShortPrint();
-        PrintF(" ; literal\n");
-      }
-      intptr_t value = reinterpret_cast<intptr_t>(literal);
-      AddObjectTaggedValue(value);
-      return;
-    }
-  }
-}
-
-
 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
     int frame_index,
     unsigned output_offset,
@@ -1968,6 +1758,7 @@
       intptr_t value = input_->GetRegister(input_reg);
       bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
           Smi::IsValid(value);
+
       if (trace_) {
         PrintF(
             "    0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
@@ -2045,7 +1836,8 @@
 
     case Translation::STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset =
+          input_->GetOffsetFromSlotIndex(input_slot_index);
       intptr_t input_value = input_->GetFrameSlot(input_offset);
       if (trace_) {
         PrintF("    0x%08" V8PRIxPTR ": ",
@@ -2063,7 +1855,8 @@
 
     case Translation::INT32_STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset =
+          input_->GetOffsetFromSlotIndex(input_slot_index);
       intptr_t value = input_->GetFrameSlot(input_offset);
       bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
           Smi::IsValid(value);
@@ -2095,7 +1888,8 @@
 
     case Translation::UINT32_STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset =
+          input_->GetOffsetFromSlotIndex(input_slot_index);
       uintptr_t value =
           static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
       bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
@@ -2128,7 +1922,8 @@
 
     case Translation::DOUBLE_STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset =
+          input_->GetOffsetFromSlotIndex(input_slot_index);
       double value = input_->GetDoubleFrameSlot(input_offset);
       if (trace_) {
         PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
@@ -2159,24 +1954,31 @@
     }
 
     case Translation::ARGUMENTS_OBJECT: {
-      int length = iterator->Next();
+      bool args_known = iterator->Next();
+      int args_index = iterator->Next() + 1;  // Skip receiver.
+      int args_length = iterator->Next() - 1;  // Skip receiver.
       if (trace_) {
         PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- ",
                output_[frame_index]->GetTop() + output_offset,
                output_offset);
         isolate_->heap()->arguments_marker()->ShortPrint();
-        PrintF(" ; arguments object (length = %d)\n", length);
+        PrintF(" ; %sarguments object\n", args_known ? "" : "dummy ");
       }
       // Use the arguments marker value as a sentinel and fill in the arguments
       // object after the deoptimized frame is built.
       intptr_t value = reinterpret_cast<intptr_t>(
           isolate_->heap()->arguments_marker());
-      AddObjectStart(output_[frame_index]->GetTop() + output_offset, length);
+      AddArgumentsObject(
+          output_[frame_index]->GetTop() + output_offset, args_length);
       output_[frame_index]->SetFrameSlot(output_offset, value);
-      // We save the argument values on the side and materialize the actual
-      // arguments object after the deoptimized frame is built.
-      for (int i = 0; i < length; i++) {
-        DoTranslateObject(iterator, Translation::ARGUMENTS_OBJECT, i);
+      // We save the tagged argument values on the side and materialize the
+      // actual arguments object after the deoptimized frame is built.
+      for (int i = 0; i < args_length; i++) {
+        unsigned input_offset = input_->GetOffsetFromSlotIndex(args_index + i);
+        intptr_t input_value = args_known
+            ? input_->GetFrameSlot(input_offset)
+            : reinterpret_cast<intptr_t>(isolate_->heap()->the_hole_value());
+        AddArgumentsObjectValue(input_value);
       }
       return;
     }
@@ -2522,22 +2324,15 @@
 }
 
 
-void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) {
-  ObjectMaterializationDescriptor object_desc(
-      reinterpret_cast<Address>(slot_address), length);
-  deferred_objects_.Add(object_desc);
+void Deoptimizer::AddArgumentsObject(intptr_t slot_address, int argc) {
+  ArgumentsObjectMaterializationDescriptor object_desc(
+      reinterpret_cast<Address>(slot_address), argc);
+  deferred_arguments_objects_.Add(object_desc);
 }
 
 
-void Deoptimizer::AddObjectTaggedValue(intptr_t value) {
-  deferred_objects_tagged_values_.Add(reinterpret_cast<Object*>(value));
-  deferred_objects_double_values_.Add(isolate()->heap()->nan_value()->value());
-}
-
-
-void Deoptimizer::AddObjectDoubleValue(double value) {
-  deferred_objects_tagged_values_.Add(isolate()->heap()->the_hole_value());
-  deferred_objects_double_values_.Add(value);
+void Deoptimizer::AddArgumentsObjectValue(intptr_t value) {
+  deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value));
 }
 
 
@@ -2761,12 +2556,6 @@
 }
 
 
-void Translation::BeginArgumentsObject(int args_length) {
-  buffer_->Add(ARGUMENTS_OBJECT, zone());
-  buffer_->Add(args_length, zone());
-}
-
-
 void Translation::StoreRegister(Register reg) {
   buffer_->Add(REGISTER, zone());
   buffer_->Add(reg.code(), zone());
@@ -2821,6 +2610,16 @@
 }
 
 
+void Translation::StoreArgumentsObject(bool args_known,
+                                       int args_index,
+                                       int args_length) {
+  buffer_->Add(ARGUMENTS_OBJECT, zone());
+  buffer_->Add(args_known, zone());
+  buffer_->Add(args_index, zone());
+  buffer_->Add(args_length, zone());
+}
+
+
 void Translation::MarkDuplicate() {
   buffer_->Add(DUPLICATE, zone());
 }
@@ -2832,7 +2631,6 @@
       return 0;
     case GETTER_STUB_FRAME:
     case SETTER_STUB_FRAME:
-    case ARGUMENTS_OBJECT:
     case REGISTER:
     case INT32_REGISTER:
     case UINT32_REGISTER:
@@ -2849,6 +2647,7 @@
     case CONSTRUCT_STUB_FRAME:
       return 2;
     case JS_FRAME:
+    case ARGUMENTS_OBJECT:
       return 3;
   }
   UNREACHABLE();
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 5ca635c..5569f7f 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -75,17 +75,17 @@
 };
 
 
-class ObjectMaterializationDescriptor BASE_EMBEDDED {
+class ArgumentsObjectMaterializationDescriptor BASE_EMBEDDED {
  public:
-  ObjectMaterializationDescriptor(Address slot_address, int length)
-      : slot_address_(slot_address), object_length_(length) { }
+  ArgumentsObjectMaterializationDescriptor(Address slot_address, int argc)
+      : slot_address_(slot_address), arguments_length_(argc) { }
 
   Address slot_address() const { return slot_address_; }
-  int object_length() const { return object_length_; }
+  int arguments_length() const { return arguments_length_; }
 
  private:
   Address slot_address_;
-  int object_length_;
+  int arguments_length_;
 };
 
 
@@ -369,10 +369,6 @@
   void DoComputeCompiledStubFrame(TranslationIterator* iterator,
                                   int frame_index);
 
-  void DoTranslateObject(TranslationIterator* iterator,
-                         int object_opcode,
-                         int field_index);
-
   enum DeoptimizerTranslatedValueType {
     TRANSLATED_VALUE_IS_NATIVE,
     TRANSLATED_VALUE_IS_TAGGED
@@ -398,9 +394,8 @@
 
   Object* ComputeLiteral(int index) const;
 
-  void AddObjectStart(intptr_t slot_address, int argc);
-  void AddObjectTaggedValue(intptr_t value);
-  void AddObjectDoubleValue(double value);
+  void AddArgumentsObject(intptr_t slot_address, int argc);
+  void AddArgumentsObjectValue(intptr_t value);
   void AddDoubleValue(intptr_t slot_address, double value);
 
   static void GenerateDeoptimizationEntries(
@@ -451,9 +446,8 @@
   // Array of output frame descriptions.
   FrameDescription** output_;
 
-  List<Object*> deferred_objects_tagged_values_;
-  List<double> deferred_objects_double_values_;
-  List<ObjectMaterializationDescriptor> deferred_objects_;
+  List<Object*> deferred_arguments_objects_values_;
+  List<ArgumentsObjectMaterializationDescriptor> deferred_arguments_objects_;
   List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_;
 #ifdef DEBUG
   DisallowHeapAllocation* disallow_heap_allocation_;
@@ -704,7 +698,6 @@
     SETTER_STUB_FRAME,
     ARGUMENTS_ADAPTOR_FRAME,
     COMPILED_STUB_FRAME,
-    ARGUMENTS_OBJECT,
     REGISTER,
     INT32_REGISTER,
     UINT32_REGISTER,
@@ -714,6 +707,7 @@
     UINT32_STACK_SLOT,
     DOUBLE_STACK_SLOT,
     LITERAL,
+    ARGUMENTS_OBJECT,
 
     // A prefix indicating that the next command is a duplicate of the one
     // that follows it.
@@ -739,7 +733,6 @@
   void BeginConstructStubFrame(int literal_id, unsigned height);
   void BeginGetterStubFrame(int literal_id);
   void BeginSetterStubFrame(int literal_id);
-  void BeginArgumentsObject(int args_length);
   void StoreRegister(Register reg);
   void StoreInt32Register(Register reg);
   void StoreUint32Register(Register reg);
@@ -749,6 +742,7 @@
   void StoreUint32StackSlot(int index);
   void StoreDoubleStackSlot(int index);
   void StoreLiteral(int literal_id);
+  void StoreArgumentsObject(bool args_known, int args_index, int args_length);
   void MarkDuplicate();
 
   Zone* zone() const { return zone_; }
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index d13a31b..d691299 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -2016,9 +2016,6 @@
 };
 
 
-class HArgumentsObject;
-
-
 class HEnterInlined: public HTemplateInstruction<0> {
  public:
   HEnterInlined(Handle<JSFunction> closure,
@@ -2026,7 +2023,7 @@
                 FunctionLiteral* function,
                 InliningKind inlining_kind,
                 Variable* arguments_var,
-                HArgumentsObject* arguments_object,
+                ZoneList<HValue*>* arguments_values,
                 bool undefined_receiver,
                 Zone* zone)
       : closure_(closure),
@@ -2035,7 +2032,7 @@
         function_(function),
         inlining_kind_(inlining_kind),
         arguments_var_(arguments_var),
-        arguments_object_(arguments_object),
+        arguments_values_(arguments_values),
         undefined_receiver_(undefined_receiver),
         return_targets_(2, zone) {
   }
@@ -2058,7 +2055,7 @@
   }
 
   Variable* arguments_var() { return arguments_var_; }
-  HArgumentsObject* arguments_object() { return arguments_object_; }
+  ZoneList<HValue*>* arguments_values() { return arguments_values_; }
 
   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
 
@@ -2069,7 +2066,7 @@
   FunctionLiteral* function_;
   InliningKind inlining_kind_;
   Variable* arguments_var_;
-  HArgumentsObject* arguments_object_;
+  ZoneList<HValue*>* arguments_values_;
   bool undefined_receiver_;
   ZoneList<HBasicBlock*> return_targets_;
 };
@@ -3205,37 +3202,19 @@
 
 class HArgumentsObject: public HTemplateInstruction<0> {
  public:
-  HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
+  HArgumentsObject() {
     set_representation(Representation::Tagged());
     SetFlag(kIsArguments);
   }
 
-  const ZoneList<HValue*>* arguments_values() const { return &values_; }
-  int arguments_count() const { return values_.length(); }
-
-  void AddArgument(HValue* argument, Zone* zone) {
-    values_.Add(NULL, zone);  // Resize list.
-    SetOperandAt(values_.length() - 1, argument);
-  }
-
-  virtual int OperandCount() { return values_.length(); }
-  virtual HValue* OperandAt(int index) const { return values_[index]; }
-
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
   }
 
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
 
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    values_[index] = value;
-  }
-
  private:
   virtual bool IsDeletable() const { return true; }
-
-  ZoneList<HValue*> values_;
 };
 
 
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index e86d216..0676555 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3546,7 +3546,6 @@
       function_return_(NULL),
       test_context_(NULL),
       entry_(NULL),
-      arguments_object_(NULL),
       arguments_elements_(NULL),
       outer_(owner->function_state()) {
   if (outer_ != NULL) {
@@ -4698,18 +4697,18 @@
   AddInstruction(undefined_constant);
   graph()->set_undefined_constant(undefined_constant);
 
-  // Create an arguments object containing the initial parameters.  Set the
-  // initial values of parameters including "this" having parameter index 0.
+  HArgumentsObject* object = new(zone()) HArgumentsObject;
+  AddInstruction(object);
+  graph()->SetArgumentsObject(object);
+
+  // Set the initial values of parameters including "this".  "This" has
+  // parameter index 0.
   ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
-  HArgumentsObject* arguments_object =
-      new(zone()) HArgumentsObject(environment()->parameter_count(), zone());
+
   for (int i = 0; i < environment()->parameter_count(); ++i) {
     HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
-    arguments_object->AddArgument(parameter, zone());
     environment()->Bind(i, parameter);
   }
-  AddInstruction(arguments_object);
-  graph()->SetArgumentsObject(arguments_object);
 
   // First special is HContext.
   HInstruction* context = AddInstruction(new(zone()) HContext);
@@ -7429,8 +7428,7 @@
   HEnterInlined* entry = function_state()->entry();
   entry->set_arguments_pushed();
 
-  HArgumentsObject* arguments = entry->arguments_object();
-  const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
+  ZoneList<HValue*>* arguments_values = entry->arguments_values();
 
   HInstruction* insert_after = entry;
   for (int i = 0; i < arguments_values->length(); i++) {
@@ -8031,20 +8029,17 @@
 
   AddSimulate(return_id);
   current_block()->UpdateEnvironment(inner_env);
-  HArgumentsObject* arguments_object = NULL;
+  ZoneList<HValue*>* arguments_values = NULL;
 
-  // If the function uses arguments object create and bind one, also copy
-  // current arguments values to use them for materialization.
+  // If the function uses arguments copy current arguments values
+  // to use them for materialization.
   if (function->scope()->arguments() != NULL) {
-    ASSERT(function->scope()->arguments()->IsStackAllocated());
     HEnvironment* arguments_env = inner_env->arguments_environment();
     int arguments_count = arguments_env->parameter_count();
-    arguments_object = new(zone()) HArgumentsObject(arguments_count, zone());
-    inner_env->Bind(function->scope()->arguments(), arguments_object);
+    arguments_values = new(zone()) ZoneList<HValue*>(arguments_count, zone());
     for (int i = 0; i < arguments_count; i++) {
-      arguments_object->AddArgument(arguments_env->Lookup(i), zone());
+      arguments_values->Add(arguments_env->Lookup(i), zone());
     }
-    AddInstruction(arguments_object);
   }
 
   HEnterInlined* enter_inlined =
@@ -8053,12 +8048,20 @@
                                 function,
                                 function_state()->inlining_kind(),
                                 function->scope()->arguments(),
-                                arguments_object,
+                                arguments_values,
                                 undefined_receiver,
                                 zone());
   function_state()->set_entry(enter_inlined);
   AddInstruction(enter_inlined);
 
+  // If the function uses arguments object create and bind one.
+  if (function->scope()->arguments() != NULL) {
+    ASSERT(function->scope()->arguments()->IsStackAllocated());
+    inner_env->Bind(function->scope()->arguments(),
+                    graph()->GetArgumentsObject());
+  }
+
+
   VisitDeclarations(target_info.scope()->declarations());
   VisitStatements(function->body());
   if (HasStackOverflow()) {
@@ -8490,10 +8493,13 @@
   } else {
     // We are inside inlined function and we know exactly what is inside
     // arguments object. But we need to be able to materialize at deopt.
+    // TODO(mstarzinger): For now we just ensure arguments are pushed
+    // right after HEnterInlined, but we could be smarter about this.
+    EnsureArgumentsArePushedForAccess();
     ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
-              function_state()->entry()->arguments_object()->arguments_count());
-    HArgumentsObject* args = function_state()->entry()->arguments_object();
-    const ZoneList<HValue*>* arguments_values = args->arguments_values();
+              function_state()->entry()->arguments_values()->length());
+    HEnterInlined* entry = function_state()->entry();
+    ZoneList<HValue*>* arguments_values = entry->arguments_values();
     int arguments_count = arguments_values->length();
     PushAndAdd(new(zone()) HWrapReceiver(receiver, function));
     for (int i = 1; i < arguments_count; i++) {
@@ -11008,7 +11014,6 @@
       values_(arguments, zone),
       frame_type_(frame_type),
       parameter_count_(arguments),
-      specials_count_(0),
       local_count_(0),
       outer_(outer),
       entry_(NULL),
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 3680775..a6f0521 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -260,7 +260,6 @@
   HStackCheck* stack_check_;
 };
 
-
 class BoundsCheckTable;
 class HGraph: public ZoneObject {
  public:
@@ -412,10 +411,6 @@
     depends_on_empty_array_proto_elements_ = true;
   }
 
-  bool depends_on_empty_array_proto_elements() {
-    return depends_on_empty_array_proto_elements_;
-  }
-
   void RecordUint32Instruction(HInstruction* instr) {
     if (uint32_instructions_ == NULL) {
       uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
@@ -881,11 +876,6 @@
   HEnterInlined* entry() { return entry_; }
   void set_entry(HEnterInlined* entry) { entry_ = entry; }
 
-  HArgumentsObject* arguments_object() { return arguments_object_; }
-  void set_arguments_object(HArgumentsObject* arguments_object) {
-    arguments_object_ = arguments_object;
-  }
-
   HArgumentsElements* arguments_elements() { return arguments_elements_; }
   void set_arguments_elements(HArgumentsElements* arguments_elements) {
     arguments_elements_ = arguments_elements;
@@ -919,7 +909,6 @@
   // entry.
   HEnterInlined* entry_;
 
-  HArgumentsObject* arguments_object_;
   HArgumentsElements* arguments_elements_;
 
   FunctionState* outer_;
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index cfda00a..5df6d81 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -614,15 +614,27 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation) {
+                                Translation* translation,
+                                int* pushed_arguments_index,
+                                int* pushed_arguments_count) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->translation_size();
+  int translation_size = environment->values()->length();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  WriteTranslation(environment->outer(), translation);
+  // Function parameters are arguments to the outermost environment. The
+  // arguments index points to the first element of a sequence of tagged
+  // values on the stack that represent the arguments. This needs to be
+  // kept in sync with the LArgumentsElements implementation.
+  *pushed_arguments_index = -environment->parameter_count();
+  *pushed_arguments_count = environment->parameter_count();
+
+  WriteTranslation(environment->outer(),
+                   translation,
+                   pushed_arguments_index,
+                   pushed_arguments_count);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -655,6 +667,23 @@
       UNREACHABLE();
   }
 
+  // Inlined frames which push their arguments cause the index to be
+  // bumped and another stack area to be used for materialization,
+  // otherwise actual argument values are unknown for inlined frames.
+  bool arguments_known = true;
+  int arguments_index = *pushed_arguments_index;
+  int arguments_count = *pushed_arguments_count;
+  if (environment->entry() != NULL) {
+    arguments_known = environment->entry()->arguments_pushed();
+    arguments_index = arguments_index < 0
+        ? GetStackSlotCount() : arguments_index + arguments_count;
+    arguments_count = environment->entry()->arguments_count() + 1;
+    if (environment->entry()->arguments_pushed()) {
+      *pushed_arguments_index = arguments_index;
+      *pushed_arguments_count = arguments_count;
+    }
+  }
+
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -666,7 +695,10 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i));
+                         environment->HasUint32ValueAt(i),
+                         arguments_known,
+                         arguments_index,
+                         arguments_count);
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -675,36 +707,20 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false);
+            false,
+            arguments_known,
+            arguments_index,
+            arguments_count);
       }
     }
 
-    // TODO(mstarzinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    if (value == NULL) {
-      int arguments_count = environment->values()->length() - translation_size;
-      translation->BeginArgumentsObject(arguments_count);
-      for (int i = 0; i < arguments_count; ++i) {
-        LOperand* value = environment->values()->at(translation_size + i);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsRegister() ||
-               environment->spilled_registers()[value->index()] == NULL);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsDoubleRegister() ||
-               environment->spilled_double_registers()[value->index()] == NULL);
-        AddToTranslation(translation,
-                         value,
-                         environment->HasTaggedValueAt(translation_size + i),
-                         environment->HasUint32ValueAt(translation_size + i));
-      }
-      continue;
-    }
-
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i));
+                     environment->HasUint32ValueAt(i),
+                     arguments_known,
+                     arguments_index,
+                     arguments_count);
   }
 }
 
@@ -712,8 +728,17 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32) {
-  if (op->IsStackSlot()) {
+                                bool is_uint32,
+                                bool arguments_known,
+                                int arguments_index,
+                                int arguments_count) {
+  if (op == NULL) {
+    // TODO(twuerthinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    translation->StoreArgumentsObject(
+        arguments_known, arguments_index, arguments_count);
+  } else if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -839,6 +864,8 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
+    int args_index = 0;
+    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -846,7 +873,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation);
+    WriteTranslation(environment, &translation, &args_index, &args_count);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index 21f6076..33f0eda 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -168,7 +168,10 @@
   void DoGap(LGap* instr);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment, Translation* translation);
+  void WriteTranslation(LEnvironment* environment,
+                        Translation* translation,
+                        int* arguments_index,
+                        int* arguments_count);
 
   void EnsureRelocSpaceForDeoptimization();
 
@@ -282,7 +285,10 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32);
+                        bool is_uint32,
+                        bool arguments_known,
+                        int arguments_index,
+                        int arguments_count);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 216872d..325ed2c 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -990,7 +990,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
+  int value_count = hydrogen_env->length();
   LEnvironment* result =
       new(zone()) LEnvironment(hydrogen_env->closure(),
                                hydrogen_env->frame_type(),
@@ -1001,15 +1001,13 @@
                                outer,
                                hydrogen_env->entry(),
                                zone());
-  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < hydrogen_env->length(); ++i) {
+  for (int i = 0; i < value_count; ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
-      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -1021,22 +1019,6 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
-  if (needs_arguments_object_materialization) {
-    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
-        ? graph()->GetArgumentsObject()
-        : hydrogen_env->entry()->arguments_object();
-    ASSERT(arguments->IsLinked());
-    for (int i = 1; i < arguments->arguments_count(); ++i) {
-      HValue* value = arguments->arguments_values()->at(i);
-      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
-      ASSERT(HInstruction::cast(value)->IsLinked());
-      LOperand* op = UseAny(value);
-      result->AddValue(op,
-                       value->representation(),
-                       value->CheckFlag(HInstruction::kUint32));
-    }
-  }
-
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/src/lithium.h b/src/lithium.h
index ab34453..170e5c8 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -527,7 +527,6 @@
         deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
         translation_index_(-1),
         ast_id_(ast_id),
-        translation_size_(value_count),
         parameter_count_(parameter_count),
         pc_offset_(-1),
         values_(value_count, zone),
@@ -545,7 +544,6 @@
   int deoptimization_index() const { return deoptimization_index_; }
   int translation_index() const { return translation_index_; }
   BailoutId ast_id() const { return ast_id_; }
-  int translation_size() const { return translation_size_; }
   int parameter_count() const { return parameter_count_; }
   int pc_offset() const { return pc_offset_; }
   LOperand** spilled_registers() const { return spilled_registers_; }
@@ -555,7 +553,6 @@
   const ZoneList<LOperand*>* values() const { return &values_; }
   LEnvironment* outer() const { return outer_; }
   HEnterInlined* entry() { return entry_; }
-  Zone* zone() const { return zone_; }
 
   void AddValue(LOperand* operand,
                 Representation representation,
@@ -563,11 +560,11 @@
     values_.Add(operand, zone());
     if (representation.IsSmiOrTagged()) {
       ASSERT(!is_uint32);
-      is_tagged_.Add(values_.length() - 1, zone());
+      is_tagged_.Add(values_.length() - 1);
     }
 
     if (is_uint32) {
-      is_uint32_.Add(values_.length() - 1, zone());
+      is_uint32_.Add(values_.length() - 1);
     }
   }
 
@@ -599,6 +596,8 @@
 
   void PrintTo(StringStream* stream);
 
+  Zone* zone() const { return zone_; }
+
  private:
   Handle<JSFunction> closure_;
   FrameType frame_type_;
@@ -606,15 +605,11 @@
   int deoptimization_index_;
   int translation_index_;
   BailoutId ast_id_;
-  int translation_size_;
   int parameter_count_;
   int pc_offset_;
-
-  // Value array: [parameters] [locals] [expression stack] [de-materialized].
-  //              |>--------- translation_size ---------<|
   ZoneList<LOperand*> values_;
-  GrowableBitVector is_tagged_;
-  GrowableBitVector is_uint32_;
+  BitVector is_tagged_;
+  BitVector is_uint32_;
 
   // Allocation index indexed arrays of spill slot operands for registers
   // that are also in spill slots at an OSR entry.  NULL for environments
@@ -624,6 +619,7 @@
 
   LEnvironment* outer_;
   HEnterInlined* entry_;
+
   Zone* zone_;
 };
 
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 0f02578..c256646 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -561,15 +561,27 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation) {
+                                Translation* translation,
+                                int* pushed_arguments_index,
+                                int* pushed_arguments_count) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->translation_size();
+  int translation_size = environment->values()->length();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  WriteTranslation(environment->outer(), translation);
+  // Function parameters are arguments to the outermost environment. The
+  // arguments index points to the first element of a sequence of tagged
+  // values on the stack that represent the arguments. This needs to be
+  // kept in sync with the LArgumentsElements implementation.
+  *pushed_arguments_index = -environment->parameter_count();
+  *pushed_arguments_count = environment->parameter_count();
+
+  WriteTranslation(environment->outer(),
+                   translation,
+                   pushed_arguments_index,
+                   pushed_arguments_count);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -601,6 +613,23 @@
       break;
   }
 
+  // Inlined frames which push their arguments cause the index to be
+  // bumped and another stack area to be used for materialization,
+  // otherwise actual argument values are unknown for inlined frames.
+  bool arguments_known = true;
+  int arguments_index = *pushed_arguments_index;
+  int arguments_count = *pushed_arguments_count;
+  if (environment->entry() != NULL) {
+    arguments_known = environment->entry()->arguments_pushed();
+    arguments_index = arguments_index < 0
+        ? GetStackSlotCount() : arguments_index + arguments_count;
+    arguments_count = environment->entry()->arguments_count() + 1;
+    if (environment->entry()->arguments_pushed()) {
+      *pushed_arguments_index = arguments_index;
+      *pushed_arguments_count = arguments_count;
+    }
+  }
+
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -612,7 +641,10 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i));
+                         environment->HasUint32ValueAt(i),
+                         arguments_known,
+                         arguments_index,
+                         arguments_count);
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -621,36 +653,20 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false);
+            false,
+            arguments_known,
+            arguments_index,
+            arguments_count);
       }
     }
 
-    // TODO(mstarzinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    if (value == NULL) {
-      int arguments_count = environment->values()->length() - translation_size;
-      translation->BeginArgumentsObject(arguments_count);
-      for (int i = 0; i < arguments_count; ++i) {
-        LOperand* value = environment->values()->at(translation_size + i);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsRegister() ||
-               environment->spilled_registers()[value->index()] == NULL);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsDoubleRegister() ||
-               environment->spilled_double_registers()[value->index()] == NULL);
-        AddToTranslation(translation,
-                         value,
-                         environment->HasTaggedValueAt(translation_size + i),
-                         environment->HasUint32ValueAt(translation_size + i));
-      }
-      continue;
-    }
-
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i));
+                     environment->HasUint32ValueAt(i),
+                     arguments_known,
+                     arguments_index,
+                     arguments_count);
   }
 }
 
@@ -658,8 +674,17 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32) {
-  if (op->IsStackSlot()) {
+                                bool is_uint32,
+                                bool arguments_known,
+                                int arguments_index,
+                                int arguments_count) {
+  if (op == NULL) {
+    // TODO(twuerthinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    translation->StoreArgumentsObject(
+        arguments_known, arguments_index, arguments_count);
+  } else if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -754,6 +779,8 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
+    int args_index = 0;
+    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -761,7 +788,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation);
+    WriteTranslation(environment, &translation, &args_index, &args_count);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index a8d7e04..ee01383 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -169,7 +169,10 @@
                                  int additional_offset);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment, Translation* translation);
+  void WriteTranslation(LEnvironment* environment,
+                        Translation* translation,
+                        int* arguments_index,
+                        int* arguments_count);
 
   // Declare methods that deal with the individual node types.
 #define DECLARE_DO(type) void Do##type(L##type* node);
@@ -292,7 +295,10 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32);
+                        bool is_uint32,
+                        bool arguments_known,
+                        int arguments_index,
+                        int arguments_count);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 889e997..ad39c61 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -933,7 +933,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
+  int value_count = hydrogen_env->length();
   LEnvironment* result = new(zone()) LEnvironment(
       hydrogen_env->closure(),
       hydrogen_env->frame_type(),
@@ -944,15 +944,13 @@
       outer,
       hydrogen_env->entry(),
       zone());
-  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < hydrogen_env->length(); ++i) {
+  for (int i = 0; i < value_count; ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
-      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -964,22 +962,6 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
-  if (needs_arguments_object_materialization) {
-    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
-        ? graph()->GetArgumentsObject()
-        : hydrogen_env->entry()->arguments_object();
-    ASSERT(arguments->IsLinked());
-    for (int i = 1; i < arguments->arguments_count(); ++i) {
-      HValue* value = arguments->arguments_values()->at(i);
-      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
-      ASSERT(HInstruction::cast(value)->IsLinked());
-      LOperand* op = UseAny(value);
-      result->AddValue(op,
-                       value->representation(),
-                       value->CheckFlag(HInstruction::kUint32));
-    }
-  }
-
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/src/objects.cc b/src/objects.cc
index 5459679..54d25a7 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1384,7 +1384,7 @@
                        global_object ? "Global Object: " : "",
                        vowel ? "n" : "");
                 accumulator->Put(str);
-                accumulator->Add(" with %smap %p",
+                accumulator->Add(" with %smap 0x%p",
                     map_of_this->is_deprecated() ? "deprecated " : "",
                     map_of_this);
                 printed = true;
@@ -10556,8 +10556,11 @@
         }
 
         case Translation::ARGUMENTS_OBJECT: {
+          bool args_known = iterator.Next();
+          int args_index = iterator.Next();
           int args_length = iterator.Next();
-          PrintF(out, "{length=%d}", args_length);
+          PrintF(out, "{index=%d, length=%d, known=%d}",
+                 args_index, args_length, args_known);
           break;
         }
       }
diff --git a/src/version.cc b/src/version.cc
index e443d37..1d61fe8 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     19
 #define BUILD_NUMBER      15
-#define PATCH_LEVEL       0
+#define PATCH_LEVEL       1
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 1dd27ac..18958db 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -469,15 +469,27 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation) {
+                                Translation* translation,
+                                int* pushed_arguments_index,
+                                int* pushed_arguments_count) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->translation_size();
+  int translation_size = environment->values()->length();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  WriteTranslation(environment->outer(), translation);
+  // Function parameters are arguments to the outermost environment. The
+  // arguments index points to the first element of a sequence of tagged
+  // values on the stack that represent the arguments. This needs to be
+  // kept in sync with the LArgumentsElements implementation.
+  *pushed_arguments_index = -environment->parameter_count();
+  *pushed_arguments_count = environment->parameter_count();
+
+  WriteTranslation(environment->outer(),
+                   translation,
+                   pushed_arguments_index,
+                   pushed_arguments_count);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -509,6 +521,23 @@
       break;
   }
 
+  // Inlined frames which push their arguments cause the index to be
+  // bumped and another stack area to be used for materialization,
+  // otherwise actual argument values are unknown for inlined frames.
+  bool arguments_known = true;
+  int arguments_index = *pushed_arguments_index;
+  int arguments_count = *pushed_arguments_count;
+  if (environment->entry() != NULL) {
+    arguments_known = environment->entry()->arguments_pushed();
+    arguments_index = arguments_index < 0
+        ? GetStackSlotCount() : arguments_index + arguments_count;
+    arguments_count = environment->entry()->arguments_count() + 1;
+    if (environment->entry()->arguments_pushed()) {
+      *pushed_arguments_index = arguments_index;
+      *pushed_arguments_count = arguments_count;
+    }
+  }
+
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -520,7 +549,10 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i));
+                         environment->HasUint32ValueAt(i),
+                         arguments_known,
+                         arguments_index,
+                         arguments_count);
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -529,36 +561,20 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false);
+            false,
+            arguments_known,
+            arguments_index,
+            arguments_count);
       }
     }
 
-    // TODO(mstarzinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    if (value == NULL) {
-      int arguments_count = environment->values()->length() - translation_size;
-      translation->BeginArgumentsObject(arguments_count);
-      for (int i = 0; i < arguments_count; ++i) {
-        LOperand* value = environment->values()->at(translation_size + i);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsRegister() ||
-               environment->spilled_registers()[value->index()] == NULL);
-        ASSERT(environment->spilled_registers() == NULL ||
-               !value->IsDoubleRegister() ||
-               environment->spilled_double_registers()[value->index()] == NULL);
-        AddToTranslation(translation,
-                         value,
-                         environment->HasTaggedValueAt(translation_size + i),
-                         environment->HasUint32ValueAt(translation_size + i));
-      }
-      continue;
-    }
-
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i));
+                     environment->HasUint32ValueAt(i),
+                     arguments_known,
+                     arguments_index,
+                     arguments_count);
   }
 }
 
@@ -566,8 +582,17 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32) {
-  if (op->IsStackSlot()) {
+                                bool is_uint32,
+                                bool arguments_known,
+                                int arguments_index,
+                                int arguments_count) {
+  if (op == NULL) {
+    // TODO(twuerthinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    translation->StoreArgumentsObject(
+        arguments_known, arguments_index, arguments_count);
+  } else if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -672,6 +697,8 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
+    int args_index = 0;
+    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -679,7 +706,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation);
+    WriteTranslation(environment, &translation, &args_index, &args_count);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 31dd9c4..c3f99c4f 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -139,7 +139,10 @@
   void DoGap(LGap* instr);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment, Translation* translation);
+  void WriteTranslation(LEnvironment* environment,
+                        Translation* translation,
+                        int* arguments_index,
+                        int* arguments_count);
 
   // Declare methods that deal with the individual node types.
 #define DECLARE_DO(type) void Do##type(L##type* node);
@@ -250,7 +253,10 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32);
+                        bool is_uint32,
+                        bool arguments_known,
+                        int arguments_index,
+                        int arguments_count);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 57a8b2e..cb0659d 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -937,7 +937,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
+  int value_count = hydrogen_env->length();
   LEnvironment* result = new(zone()) LEnvironment(
       hydrogen_env->closure(),
       hydrogen_env->frame_type(),
@@ -948,15 +948,13 @@
       outer,
       hydrogen_env->entry(),
       zone());
-  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < hydrogen_env->length(); ++i) {
+  for (int i = 0; i < value_count; ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
-      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -968,22 +966,6 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
-  if (needs_arguments_object_materialization) {
-    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
-        ? graph()->GetArgumentsObject()
-        : hydrogen_env->entry()->arguments_object();
-    ASSERT(arguments->IsLinked());
-    for (int i = 1; i < arguments->arguments_count(); ++i) {
-      HValue* value = arguments->arguments_values()->at(i);
-      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
-      ASSERT(HInstruction::cast(value)->IsLinked());
-      LOperand* op = UseAny(value);
-      result->AddValue(op,
-                       value->representation(),
-                       value->CheckFlag(HInstruction::kUint32));
-    }
-  }
-
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/test/mjsunit/compiler/inline-arguments.js b/test/mjsunit/compiler/inline-arguments.js
index 75d01b5..df1bd22 100644
--- a/test/mjsunit/compiler/inline-arguments.js
+++ b/test/mjsunit/compiler/inline-arguments.js
@@ -266,46 +266,3 @@
     }
   }
 })();
-
-
-// Test materialization of arguments object with values in registers.
-(function () {
-  "use strict";
-  var forceDeopt = { deopt:false };
-  function inner(a,b,c,d,e,f,g,h,i,j) {
-    var args = arguments;
-    forceDeopt.deopt;
-    assertSame(10, args.length);
-    assertSame(a, args[0]);
-    assertSame(b, args[1]);
-    assertSame(c, args[2]);
-    assertSame(d, args[3]);
-    assertSame(e, args[4]);
-    assertSame(f, args[5]);
-    assertSame(g, args[6]);
-    assertSame(h, args[7]);
-    assertSame(i, args[8]);
-    assertSame(j, args[9]);
-  }
-
-  var a = 0.5;
-  var b = 1.7;
-  var c = 123;
-  function outer() {
-    inner(
-      a - 0.3,  // double in double register
-      b + 2.3,  // integer in double register
-      c + 321,  // integer in general register
-      c - 456,  // integer in stack slot
-      a + 0.1, a + 0.2, a + 0.3, a + 0.4, a + 0.5,
-      a + 0.6   // double in stack slot
-    );
-  }
-
-  outer();
-  outer();
-  %OptimizeFunctionOnNextCall(outer);
-  outer();
-  delete forceDeopt.deopt;
-  outer();
-})();