Revision: 6584
Author: [email protected]
Date: Wed Feb  2 07:49:30 2011
Log: Merge r6576 and r6581 from bleeding_edge to 3.0 branch.

This is a partial fix for V8 issue 1079, affecting use of the arguments
property of optimized functions.

Review URL: http://codereview.chromium.org/6334055
http://code.google.com/p/v8/source/detail?r=6584

Added:
 /branches/3.0/test/mjsunit/regress/regress-1079.js
Modified:
 /branches/3.0/src/accessors.cc
 /branches/3.0/src/arm/deoptimizer-arm.cc
 /branches/3.0/src/arm/lithium-arm.cc
 /branches/3.0/src/arm/lithium-arm.h
 /branches/3.0/src/arm/lithium-codegen-arm.cc
 /branches/3.0/src/deoptimizer.h
 /branches/3.0/src/hydrogen-instructions.h
 /branches/3.0/src/hydrogen.cc
 /branches/3.0/src/ia32/deoptimizer-ia32.cc
 /branches/3.0/src/ia32/lithium-codegen-ia32.cc
 /branches/3.0/src/ia32/lithium-ia32.cc
 /branches/3.0/src/ia32/lithium-ia32.h
 /branches/3.0/src/safepoint-table.cc
 /branches/3.0/src/safepoint-table.h
 /branches/3.0/src/x64/deoptimizer-x64.cc
 /branches/3.0/src/x64/lithium-codegen-x64.cc
 /branches/3.0/src/x64/lithium-x64.cc
 /branches/3.0/src/x64/lithium-x64.h
 /branches/3.0/test/cctest/cctest.status

=======================================
--- /dev/null
+++ /branches/3.0/test/mjsunit/regress/regress-1079.js Wed Feb 2 07:49:30 2011
@@ -0,0 +1,45 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Getting the arguments property of an optimized function should not crash, +// even if called through our optimized version of Function.prototype.apply.
+
+function optimized() {
+  return unoptimized.apply(null, arguments);
+}
+
+// It's not crucial that this is unoptimized.
+function unoptimized() {
+  with ({}) {
+    return optimized.arguments;
+  }
+}
+
+for (var i = 0; i < 100000; ++i) {
+  assertEquals(3, optimized(1, 2, 3).length);
+}
+
=======================================
--- /branches/3.0/src/accessors.cc      Mon Jan 10 00:15:37 2011
+++ /branches/3.0/src/accessors.cc      Wed Feb  2 07:49:30 2011
@@ -675,46 +675,36 @@
                                            int inlined_frame_index,
                                            Vector<SlotRef>* args_slots) {
   AssertNoAllocation no_gc;
-
   int deopt_index = AstNode::kNoNumber;
-
   DeoptimizationInputData* data =
static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
-
   TranslationIterator it(data->TranslationByteArray(),
                          data->TranslationIndex(deopt_index)->value());
-
   Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
   ASSERT(opcode == Translation::BEGIN);
   int frame_count = it.Next();
-
   USE(frame_count);
   ASSERT(frame_count > inlined_frame_index);
-
   int frames_to_skip = inlined_frame_index;
   while (true) {
     opcode = static_cast<Translation::Opcode>(it.Next());
-
     // Skip over operands to advance to the next opcode.
     it.Skip(Translation::NumberOfOperandsFor(opcode));
-
     if (opcode == Translation::FRAME) {
       if (frames_to_skip == 0) {
-        // We reached frame corresponding to inlined function in question.
-        // Process translation commands for arguments.
-
-        // Skip translation command for receiver.
+        // We reached the frame corresponding to the inlined function
+        // in question.  Process the translation commands for the
+        // arguments.
+        //
+        // Skip the translation command for the receiver.
         it.Skip(Translation::NumberOfOperandsFor(
             static_cast<Translation::Opcode>(it.Next())));
-
         // Compute slots for arguments.
         for (int i = 0; i < args_slots->length(); ++i) {
           (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame);
         }
-
         return;
       }
-
       frames_to_skip--;
     }
   }
@@ -727,16 +717,11 @@
     JavaScriptFrame* frame,
     Handle<JSFunction> inlined_function,
     int inlined_frame_index) {
-
   int args_count = inlined_function->shared()->formal_parameter_count();
-
   ScopedVector<SlotRef> args_slots(args_count);
-
   ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots);
