Revision: 6576
Author: [email protected]
Date: Wed Feb  2 05:55:29 2011
Log: Partial fix for V8 issue 1079.

Record a safepoint with a deoptimization id for throw in optimized code.  We
don't seem to much care what the AST ID is because we will not be using it
for lazy deoptimization (throw doesn't return to the point of throw).  For
hygiene we use the actual ID of the throw expression.  Throw is no longer a
control-flow instruction, but it's followed by an unconditional abnormal
exit.  This is required to insert a simulate between the throw and the exit.

Make our optimized treatment of Function.prototype.apply act like a call and
have side effects.  This ensures that it will get a lazy deoptimization
environment.  Use that deoptimization ID in the safepoint for the call.

Deleting a property was also missing a deoptimization ID, though there was a
deoptimization environment assigned to the instruction.  Record the
environment and use the deoptimization ID at the safepoint.

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

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

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-1079.js Wed Feb 2 05:55:29 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) {
+  optimized(1, 2, 3)
+}
+
=======================================
--- /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Wed Feb 2 03:58:24 2011 +++ /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Wed Feb 2 05:55:29 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/bleeding_edge/src/arm/lithium-arm.cc      Thu Jan 27 00:35:39 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Wed Feb  2 05:55:29 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/bleeding_edge/src/arm/lithium-arm.h       Thu Jan 27 00:35:39 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Wed Feb  2 05:55:29 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/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Feb 1 08:38:25 2011 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Feb 2 05:55:29 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);
 }


@@ -2446,12 +2432,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);
 }

@@ -3666,10 +3657,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/bleeding_edge/src/deoptimizer.h   Wed Feb  2 03:58:24 2011
+++ /branches/bleeding_edge/src/deoptimizer.h   Wed Feb  2 05:55:29 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/bleeding_edge/src/hydrogen-instructions.h Wed Feb 2 01:52:57 2011 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Feb 2 05:55:29 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/bleeding_edge/src/hydrogen.cc     Mon Jan 31 04:36:54 2011
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Feb  2 05:55:29 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/bleeding_edge/src/ia32/deoptimizer-ia32.cc Wed Feb 2 03:58:24 2011 +++ /branches/bleeding_edge/src/ia32/deoptimizer-ia32.cc Wed Feb 2 05:55:29 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/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Feb 2 04:54:58 2011 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Feb 2 05:55:29 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);
 }

@@ -3577,10 +3568,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/bleeding_edge/src/ia32/lithium-ia32.cc Thu Jan 27 00:35:39 2011 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Feb 2 05:55:29 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/bleeding_edge/src/ia32/lithium-ia32.h     Wed Jan 26 00:03:48 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Feb  2 05:55:29 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/bleeding_edge/src/safepoint-table.cc      Wed Jan 26 12:48:48 2011
+++ /branches/bleeding_edge/src/safepoint-table.cc      Wed Feb  2 05:55:29 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/bleeding_edge/src/safepoint-table.h       Wed Jan 26 12:48:48 2011
+++ /branches/bleeding_edge/src/safepoint-table.h       Wed Feb  2 05:55:29 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/bleeding_edge/src/x64/deoptimizer-x64.cc Wed Feb 2 03:58:24 2011 +++ /branches/bleeding_edge/src/x64/deoptimizer-x64.cc Wed Feb 2 05:55:29 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/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Jan 27 08:41:43 2011 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Feb 2 05:55:29 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/bleeding_edge/src/x64/lithium-x64.cc      Thu Jan 27 08:41:43 2011
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Wed Feb  2 05:55:29 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/bleeding_edge/src/x64/lithium-x64.h       Wed Jan 26 00:03:48 2011
+++ /branches/bleeding_edge/src/x64/lithium-x64.h       Wed Feb  2 05:55:29 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/bleeding_edge/test/cctest/cctest.status Tue Feb 1 04:39:02 2011 +++ /branches/bleeding_edge/test/cctest/cctest.status Wed Feb 2 05:55:29 2011
@@ -46,9 +46,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