Revision: 20978
Author:   [email protected]
Date:     Fri Apr 25 12:58:15 2014 UTC
Log:      Fix materialization of accessor frames with captured receivers

I have fixed skipping of the receiver object to materialize captured
objects. This is done with a new DoTranslateSkip method.

We should consider unifying DoTranslateSkip, DoTranslateObject and
DoTranslateCommand as they do the almost the same thing - they only
differ in where they store the result.

The change also turns bunch of ASSERTs into CHECKs.

[email protected]
BUG=359441
TEST=test/mjsunit/regress/regress-359441.js
LOG=N

Review URL: https://codereview.chromium.org/225283006
http://code.google.com/p/v8/source/detail?r=20978

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-359441.js
Modified:
 /branches/bleeding_edge/src/deoptimizer.cc
 /branches/bleeding_edge/src/deoptimizer.h

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-359441.js Fri Apr 25 12:58:15 2014 UTC
@@ -0,0 +1,23 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function g() {
+  this.x = {};
+}
+
+function f() {
+  new g();
+}
+
+function deopt(x) {
+  %DeoptimizeFunction(f);
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+Object.prototype.__defineSetter__('x', deopt);
+f();
=======================================
--- /branches/bleeding_edge/src/deoptimizer.cc  Fri Apr 25 11:00:37 2014 UTC
+++ /branches/bleeding_edge/src/deoptimizer.cc  Fri Apr 25 12:58:15 2014 UTC
@@ -87,7 +87,7 @@
     Object* element = native_context->DeoptimizedCodeListHead();
     while (!element->IsUndefined()) {
       Code* code = Code::cast(element);
-      ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+      CHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
       if (code->contains(addr)) return code;
       element = code->next_code_link();
     }
@@ -111,7 +111,7 @@
                                              from,
                                              fp_to_sp_delta,
                                              NULL);
-  ASSERT(isolate->deoptimizer_data()->current_ == NULL);
+  CHECK(isolate->deoptimizer_data()->current_ == NULL);
   isolate->deoptimizer_data()->current_ = deoptimizer;
   return deoptimizer;
 }
@@ -133,7 +133,7 @@

 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
   Deoptimizer* result = isolate->deoptimizer_data()->current_;
-  ASSERT(result != NULL);
+  CHECK_NE(result, NULL);
   result->DeleteFrameDescriptions();
   isolate->deoptimizer_data()->current_ = NULL;
   return result;
@@ -160,8 +160,8 @@
     JavaScriptFrame* frame,
     int jsframe_index,
     Isolate* isolate) {
-  ASSERT(frame->is_optimized());
-  ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL);
+  CHECK(frame->is_optimized());
+  CHECK(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL);

   // Get the function and code from the frame.
   JSFunction* function = frame->function();
@@ -171,7 +171,7 @@
// return address must be at a place in the code with deoptimization support.
   SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
   int deoptimization_index = safepoint_entry.deoptimization_index();
-  ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
+  CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex);

   // Always use the actual stack slots when calculating the fp to sp
   // delta adding two for the function and context.
@@ -194,7 +194,7 @@

   // Create the GC safe output frame information and register it for GC
   // handling.
-  ASSERT_LT(jsframe_index, deoptimizer->jsframe_count());
+  CHECK_LT(jsframe_index, deoptimizer->jsframe_count());

   // Convert JS frame index into frame index.
int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index);
@@ -246,7 +246,7 @@

void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
                                                  Isolate* isolate) {
-  ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info);
+  CHECK_EQ(isolate->deoptimizer_data()->deoptimized_frame_info_, info);
   delete info;
   isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL;
 }
@@ -264,7 +264,7 @@
     Context* context, OptimizedFunctionVisitor* visitor) {
   DisallowHeapAllocation no_allocation;

-  ASSERT(context->IsNativeContext());
+  CHECK(context->IsNativeContext());

   visitor->EnterContext(context);

@@ -287,13 +287,13 @@
         context->SetOptimizedFunctionsListHead(next);
       }
       // The visitor should not alter the link directly.
-      ASSERT(function->next_function_link() == next);
+      CHECK_EQ(function->next_function_link(), next);
// Set the next function link to undefined to indicate it is no longer
       // in the optimized functions list.
function->set_next_function_link(context->GetHeap()->undefined_value());
     } else {
       // The visitor should not alter the link directly.
-      ASSERT(function->next_function_link() == next);
+      CHECK_EQ(function->next_function_link(), next);
       // preserve this element.
       prev = function;
     }