-
   Handle<JSObject> arguments =
       Factory::NewArgumentsObject(inlined_function, args_count);
-
   Handle<FixedArray> array = Factory::NewFixedArray(args_count);
   for (int i = 0; i < args_count; ++i) {
     Handle<Object> value = args_slots[i].GetValue();
@@ -766,39 +751,43 @@
       if (functions[i] != *function) continue;

       if (i > 0) {
-        // Function in question was inlined.
+ // The function in question was inlined. Inlined functions have the + // correct number of arguments and no allocated arguments object, so
+        // we can construct a fresh one by interpreting the function's
+        // deoptimization input data.
return ConstructArgumentsObjectForInlinedFunction(frame, function, i);
-      } else {
+      }
+
+      if (!frame->is_optimized()) {
         // If there is an arguments variable in the stack, we return that.
-        int index = function->shared()->scope_info()->
-            StackSlotIndex(Heap::arguments_symbol());
+        Handle<SerializedScopeInfo> info(function->shared()->scope_info());
+        int index = info->StackSlotIndex(Heap::arguments_symbol());
         if (index >= 0) {
-          Handle<Object> arguments =
-              Handle<Object>(frame->GetExpression(index));
+          Handle<Object> arguments(frame->GetExpression(index));
           if (!arguments->IsArgumentsMarker()) return *arguments;
         }
-
-        // If there isn't an arguments variable in the stack, we need to
-        // find the frame that holds the actual arguments passed to the
-        // function on the stack.
-        it.AdvanceToArgumentsFrame();
-        frame = it.frame();
-
-        // Get the number of arguments and construct an arguments object
-        // mirror for the right frame.
-        const int length = frame->GetProvidedParametersCount();
-        Handle<JSObject> arguments = Factory::NewArgumentsObject(function,
-                                                                 length);
-        Handle<FixedArray> array = Factory::NewFixedArray(length);
-
-        // Copy the parameters to the arguments object.
-        ASSERT(array->length() == length);
- for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
-        arguments->set_elements(*array);
-
-        // Return the freshly allocated arguments object.
-        return *arguments;
-      }
+      }
+
+      // If there is no arguments variable in the stack or we have an
+      // optimized frame, we find the frame that holds the actual arguments
+      // passed to the function.
+      it.AdvanceToArgumentsFrame();
+      frame = it.frame();
+
+      // Get the number of arguments and construct an arguments object
+      // mirror for the right frame.
+      const int length = frame->GetProvidedParametersCount();
+      Handle<JSObject> arguments = Factory::NewArgumentsObject(function,
+                                                               length);
+      Handle<FixedArray> array = Factory::NewFixedArray(length);
+
+      // Copy the parameters to the arguments object.
+      ASSERT(array->length() == length);
+ for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
+      arguments->set_elements(*array);
+
+      // Return the freshly allocated arguments object.
+      return *arguments;
     }
     functions.Rewind(0);
   }
=======================================
--- /branches/3.0/src/arm/deoptimizer-arm.cc    Tue Jan 25 06:06:47 2011
+++ /branches/3.0/src/arm/deoptimizer-arm.cc    Wed Feb  2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -37,6 +37,14 @@

 int Deoptimizer::table_entry_size_ = 16;

+
+int Deoptimizer::patch_size() {
+  const int kCallInstructionSizeInWords = 3;
+  return kCallInstructionSizeInWords * Assembler::kInstrSize;
+}
+
+
+
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
   AssertNoAllocation no_allocation;

@@ -51,6 +59,8 @@

   // For each return after a safepoint insert an absolute call to the
   // corresponding deoptimization entry.
+  ASSERT(patch_size() % Assembler::kInstrSize == 0);
+  int call_size_in_words = patch_size() / Assembler::kInstrSize;
   unsigned last_pc_offset = 0;
   SafepointTable table(function->code());
   for (unsigned i = 0; i < table.length(); i++) {
@@ -73,14 +83,13 @@
 #endif
     last_pc_offset = pc_offset;
     if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
-      const int kCallInstructionSizeInWords = 3;
- CodePatcher patcher(code->instruction_start() + pc_offset + gap_code_size,
-                          kCallInstructionSizeInWords);
+      last_pc_offset += gap_code_size;
+      CodePatcher patcher(code->instruction_start() + last_pc_offset,
+                          call_size_in_words);
       Address deoptimization_entry = Deoptimizer::GetDeoptimizationEntry(
           deoptimization_index, Deoptimizer::LAZY);
       patcher.masm()->Call(deoptimization_entry, RelocInfo::NONE);
-      last_pc_offset +=
- gap_code_size + kCallInstructionSizeInWords * Assembler::kInstrSize;
+      last_pc_offset += patch_size();
     }
   }

=======================================
--- /branches/3.0/src/arm/lithium-arm.cc        Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/arm/lithium-arm.cc        Wed Feb  2 07:49:30 2011
@@ -655,16 +655,16 @@

LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
     LInstruction* instr, int ast_id) {
-  ASSERT(instructions_pending_deoptimization_environment_ == NULL);
+  ASSERT(instruction_pending_deoptimization_environment_ == NULL);
   ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
-  instructions_pending_deoptimization_environment_ = instr;
+  instruction_pending_deoptimization_environment_ = instr;
   pending_deoptimization_ast_id_ = ast_id;
   return instr;
 }


 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
-  instructions_pending_deoptimization_environment_ = NULL;
+  instruction_pending_deoptimization_environment_ = NULL;
   pending_deoptimization_ast_id_ = AstNode::kNoNumber;
 }

@@ -1461,6 +1461,13 @@
return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
                                             UseRegister(instr->length())));
 }
+
+
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}


 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
@@ -1837,7 +1844,7 @@
   if (pending_deoptimization_ast_id_ == instr->ast_id()) {
     LInstruction* result = new LLazyBailout;
     result = AssignEnvironment(result);
-    instructions_pending_deoptimization_environment_->
+    instruction_pending_deoptimization_environment_->
         set_deoptimization_environment(result->environment());
     ClearInstructionPendingDeoptimizationEnvironment();
     return result;
=======================================
--- /branches/3.0/src/arm/lithium-arm.h Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/arm/lithium-arm.h Wed Feb  2 07:49:30 2011
@@ -1855,7 +1855,7 @@
         argument_count_(0),
         allocator_(allocator),
         position_(RelocInfo::kNoPosition),
-        instructions_pending_deoptimization_environment_(NULL),
+        instruction_pending_deoptimization_environment_(NULL),
         pending_deoptimization_ast_id_(AstNode::kNoNumber) { }

   // Build the sequence for the graph.
@@ -1989,7 +1989,7 @@
   int argument_count_;
   LAllocator* allocator_;
   int position_;
-  LInstruction* instructions_pending_deoptimization_environment_;
+  LInstruction* instruction_pending_deoptimization_environment_;
   int pending_deoptimization_ast_id_;

   DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
=======================================
--- /branches/3.0/src/arm/lithium-codegen-arm.cc        Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/arm/lithium-codegen-arm.cc        Wed Feb  2 07:49:30 2011
@@ -562,17 +562,11 @@
 void LCodeGen::CallCode(Handle<Code> code,
                         RelocInfo::Mode mode,
                         LInstruction* instr) {
-  if (instr != NULL) {
-    LPointerMap* pointers = instr->pointer_map();
-    RecordPosition(pointers->position());
-    __ Call(code, mode);
-    RegisterLazyDeoptimization(instr);
-  } else {
-    LPointerMap no_pointers(0);
-    RecordPosition(no_pointers.position());
-    __ Call(code, mode);
-    RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
-  }
+  ASSERT(instr != NULL);
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+  __ Call(code, mode);
+  RegisterLazyDeoptimization(instr);
 }


@@ -585,15 +579,7 @@
   RecordPosition(pointers->position());

   __ CallRuntime(function, num_arguments);
-  // Runtime calls to Throw are not supposed to ever return at the
-  // call site, so don't register lazy deoptimization for these. We do
-  // however have to record a safepoint since throwing exceptions can
-  // cause garbage collections.
-  if (!instr->IsThrow()) {
-    RegisterLazyDeoptimization(instr);
-  } else {
- RecordSafepoint(instr->pointer_map(), Safepoint::kNoDeoptimizationIndex);
-  }
+  RegisterLazyDeoptimization(instr);
 }


@@ -2450,12 +2436,17 @@
   __ b(ne, &loop);

   __ bind(&invoke);