@@ -395,7 +395,7 @@
   Object* element = context->OptimizedCodeListHead();
   while (!element->IsUndefined()) {
     Code* code = Code::cast(element);
-    ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+    CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     Object* next = code->next_code_link();
     if (code->marked_for_deoptimization()) {
       // Put the code into the list for later patching.
@@ -483,7 +483,7 @@
   }
   if (object->IsJSGlobalProxy()) {
     Object* proto = object->GetPrototype();
-    ASSERT(proto->IsJSGlobalObject());
+    CHECK(proto->IsJSGlobalObject());
     Context* native_context = GlobalObject::cast(proto)->native_context();
     MarkAllCodeForContext(native_context);
     DeoptimizeMarkedCodeForContext(native_context);
@@ -499,7 +499,7 @@
   Object* element = context->OptimizedCodeListHead();
   while (!element->IsUndefined()) {
     Code* code = Code::cast(element);
-    ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+    CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     code->set_marked_for_deoptimization(true);
     element = code->next_code_link();
   }
@@ -534,7 +534,7 @@
           ? FLAG_trace_stub_failures
           : FLAG_trace_deopt;
   }
-  UNREACHABLE();
+  FATAL("Unsupported deopt type");
   return false;
 }

@@ -546,7 +546,7 @@
     case LAZY: return "lazy";
     case DEBUGGER: return "debugger";
   }
-  UNREACHABLE();
+  FATAL("Unsupported deopt type");
   return NULL;
 }

@@ -636,7 +636,7 @@
       ASSERT(optimized_code->contains(from_));
       return optimized_code;
   }
-  UNREACHABLE();
+  FATAL("Could not find code for optimized function");
   return NULL;
 }

@@ -679,15 +679,15 @@
                                             int id,
                                             BailoutType type,
                                             GetEntryMode mode) {
-  ASSERT(id >= 0);
+  CHECK_GE(id, 0);
   if (id >= kMaxNumberOfEntries) return NULL;
   if (mode == ENSURE_ENTRY_CODE) {
     EnsureCodeForDeoptimizationEntry(isolate, type, id);
   } else {
-    ASSERT(mode == CALCULATE_ENTRY_ADDRESS);
+    CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS);
   }
   DeoptimizerData* data = isolate->deoptimizer_data();
-  ASSERT(type < kBailoutTypesWithCodeEntry);
+  CHECK_LT(type, kBailoutTypesWithCodeEntry);
   MemoryChunk* base = data->deopt_entry_code_[type];
   return base->area_start() + (id * table_entry_size_);
 }
@@ -850,7 +850,7 @@
       case Translation::LITERAL:
       case Translation::ARGUMENTS_OBJECT:
       default:
-        UNREACHABLE();
+        FATAL("Unsupported translation");
         break;
     }
   }
@@ -889,7 +889,7 @@
   } else {
     int closure_id = iterator->Next();
     USE(closure_id);
-    ASSERT_EQ(Translation::kSelfLiteralId, closure_id);
+    CHECK_EQ(Translation::kSelfLiteralId, closure_id);
     function = function_;
   }
   unsigned height = iterator->Next();
@@ -914,8 +914,8 @@

   bool is_bottommost = (0 == frame_index);
   bool is_topmost = (output_count_ - 1 == frame_index);
-  ASSERT(frame_index >= 0 && frame_index < output_count_);
-  ASSERT(output_[frame_index] == NULL);
+  CHECK(frame_index >= 0 && frame_index < output_count_);
+  CHECK_EQ(output_[frame_index], NULL);
   output_[frame_index] = output_frame;

   // The top address for the bottommost output frame can be computed from
@@ -1059,7 +1059,7 @@
     output_offset -= kPointerSize;
     DoTranslateCommand(iterator, frame_index, output_offset);
   }
-  ASSERT(0 == output_offset);
+  CHECK_EQ(0, output_offset);

   // Compute this frame's PC, state, and continuation.
   Code* non_optimized_code = function->shared()->code();
@@ -1096,7 +1096,7 @@
     } else if (bailout_type_ == SOFT) {
       continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
     } else {
-      ASSERT(bailout_type_ == EAGER);
+      CHECK_EQ(bailout_type_, EAGER);
     }
     output_frame->SetContinuation(
         reinterpret_cast<intptr_t>(continuation->entry()));