-  // Invoke the function. The number of arguments is stored in receiver
-  // which is r0, as expected by InvokeFunction.
-  v8::internal::ParameterCount actual(receiver);
+  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+  LPointerMap* pointers = instr->pointer_map();
+  LEnvironment* env = instr->deoptimization_environment();
+  RecordPosition(pointers->position());
+  RegisterEnvironmentForDeoptimization(env);
   SafepointGenerator safepoint_generator(this,
-                                         instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
+                                         pointers,
+                                         env->deoptimization_index());
+  // The number of arguments is stored in receiver which is r0, as expected
+  // by InvokeFunction.
+  v8::internal::ParameterCount actual(receiver);
   __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
 }

@@ -3667,10 +3658,14 @@
   Register object = ToRegister(instr->object());
   Register key = ToRegister(instr->key());
   __ Push(object, key);
-  RecordPosition(instr->pointer_map()->position());
+  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+  LPointerMap* pointers = instr->pointer_map();
+  LEnvironment* env = instr->deoptimization_environment();
+  RecordPosition(pointers->position());
+  RegisterEnvironmentForDeoptimization(env);
   SafepointGenerator safepoint_generator(this,
-                                         instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
+                                         pointers,
+                                         env->deoptimization_index());
   __ InvokeBuiltin(Builtins::DELETE, CALL_JS, &safepoint_generator);
 }

=======================================
--- /branches/3.0/src/deoptimizer.h     Tue Jan 25 06:06:47 2011
+++ /branches/3.0/src/deoptimizer.h     Wed Feb  2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -128,6 +128,9 @@

static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor* visitor);

+  // The size in bytes of the code required at a lazy deopt patch site.
+  static int patch_size();
+
   // Patch all stack guard checks in the unoptimized code to
   // unconditionally call replacement_code.
   static void PatchStackCheckCode(Code* unoptimized_code,
=======================================
--- /branches/3.0/src/hydrogen-instructions.h   Wed Feb  2 02:08:20 2011
+++ /branches/3.0/src/hydrogen-instructions.h   Wed Feb  2 07:49:30 2011
@@ -64,6 +64,7 @@


 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
+  V(AbnormalExit)                              \
   V(AccessArgumentsAt)                         \
   V(Add)                                       \
   V(ApplyArguments)                            \
@@ -834,12 +835,11 @@
 };


-class HThrow: public HUnaryControlInstruction {
+class HAbnormalExit: public HControlInstruction {
  public:
-  explicit HThrow(HValue* value)
-      : HUnaryControlInstruction(value, NULL, NULL) { }
-
-  DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
+  HAbnormalExit() : HControlInstruction(NULL, NULL) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
 };


@@ -866,6 +866,20 @@
 };


+class HThrow: public HUnaryOperation {
+ public:
+  explicit HThrow(HValue* value) : HUnaryOperation(value) {
+    SetAllSideEffects();
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
+};
+
+
 class HChange: public HUnaryOperation {
  public:
   HChange(HValue* value,
@@ -989,7 +1003,7 @@
  public:
   HStackCheck() { }

-  DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
+  DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
 };


@@ -1831,6 +1845,7 @@
     SetOperandAt(1, receiver);
     SetOperandAt(2, length);
     SetOperandAt(3, elements);
+    SetAllSideEffects();
   }

   virtual Representation RequiredInputRepresentation(int index) const {
@@ -1850,8 +1865,6 @@

   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")

-
-
  protected:
   virtual void InternalSetOperandAt(int index, HValue* value) {
     operands_[index] = value;
=======================================
--- /branches/3.0/src/hydrogen.cc       Mon Jan 31 05:20:57 2011
+++ /branches/3.0/src/hydrogen.cc       Wed Feb  2 07:49:30 2011
@@ -3556,9 +3556,11 @@
   VISIT_FOR_VALUE(expr->exception());

   HValue* value = environment()->Pop();
-  HControlInstruction* instr = new HThrow(value);
+  HThrow* instr = new HThrow(value);
   instr->set_position(expr->position());
-  current_subgraph_->FinishExit(instr);
+  AddInstruction(instr);
+  AddSimulate(expr->id());
+  current_subgraph_->FinishExit(new HAbnormalExit);
 }


=======================================
--- /branches/3.0/src/ia32/deoptimizer-ia32.cc  Wed Feb  2 02:24:23 2011
+++ /branches/3.0/src/ia32/deoptimizer-ia32.cc  Wed Feb  2 07:49:30 2011
@@ -37,9 +37,14 @@
 namespace v8 {
 namespace internal {

-
 int Deoptimizer::table_entry_size_ = 10;

+
+int Deoptimizer::patch_size() {
+  return Assembler::kCallInstructionLength;
+}
+
+
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
   AssertNoAllocation no_allocation;

@@ -77,11 +82,12 @@
 #endif
     last_pc_offset = pc_offset;
     if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- Address call_pc = code->instruction_start() + pc_offset + gap_code_size;
-      CodePatcher patcher(call_pc, Assembler::kCallInstructionLength);
+      last_pc_offset += gap_code_size;
+      Address call_pc = code->instruction_start() + last_pc_offset;
+      CodePatcher patcher(call_pc, patch_size());
       Address entry = GetDeoptimizationEntry(deoptimization_index, LAZY);
       patcher.masm()->call(entry, RelocInfo::NONE);
-      last_pc_offset += gap_code_size + Assembler::kCallInstructionLength;
+      last_pc_offset += patch_size();
       RelocInfo rinfo(call_pc + 1, RelocInfo::RUNTIME_ENTRY,
                       reinterpret_cast<intptr_t>(entry));
       reloc_info_writer.Write(&rinfo);
=======================================
--- /branches/3.0/src/ia32/lithium-codegen-ia32.cc      Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/ia32/lithium-codegen-ia32.cc      Wed Feb  2 07:49:30 2011
@@ -37,6 +37,8 @@
 namespace internal {


+// When invoking builtins, we need to record the safepoint in the middle of
+// the invoke instruction sequence generated by the macro assembler.
 class SafepointGenerator : public PostCallGenerator {
  public:
   SafepointGenerator(LCodeGen* codegen,
@@ -366,17 +368,11 @@
 void LCodeGen::CallCode(Handle<Code> code,
                         RelocInfo::Mode mode,
                         LInstruction* instr) {
-  if (instr != NULL) {
-    LPointerMap* pointers = instr->pointer_map();
-    RecordPosition(pointers->position());
-    __ call(code, mode);
-    RegisterLazyDeoptimization(instr);
-  } else {
-    LPointerMap no_pointers(0);
-    RecordPosition(no_pointers.position());
-    __ call(code, mode);
-    RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
-  }
+  ASSERT(instr != NULL);
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+  __ call(code, mode);
+  RegisterLazyDeoptimization(instr);

   // Signal that we don't inline smi code before these stubs in the
   // optimizing code generator.
@@ -391,22 +387,12 @@
                            int num_arguments,
                            LInstruction* instr) {
   ASSERT(instr != NULL);
+  ASSERT(instr->HasPointerMap());
   LPointerMap* pointers = instr->pointer_map();
-  ASSERT(pointers != NULL);
   RecordPosition(pointers->position());

   __ CallRuntime(function, num_arguments);
-  // Runtime calls to Throw are not supposed to ever return at the
-  // call site, so don't register lazy deoptimization for these. We do
-  // however have to record a safepoint since throwing exceptions can
-  // cause garbage collections.
-  // BUG(3243555): register a lazy deoptimization point at throw. We need
-  // it to be able to inline functions containing a throw statement.
-  if (!instr->IsThrow()) {
-    RegisterLazyDeoptimization(instr);
-  } else {
- RecordSafepoint(instr->pointer_map(), Safepoint::kNoDeoptimizationIndex);
-  }
+  RegisterLazyDeoptimization(instr);
 }


@@ -2145,11 +2131,16 @@

   // Invoke the function.
   __ bind(&invoke);
+  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+  LPointerMap* pointers = instr->pointer_map();
+  LEnvironment* env = instr->deoptimization_environment();
+  RecordPosition(pointers->position());
+  RegisterEnvironmentForDeoptimization(env);
+  SafepointGenerator safepoint_generator(this,
+                                         pointers,
+                                         env->deoptimization_index());
   ASSERT(receiver.is(eax));
   v8::internal::ParameterCount actual(eax);
-  SafepointGenerator safepoint_generator(this,
-                                         instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
   __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator);
 }

@@ -3575,10 +3566,14 @@
   } else {
     __ push(ToOperand(key));
   }
-  RecordPosition(instr->pointer_map()->position());
+  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+  LPointerMap* pointers = instr->pointer_map();
+  LEnvironment* env = instr->deoptimization_environment();
+  RecordPosition(pointers->position());
+  RegisterEnvironmentForDeoptimization(env);
   SafepointGenerator safepoint_generator(this,
-                                         instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
+                                         pointers,
+                                         env->deoptimization_index());
   __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
 }

=======================================
--- /branches/3.0/src/ia32/lithium-ia32.cc      Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/ia32/lithium-ia32.cc      Wed Feb  2 07:49:30 2011
@@ -658,16 +658,16 @@

LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
     LInstruction* instr, int ast_id) {
-  ASSERT(instructions_pending_deoptimization_environment_ == NULL);
+  ASSERT(instruction_pending_deoptimization_environment_ == NULL);
   ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
-  instructions_pending_deoptimization_environment_ = instr;
+  instruction_pending_deoptimization_environment_ = instr;
   pending_deoptimization_ast_id_ = ast_id;
   return instr;
 }


 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
-  instructions_pending_deoptimization_environment_ = NULL;
+  instruction_pending_deoptimization_environment_ = NULL;
   pending_deoptimization_ast_id_ = AstNode::kNoNumber;
 }

@@ -1505,6 +1505,13 @@
return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
                                             Use(instr->length())));
 }