@@ -1123,8 +1123,8 @@
   output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);

   // Arguments adaptor can not be topmost or bottommost.
-  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
-  ASSERT(output_[frame_index] == NULL);
+  CHECK(frame_index > 0 && frame_index < output_count_ - 1);
+  CHECK(output_[frame_index] == NULL);
   output_[frame_index] = output_frame;

   // The top address of the frame is computed from the previous
@@ -1270,7 +1270,7 @@
     // receiver parameter through the translation. It might be encoding
     // a captured object, patch the slot address for a captured object.
     if (i == 0 && deferred_objects_.length() > deferred_object_index) {
-      ASSERT(!deferred_objects_[deferred_object_index].is_arguments());
+      CHECK(!deferred_objects_[deferred_object_index].is_arguments());
deferred_objects_[deferred_object_index].patch_slot_address(top_address);
     }
   }
@@ -1381,7 +1381,7 @@
            top_address + output_offset, output_offset, value);
   }

-  ASSERT(0 == output_offset);
+  CHECK_EQ(0, output_offset);

   intptr_t pc = reinterpret_cast<intptr_t>(
       construct_stub->instruction_start() +
@@ -1427,8 +1427,8 @@
   output_frame->SetFrameType(StackFrame::INTERNAL);

   // A frame for an accessor stub can not be the topmost or bottommost one.
-  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
-  ASSERT(output_[frame_index] == NULL);
+  CHECK(frame_index > 0 && frame_index < output_count_ - 1);
+  CHECK_EQ(output_[frame_index], NULL);
   output_[frame_index] = output_frame;

// The top address of the frame is computed from the previous frame's top and
@@ -1512,9 +1512,7 @@
   }

   // Skip receiver.
-  Translation::Opcode opcode =
-      static_cast<Translation::Opcode>(iterator->Next());
-  iterator->Skip(Translation::NumberOfOperandsFor(opcode));
+  DoTranslateObjectAndSkip(iterator);

   if (is_setter_stub_frame) {
     // The implicit return value was part of the artificial setter stub
@@ -1523,7 +1521,7 @@
     DoTranslateCommand(iterator, frame_index, output_offset);
   }

-  ASSERT(0 == output_offset);
+  CHECK_EQ(output_offset, 0);

   Smi* offset = is_setter_stub_frame ?
       isolate_->heap()->setter_stub_deopt_pc_offset() :
@@ -1573,8 +1571,8 @@
   //                                         reg = JSFunction context
   //

-  ASSERT(compiled_code_->is_crankshafted() &&
-         compiled_code_->kind() != Code::OPTIMIZED_FUNCTION);
+  CHECK(compiled_code_->is_crankshafted() &&
+        compiled_code_->kind() != Code::OPTIMIZED_FUNCTION);
   int major_key = compiled_code_->major_key();
   CodeStubInterfaceDescriptor* descriptor =
       isolate_->code_stub_interface_descriptor(major_key);
@@ -1583,7 +1581,7 @@
   // and the standard stack frame slots.  Include space for an argument
   // object to the callee and optionally the space to pass the argument
   // object to the stub failure handler.
-  ASSERT(descriptor->register_param_count_ >= 0);
+  CHECK_GE(descriptor->register_param_count_, 0);
   int height_in_bytes = kPointerSize * descriptor->register_param_count_ +
       sizeof(Arguments) + kPointerSize;
   int fixed_frame_size = StandardFrameConstants::kFixedFrameSize;
@@ -1600,7 +1598,7 @@
   FrameDescription* output_frame =
       new(output_frame_size) FrameDescription(output_frame_size, NULL);
   output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE);
-  ASSERT(frame_index == 0);
+  CHECK_EQ(frame_index, 0);
   output_[frame_index] = output_frame;

   // The top address for the output frame can be computed from the input
@@ -1658,7 +1656,7 @@
   output_frame->SetRegister(context_reg.code(), value);
   output_frame_offset -= kPointerSize;
   output_frame->SetFrameSlot(output_frame_offset, value);
-  ASSERT(reinterpret_cast<Object*>(value)->IsContext());
+  CHECK(reinterpret_cast<Object*>(value)->IsContext());
   if (trace_scope_ != NULL) {
     PrintF(trace_scope_->file(),
            "    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
@@ -1736,10 +1734,10 @@
     }
   }