+
+
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}


 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
@@ -1875,10 +1882,11 @@

   // If there is an instruction pending deoptimization environment create a
   // lazy bailout instruction to capture the environment.
-  if (pending_deoptimization_ast_id_ == instr->ast_id()) {
+  if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
+    ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
     LLazyBailout* lazy_bailout = new LLazyBailout;
     LInstruction* result = AssignEnvironment(lazy_bailout);
-    instructions_pending_deoptimization_environment_->
+    instruction_pending_deoptimization_environment_->
         set_deoptimization_environment(result->environment());
     ClearInstructionPendingDeoptimizationEnvironment();
     return result;
=======================================
--- /branches/3.0/src/ia32/lithium-ia32.h       Wed Jan 26 00:23:03 2011
+++ /branches/3.0/src/ia32/lithium-ia32.h       Wed Feb  2 07:49:30 2011
@@ -1881,7 +1881,7 @@
         argument_count_(0),
         allocator_(allocator),
         position_(RelocInfo::kNoPosition),
-        instructions_pending_deoptimization_environment_(NULL),
+        instruction_pending_deoptimization_environment_(NULL),
         pending_deoptimization_ast_id_(AstNode::kNoNumber) { }

   // Build the sequence for the graph.
@@ -2015,7 +2015,7 @@
   int argument_count_;
   LAllocator* allocator_;
   int position_;
-  LInstruction* instructions_pending_deoptimization_environment_;
+  LInstruction* instruction_pending_deoptimization_environment_;
   int pending_deoptimization_ast_id_;

   DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
=======================================
--- /branches/3.0/src/safepoint-table.cc        Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/safepoint-table.cc        Wed Feb  2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -27,6 +27,7 @@

 #include "safepoint-table.h"

+#include "deoptimizer.h"
 #include "disasm.h"
 #include "macro-assembler.h"

@@ -144,6 +145,14 @@


void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) { + // For lazy deoptimization we need space to patch a call after every call.
+  // Ensure there is always space for such patching, even if the code ends
+  // in a call.
+  int target_offset = assembler->pc_offset() + Deoptimizer::patch_size();
+  while (assembler->pc_offset() < target_offset) {
+    assembler->nop();
+  }
+
   // Make sure the safepoint table is properly aligned. Pad with nops.
   assembler->Align(kIntSize);
   assembler->RecordComment(";;; Safepoint table.");
=======================================
--- /branches/3.0/src/safepoint-table.h Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/safepoint-table.h Wed Feb  2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -215,11 +215,10 @@
   unsigned GetCodeOffset() const;

   // Define a new safepoint for the current position in the body.
-  Safepoint DefineSafepoint(
-      Assembler* assembler,
-      Safepoint::Kind kind,
-      int arguments,
-      int deoptimization_index = Safepoint::kNoDeoptimizationIndex);
+  Safepoint DefineSafepoint(Assembler* assembler,
+                            Safepoint::Kind kind,
+                            int arguments,
+                            int deoptimization_index);

// Update the last safepoint with the size of the code generated for the gap
   // following it.
=======================================
--- /branches/3.0/src/x64/deoptimizer-x64.cc    Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/x64/deoptimizer-x64.cc    Wed Feb  2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -40,6 +40,12 @@

 int Deoptimizer::table_entry_size_ = 10;

+
+int Deoptimizer::patch_size() {
+  return Assembler::kCallInstructionLength;
+}
+
+
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
   AssertNoAllocation no_allocation;

@@ -72,12 +78,12 @@
 #endif
     last_pc_offset = pc_offset;
     if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
-      CodePatcher patcher(
-          code->instruction_start() + pc_offset + gap_code_size,
-          Assembler::kCallInstructionLength);
+      last_pc_offset += gap_code_size;
+      CodePatcher patcher(code->instruction_start() + last_pc_offset,
+                          patch_size());
patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY),
                            RelocInfo::NONE);