-  ASSERT(0 == output_frame_offset);
+  CHECK_EQ(output_frame_offset, 0);

   if (!arg_count_known) {
-    ASSERT(arguments_length_offset >= 0);
+    CHECK_GE(arguments_length_offset, 0);
     // We know it's a smi because 1) the code stub guarantees the stack
// parameter count is in smi range, and 2) the DoTranslateCommand in the
     // parameter loop above translated that to a tagged value.
@@ -1823,7 +1821,7 @@
     Handle<JSObject> arguments =
         isolate_->factory()->NewArgumentsObject(function, length);
     Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
-    ASSERT(array->length() == length);
+    ASSERT_EQ(array->length(), length);
     arguments->set_elements(*array);
     materialized_objects_->Add(arguments);
     for (int i = 0; i < length; ++i) {
@@ -1889,7 +1887,7 @@
       default:
         PrintF(stderr,
"[couldn't handle instance type %d]\n", map->instance_type());
-        UNREACHABLE();
+        FATAL("Unsupported instance type");
     }
   }

@@ -1983,7 +1981,9 @@
       // materialize a new instance of the object if necessary. Store
       // the materialized object into the frame slot.
       Handle<Object> object = MaterializeNextHeapObject();
-      Memory::Object_at(descriptor.slot_address()) = *object;
+      if (descriptor.slot_address() != NULL) {
+        Memory::Object_at(descriptor.slot_address()) = *object;
+      }
       if (trace_scope_ != NULL) {
         if (descriptor.is_arguments()) {
           PrintF(trace_scope_->file(),
@@ -2002,8 +2002,8 @@
       }
     }

- ASSERT(materialization_object_index_ == materialized_objects_->length());
-    ASSERT(materialization_value_index_ == materialized_values_->length());
+ CHECK_EQ(materialization_object_index_, materialized_objects_->length());
+    CHECK_EQ(materialization_value_index_, materialized_values_->length());
   }

   if (prev_materialized_count_ > 0) {
@@ -2018,7 +2018,7 @@
     Address expressions_top,
     uint32_t expressions_size,
     DeoptimizedFrameInfo* info) {
-  ASSERT_EQ(DEBUGGER, bailout_type_);
+  CHECK_EQ(DEBUGGER, bailout_type_);
   Address parameters_bottom = parameters_top + parameters_size;
   Address expressions_bottom = expressions_top + expressions_size;
   for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
@@ -2074,6 +2074,73 @@
   return "heap number";
 }

+
+void Deoptimizer::DoTranslateObjectAndSkip(TranslationIterator* iterator) {
+  Translation::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: {
+      FATAL("Unexpected frame start translation opcode");
+      return;
+    }
+
+    case Translation::REGISTER:
+    case Translation::INT32_REGISTER:
+    case Translation::UINT32_REGISTER:
+    case Translation::DOUBLE_REGISTER:
+    case Translation::STACK_SLOT:
+    case Translation::INT32_STACK_SLOT:
+    case Translation::UINT32_STACK_SLOT:
+    case Translation::DOUBLE_STACK_SLOT:
+    case Translation::LITERAL: {
+ // The value is not part of any materialized object, so we can ignore it.
+      iterator->Skip(Translation::NumberOfOperandsFor(opcode));
+      return;
+    }
+
+    case Translation::DUPLICATED_OBJECT: {
+      int object_index = iterator->Next();
+      if (trace_scope_ != NULL) {
+        PrintF(trace_scope_->file(), "      skipping object ");
+        PrintF(trace_scope_->file(),
+               " ; duplicate of object #%d\n", object_index);
+      }
+      AddObjectDuplication(0, object_index);
+      return;
+    }
+
+    case Translation::ARGUMENTS_OBJECT:
+    case Translation::CAPTURED_OBJECT: {
+      int length = iterator->Next();
+      bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
+      if (trace_scope_ != NULL) {
+        PrintF(trace_scope_->file(), "    skipping object ");
+        PrintF(trace_scope_->file(),
+               " ; object (length = %d, is_args = %d)\n", length, is_args);
+      }
+
+      AddObjectStart(0, length, is_args);
+
+      // We save the object values on the side and materialize the actual
+      // object after the deoptimized frame is built.
+      int object_index = deferred_objects_.length() - 1;
+      for (int i = 0; i < length; i++) {
+        DoTranslateObject(iterator, object_index, i);
+      }
+      return;
+    }
+  }
+
+  FATAL("Unexpected translation opcode");
+}
+

 void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
                                     int object_index,
@@ -2092,7 +2159,7 @@
     case Translation::GETTER_STUB_FRAME:
     case Translation::SETTER_STUB_FRAME:
     case Translation::COMPILED_STUB_FRAME:
-      UNREACHABLE();
+      FATAL("Unexpected frame start translation opcode");
       return;

     case Translation::REGISTER: {
@@ -2332,6 +2399,8 @@
       return;
     }
   }
+
+  FATAL("Unexpected translation opcode");
 }


@@ -2353,7 +2422,7 @@
     case Translation::GETTER_STUB_FRAME:
     case Translation::SETTER_STUB_FRAME:
     case Translation::COMPILED_STUB_FRAME:
-      UNREACHABLE();
+      FATAL("Unexpected translation opcode");
       return;

     case Translation::REGISTER: {
@@ -2646,7 +2715,7 @@
   // The incoming arguments is the values for formal parameters and
   // the receiver. Every slot contains a pointer.
   if (function->IsSmi()) {
-    ASSERT(Smi::cast(function) == Smi::FromInt(StackFrame::STUB));
+    CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB));
     return 0;
   }
   unsigned arguments = function->shared()->formal_parameter_count() + 1;
@@ -2711,13 +2780,13 @@
   // cause us to emit relocation information for the external
   // references. This is fine because the deoptimizer's code section
   // isn't meant to be serialized at all.
-  ASSERT(type == EAGER || type == SOFT || type == LAZY);
+  CHECK(type == EAGER || type == SOFT || type == LAZY);
   DeoptimizerData* data = isolate->deoptimizer_data();
   int entry_count = data->deopt_entry_code_entries_[type];
   if (max_entry_id < entry_count) return;
   entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries);
   while (max_entry_id >= entry_count) entry_count *= 2;
-  ASSERT(entry_count <= Deoptimizer::kMaxNumberOfEntries);
+  CHECK(entry_count <= Deoptimizer::kMaxNumberOfEntries);

   MacroAssembler masm(isolate, NULL, 16 * KB);
   masm.set_emit_debug_code(false);
@@ -2727,8 +2796,8 @@
   ASSERT(!RelocInfo::RequiresRelocation(desc));

   MemoryChunk* chunk = data->deopt_entry_code_[type];
-  ASSERT(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
-         desc.instr_size);
+  CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
+        desc.instr_size);
   chunk->CommitArea(desc.instr_size);
   CopyBytes(chunk->area_start(), desc.buffer,
       static_cast<size_t>(desc.instr_size));
@@ -2795,15 +2864,15 @@
     case StackFrame::STUB:
       return -1;  // Minus receiver.
     default:
-      UNREACHABLE();
+      FATAL("Unexpected stack frame type");
       return 0;
   }
 }


 Object* FrameDescription::GetParameter(int index) {
-  ASSERT(index >= 0);
-  ASSERT(index < ComputeParametersCount());
+  CHECK_GE(index, 0);
+  CHECK_LT(index, ComputeParametersCount());
   // The slot indexes for incoming arguments are negative.
unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount());
   return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
@@ -2811,7 +2880,7 @@


 unsigned FrameDescription::GetExpressionCount() {
-  ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_);
+  CHECK_EQ(StackFrame::JAVA_SCRIPT, type_);
   unsigned size = GetFrameSize() - ComputeFixedSize();
   return size / kPointerSize;
 }
@@ -3013,7 +3082,7 @@
     case JS_FRAME:
       return 3;
   }
-  UNREACHABLE();
+  FATAL("Unexpected translation type");
   return -1;
 }

@@ -3123,14 +3192,13 @@
   TranslationIterator it(data->TranslationByteArray(),
                          data->TranslationIndex(deopt_index)->value());
   Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
-  ASSERT(opcode == Translation::BEGIN);
+  CHECK_EQ(opcode, Translation::BEGIN);
   it.Next();  // Drop frame count.

   stack_frame_id_ = frame->fp();

   int jsframe_count = it.Next();
-  USE(jsframe_count);
-  ASSERT(jsframe_count > inlined_jsframe_index);
+  CHECK_GT(jsframe_count, inlined_jsframe_index);
   int jsframes_to_skip = inlined_jsframe_index;
int number_of_slots = -1; // Number of slots inside our frame (yet unknown)
   bool should_deopt = false;