-      last_pc_offset += gap_code_size + Assembler::kCallInstructionLength;
+      last_pc_offset += patch_size();
     }
   }
 #ifdef DEBUG
=======================================
--- /branches/3.0/src/x64/lithium-codegen-x64.cc        Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/x64/lithium-codegen-x64.cc        Wed Feb  2 07:49:30 2011
@@ -346,17 +346,11 @@
 void LCodeGen::CallCode(Handle<Code> code,
                         RelocInfo::Mode mode,
                         LInstruction* instr) {
-  if (instr != NULL) {
-    LPointerMap* pointers = instr->pointer_map();
-    RecordPosition(pointers->position());
-    __ call(code, mode);
-    RegisterLazyDeoptimization(instr);
-  } else {
-    LPointerMap no_pointers(0);
-    RecordPosition(no_pointers.position());
-    __ call(code, mode);
-    RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
-  }
+  ASSERT(instr != NULL);
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+  __ call(code, mode);
+  RegisterLazyDeoptimization(instr);

   // Signal that we don't inline smi code before these stubs in the
   // optimizing code generator.
=======================================
--- /branches/3.0/src/x64/lithium-x64.cc        Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/x64/lithium-x64.cc        Wed Feb  2 07:49:30 2011
@@ -655,14 +655,14 @@
     LInstruction* instr, int ast_id) {
   ASSERT(instructions_pending_deoptimization_environment_ == NULL);
   ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
-  instructions_pending_deoptimization_environment_ = instr;
+  instruction_pending_deoptimization_environment_ = instr;
   pending_deoptimization_ast_id_ = ast_id;
   return instr;
 }


 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
-  instructions_pending_deoptimization_environment_ = NULL;
+  instruction_pending_deoptimization_environment_ = NULL;
   pending_deoptimization_ast_id_ = AstNode::kNoNumber;
 }

@@ -1326,6 +1326,13 @@
   Abort("Unimplemented: %s", "DoBoundsCheck");
   return NULL;
 }
+
+
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}


 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
@@ -1663,7 +1670,7 @@
   if (pending_deoptimization_ast_id_ == instr->ast_id()) {
     LLazyBailout* lazy_bailout = new LLazyBailout;
     LInstruction* result = AssignEnvironment(lazy_bailout);
-    instructions_pending_deoptimization_environment_->
+    instruction_pending_deoptimization_environment_->
         set_deoptimization_environment(result->environment());
     ClearInstructionPendingDeoptimizationEnvironment();
     return result;
=======================================
--- /branches/3.0/src/x64/lithium-x64.h Wed Jan 26 00:23:03 2011
+++ /branches/3.0/src/x64/lithium-x64.h Wed Feb  2 07:49:30 2011
@@ -1847,7 +1847,7 @@
         argument_count_(0),
         allocator_(allocator),
         position_(RelocInfo::kNoPosition),
-        instructions_pending_deoptimization_environment_(NULL),
+        instruction_pending_deoptimization_environment_(NULL),
         pending_deoptimization_ast_id_(AstNode::kNoNumber) { }

   // Build the sequence for the graph.
@@ -1981,7 +1981,7 @@
   int argument_count_;
   LAllocator* allocator_;
   int position_;
-  LInstruction* instructions_pending_deoptimization_environment_;
+  LInstruction* instruction_pending_deoptimization_environment_;
   int pending_deoptimization_ast_id_;

   DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
=======================================
--- /branches/3.0/test/cctest/cctest.status     Fri Jan 28 00:04:38 2011
+++ /branches/3.0/test/cctest/cctest.status     Wed Feb  2 07:49:30 2011
@@ -51,9 +51,6 @@
 test-serialize/TestThatAlwaysFails: FAIL
 test-serialize/DependentTestThatAlwaysFails: FAIL

-# BUG(1079)
-test-api/CaptureStackTraceForUncaughtException: PASS || FAIL
-
##############################################################################
 [ $arch == x64 ]

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to