@@ -3139,7 +3207,7 @@
     bool processed = false;
     if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) {
       if (jsframes_to_skip == 0) {
-        ASSERT(Translation::NumberOfOperandsFor(opcode) == 2);
+        CHECK_EQ(Translation::NumberOfOperandsFor(opcode), 2);

         it.Skip(1);  // literal id
         int height = it.Next();
@@ -3186,7 +3254,7 @@
         // the nested slots of captured objects
         number_of_slots--;
         SlotRef& slot = slot_refs_.last();
-        ASSERT(slot.Representation() != SlotRef::ARGUMENTS_OBJECT);
+        CHECK_NE(slot.Representation(), SlotRef::ARGUMENTS_OBJECT);
         number_of_slots += slot.GetChildrenCount();
         if (slot.Representation() == SlotRef::DEFERRED_OBJECT ||
             slot.Representation() == SlotRef::DUPLICATE_OBJECT) {
@@ -3260,7 +3328,7 @@
   while (current_slot_ < first_slot_index_) {
     GetNext(isolate, 0);
   }
-  ASSERT(current_slot_ == first_slot_index_);
+  CHECK_EQ(current_slot_, first_slot_index_);
 }


@@ -3322,8 +3390,8 @@
     }
     case SlotRef::DEFERRED_OBJECT: {
       int length = slot.GetChildrenCount();
- ASSERT(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL || - slot_refs_[current_slot_].Representation() == SlotRef::TAGGED); + CHECK(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL ||
+            slot_refs_[current_slot_].Representation() == SlotRef::TAGGED);

       int object_index = materialized_objects_.length();
       if (object_index <  prev_materialized_count_) {
@@ -3384,6 +3452,7 @@
           break;
       }
       UNREACHABLE();
+      break;
     }

     case SlotRef::DUPLICATE_OBJECT: {
@@ -3404,7 +3473,7 @@

 void SlotRefValueBuilder::Finish(Isolate* isolate) {
   // We should have processed all the slots
-  ASSERT(slot_refs_.length() == current_slot_);
+  CHECK_EQ(slot_refs_.length(), current_slot_);

   if (materialized_objects_.length() > prev_materialized_count_) {
     // We have materialized some new objects, so we have to store them
@@ -3425,7 +3494,7 @@
     return Handle<FixedArray>::null();
   }
   Handle<FixedArray> array = GetStackEntries();
-  ASSERT(array->length() > index);
+  CHECK_GT(array->length(), index);
   return Handle<FixedArray>::cast(Handle<Object>(array->get(index),
                                                  isolate()));
 }
@@ -3446,11 +3515,11 @@

 void MaterializedObjectStore::Remove(Address fp) {
   int index = StackIdToIndex(fp);
-  ASSERT(index >= 0);
+  CHECK_GE(index, 0);

   frame_fps_.Remove(index);
   Handle<FixedArray> array = GetStackEntries();
-  ASSERT(array->length() > index);
+  CHECK_LT(index, array->length());
   for (int i = index; i < frame_fps_.length(); i++) {
     array->set(i, array->get(i + 1));
   }
@@ -3517,7 +3586,7 @@

   if (has_arguments_adaptor) {
     output_frame = deoptimizer->output_[frame_index - 1];
-    ASSERT(output_frame->GetFrameType() == StackFrame::ARGUMENTS_ADAPTOR);
+    CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR);
   }

   parameters_count_ = output_frame->ComputeParametersCount();
=======================================
--- /branches/bleeding_edge/src/deoptimizer.h   Fri Apr 25 11:00:37 2014 UTC
+++ /branches/bleeding_edge/src/deoptimizer.h   Fri Apr 25 12:58:15 2014 UTC
@@ -326,14 +326,21 @@
   void DoComputeCompiledStubFrame(TranslationIterator* iterator,
                                   int frame_index);

+  // Translate object, store the result into an auxiliary array
+  // (deferred_objects_tagged_values_).
   void DoTranslateObject(TranslationIterator* iterator,
                          int object_index,
                          int field_index);

+  // Translate value, store the result into the given frame slot.
   void DoTranslateCommand(TranslationIterator* iterator,
                           int frame_index,
                           unsigned output_offset);

+  // Translate object, do not store the result anywhere (but do update
+  // the deferred materialization array).
+  void DoTranslateObjectAndSkip(TranslationIterator* iterator);
+
   unsigned ComputeInputFrameSize() const;
   unsigned ComputeFixedSize(JSFunction* function) const;

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to