Merge revisions 7089, 7095, 7096 to trunk.

This fixes the memory leaks and chrashes due to safepoints being recorded in the wrong place. 

Review URL: http://codereview.chromium.org/6639023

git-svn-id: http://v8.googlecode.com/svn/trunk@7103 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 91b6651..2ba95c4 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -1424,7 +1424,7 @@
                                     const ParameterCount& actual,
                                     Handle<Code> code_constant,
                                     const Operand& code_operand,
-                                    Label* done,
+                                    NearLabel* done,
                                     InvokeFlag flag,
                                     PostCallGenerator* post_call_generator) {
   bool definitely_matches = false;
@@ -1492,7 +1492,7 @@
                                 const ParameterCount& actual,
                                 InvokeFlag flag,
                                 PostCallGenerator* post_call_generator) {
-  Label done;
+  NearLabel done;
   InvokePrologue(expected, actual, Handle<Code>::null(), code,
                  &done, flag, post_call_generator);
   if (flag == CALL_FUNCTION) {
@@ -1512,7 +1512,7 @@
                                 RelocInfo::Mode rmode,
                                 InvokeFlag flag,
                                 PostCallGenerator* post_call_generator) {
-  Label done;
+  NearLabel done;
   Operand dummy(eax);
   InvokePrologue(expected, actual, code, dummy, &done,
                  flag, post_call_generator);
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 62bb0f3..d7cfeb5 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -646,7 +646,7 @@
                       const ParameterCount& actual,
                       Handle<Code> code_constant,
                       const Operand& code_operand,
-                      Label* done,
+                      NearLabel* done,
                       InvokeFlag flag,
                       PostCallGenerator* post_call_generator = NULL);
 
diff --git a/src/safepoint-table.h b/src/safepoint-table.h
index 8803d06..2cb1994 100644
--- a/src/safepoint-table.h
+++ b/src/safepoint-table.h
@@ -228,6 +228,14 @@
     deoptimization_info_[index].pc_after_gap = pc;
   }
 
+  // Get the end pc offset of the last safepoint, including the code generated
+  // until the end of the gap following it.
+  unsigned GetPcAfterGap() {
+    int index = deoptimization_info_.length();
+    if (index == 0) return 0;
+    return deoptimization_info_[index - 1].pc_after_gap;
+  }
+
   // Emit the safepoint table after the body. The number of bits per
   // entry must be enough to hold all the pointer indexes.
   void Emit(Assembler* assembler, int bits_per_entry);
diff --git a/src/version.cc b/src/version.cc
index ac4ab4a..b82c03d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     2
 #define BUILD_NUMBER      0
-#define PATCH_LEVEL       1
+#define PATCH_LEVEL       2
 #define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index f6cd570..ab26d74 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -395,6 +395,13 @@
   // Does not check the "reg" part of the Operand.
   bool AddressUsesRegister(Register reg) const;
 
+  // Queries related to the size of the generated instruction.
+  // Whether the generated instruction will have a REX prefix.
+  bool requires_rex() const { return rex_ != 0; }
+  // Size of the ModR/M, SIB and displacement parts of the generated
+  // instruction.
+  int operand_size() const { return len_; }
+
  private:
   byte rex_;
   byte buf_[6];
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index bd968b9..a6358e3 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -39,7 +39,7 @@
 
 // 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 {
+class SafepointGenerator : public CallWrapper {
  public:
   SafepointGenerator(LCodeGen* codegen,
                      LPointerMap* pointers,
@@ -48,29 +48,29 @@
       : codegen_(codegen),
         pointers_(pointers),
         deoptimization_index_(deoptimization_index),
-        ensure_reloc_space_(ensure_reloc_space),
-        previous_safepoint_position_(-kMinSafepointSize) { }
+        ensure_reloc_space_(ensure_reloc_space) { }
   virtual ~SafepointGenerator() { }
 
-  virtual void Generate() {
+  virtual void BeforeCall(int call_size) {
+    ASSERT(call_size >= 0);
     // Ensure that we have enough space after the previous safepoint position
-    // for the generated code there.
-    int position = codegen_->masm()->pc_offset();
-    ASSERT(position > previous_safepoint_position_);
-    if (position < previous_safepoint_position_ + kMinSafepointSize) {
-      int padding_size =
-          previous_safepoint_position_ + kMinSafepointSize - position;
+    // for the jump generated there.
+    int call_end = codegen_->masm()->pc_offset() + call_size;
+    int prev_jump_end = codegen_->LastSafepointEnd() + kMinSafepointSize;
+    if (call_end < prev_jump_end) {
+      int padding_size = prev_jump_end - call_end;
       STATIC_ASSERT(kMinSafepointSize <= 9);  // One multibyte nop is enough.
       codegen_->masm()->nop(padding_size);
-      position += padding_size;
     }
+  }
+
+  virtual void AfterCall() {
     // Ensure that we have enough space in the reloc info to patch
     // this with calls when doing deoptimization.
     if (ensure_reloc_space_) {
       codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true);
     }
     codegen_->RecordSafepoint(pointers_, deoptimization_index_);
-    previous_safepoint_position_ = position;
   }
 
  private:
@@ -80,7 +80,6 @@
   LPointerMap* pointers_;
   int deoptimization_index_;
   bool ensure_reloc_space_;
-  int previous_safepoint_position_;
 };
 
 
@@ -259,9 +258,8 @@
 
 bool LCodeGen::GenerateJumpTable() {
   for (int i = 0; i < jump_table_.length(); i++) {
-    JumpTableEntry* info = jump_table_[i];
-    __ bind(&(info->label_));
-    __ Jump(info->address_, RelocInfo::RUNTIME_ENTRY);
+    __ bind(&jump_table_[i].label);
+    __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
   }
   return !is_aborted();
 }
@@ -539,17 +537,13 @@
   if (cc == no_condition) {
     __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
   } else {
-    JumpTableEntry* jump_info = NULL;
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (jump_table_.length() > 0 &&
-        jump_table_[jump_table_.length() - 1]->address_ == entry) {
-      jump_info = jump_table_[jump_table_.length() - 1];
-    } else {
-      jump_info = new JumpTableEntry(entry);
-      jump_table_.Add(jump_info);
+    if (jump_table_.is_empty() ||
+        jump_table_.last().address != entry) {
+      jump_table_.Add(entry);
     }
-    __ j(cc, &jump_info->label_);
+    __ j(cc, &jump_table_.last().label);
   }
 }
 
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index ab0dffb..d2bde6f 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -210,6 +210,9 @@
                                     int arguments,
                                     int deoptimization_index);
   void RecordPosition(int position);
+  int LastSafepointEnd() {
+    return static_cast<int>(safepoints_.GetPcAfterGap());
+  }
 
   static Condition TokenToCondition(Token::Value op, bool is_unsigned);
   void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
@@ -238,11 +241,11 @@
   void EmitPushConstantOperand(LOperand* operand);
 
   struct JumpTableEntry {
-    inline JumpTableEntry(Address address)
-        : label_(),
-          address_(address) { }
-    Label label_;
-    Address address_;
+    inline JumpTableEntry(Address entry)
+        : label(),
+          address(entry) { }
+    Label label;
+    Address address;
   };
 
   LChunk* const chunk_;
@@ -253,7 +256,7 @@
   int current_instruction_;
   const ZoneList<LInstruction*>* instructions_;
   ZoneList<LEnvironment*> deoptimizations_;
-  ZoneList<JumpTableEntry*> jump_table_;
+  ZoneList<JumpTableEntry> jump_table_;
   ZoneList<Handle<Object> > deoptimization_literals_;
   int inlined_function_count_;
   Scope* const scope_;
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index b468e82..c6829c5 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -638,7 +638,7 @@
 
 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
                                    InvokeFlag flag,
-                                   PostCallGenerator* post_call_generator) {
+                                   CallWrapper* call_wrapper) {
   // Calls are not allowed in some stubs.
   ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
 
@@ -647,7 +647,7 @@
   // parameter count to avoid emitting code to do the check.
   ParameterCount expected(0);
   GetBuiltinEntry(rdx, id);
-  InvokeCode(rdx, expected, expected, flag, post_call_generator);
+  InvokeCode(rdx, expected, expected, flag, call_wrapper);
 }
 
 
@@ -1424,20 +1424,41 @@
 
 
 void MacroAssembler::Call(ExternalReference ext) {
+#ifdef DEBUG
+  int pre_position = pc_offset();
+#endif
   movq(kScratchRegister, ext);
   call(kScratchRegister);
+#ifdef DEBUG
+  int post_position = pc_offset();
+  CHECK_EQ(pre_position + CallSize(ext), post_position);
+#endif
 }
 
 
 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
+#ifdef DEBUG
+  int pre_position = pc_offset();
+#endif
   movq(kScratchRegister, destination, rmode);
   call(kScratchRegister);
+#ifdef DEBUG
+  int post_position = pc_offset();
+  CHECK_EQ(pre_position + CallSize(destination, rmode), post_position);
+#endif
 }
 
 
 void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
+#ifdef DEBUG
+  int pre_position = pc_offset();
+#endif
   ASSERT(RelocInfo::IsCodeTarget(rmode));
   call(code_object, rmode);
+#ifdef DEBUG
+  int post_position = pc_offset();
+  CHECK_EQ(pre_position + CallSize(code_object), post_position);
+#endif
 }
 
 
@@ -1868,7 +1889,7 @@
                                 const ParameterCount& expected,
                                 const ParameterCount& actual,
                                 InvokeFlag flag,
-                                PostCallGenerator* post_call_generator) {
+                                CallWrapper* call_wrapper) {
   NearLabel done;
   InvokePrologue(expected,
                  actual,
@@ -1876,10 +1897,11 @@
                  code,
                  &done,
                  flag,
-                 post_call_generator);
+                 call_wrapper);
   if (flag == CALL_FUNCTION) {
+    if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code));
     call(code);
-    if (post_call_generator != NULL) post_call_generator->Generate();
+    if (call_wrapper != NULL) call_wrapper->AfterCall();
   } else {
     ASSERT(flag == JUMP_FUNCTION);
     jmp(code);
@@ -1893,7 +1915,7 @@
                                 const ParameterCount& actual,
                                 RelocInfo::Mode rmode,
                                 InvokeFlag flag,
-                                PostCallGenerator* post_call_generator) {
+                                CallWrapper* call_wrapper) {
   NearLabel done;
   Register dummy = rax;
   InvokePrologue(expected,
@@ -1902,10 +1924,11 @@
                  dummy,
                  &done,
                  flag,
-                 post_call_generator);
+                 call_wrapper);
   if (flag == CALL_FUNCTION) {
+    if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code));
     Call(code, rmode);
-    if (post_call_generator != NULL) post_call_generator->Generate();
+    if (call_wrapper != NULL) call_wrapper->AfterCall();
   } else {
     ASSERT(flag == JUMP_FUNCTION);
     Jump(code, rmode);
@@ -1917,7 +1940,7 @@
 void MacroAssembler::InvokeFunction(Register function,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   ASSERT(function.is(rdi));
   movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
   movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
@@ -1928,14 +1951,14 @@
   movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
 
   ParameterCount expected(rbx);
-  InvokeCode(rdx, expected, actual, flag, post_call_generator);
+  InvokeCode(rdx, expected, actual, flag, call_wrapper);
 }
 
 
 void MacroAssembler::InvokeFunction(JSFunction* function,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   ASSERT(function->is_compiled());
   // Get the function and setup the context.
   Move(rdi, Handle<JSFunction>(function));
@@ -1946,7 +1969,7 @@
     // the Code object every time we call the function.
     movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
     ParameterCount expected(function->shared()->formal_parameter_count());
-    InvokeCode(rdx, expected, actual, flag, post_call_generator);
+    InvokeCode(rdx, expected, actual, flag, call_wrapper);
   } else {
     // Invoke the cached code.
     Handle<Code> code(function->code());
@@ -1956,7 +1979,7 @@
                actual,
                RelocInfo::CODE_TARGET,
                flag,
-               post_call_generator);
+               call_wrapper);
   }
 }
 
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 7a7f1a2..5908cef 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -61,7 +61,7 @@
 
 // Forward declaration.
 class JumpTarget;
-class PostCallGenerator;
+class CallWrapper;
 
 struct SmiIndex {
   SmiIndex(Register index_register, ScaleFactor scale)
@@ -199,32 +199,32 @@
                   const ParameterCount& expected,
                   const ParameterCount& actual,
                   InvokeFlag flag,
-                  PostCallGenerator* post_call_generator = NULL);
+                  CallWrapper* call_wrapper = NULL);
 
   void InvokeCode(Handle<Code> code,
                   const ParameterCount& expected,
                   const ParameterCount& actual,
                   RelocInfo::Mode rmode,
                   InvokeFlag flag,
-                  PostCallGenerator* post_call_generator = NULL);
+                  CallWrapper* call_wrapper = NULL);
 
   // Invoke the JavaScript function in the given register. Changes the
   // current context to the context in the function before invoking.
   void InvokeFunction(Register function,
                       const ParameterCount& actual,
                       InvokeFlag flag,
-                      PostCallGenerator* post_call_generator = NULL);
+                      CallWrapper* call_wrapper = NULL);
 
   void InvokeFunction(JSFunction* function,
                       const ParameterCount& actual,
                       InvokeFlag flag,
-                      PostCallGenerator* post_call_generator = NULL);
+                      CallWrapper* call_wrapper = NULL);
 
   // Invoke specified builtin JavaScript function. Adds an entry to
   // the unresolved list if the name does not resolve.
   void InvokeBuiltin(Builtins::JavaScript id,
                      InvokeFlag flag,
-                     PostCallGenerator* post_call_generator = NULL);
+                     CallWrapper* call_wrapper = NULL);
 
   // Store the function for the given builtin in the target register.
   void GetBuiltinFunction(Register target, Builtins::JavaScript id);
@@ -626,6 +626,26 @@
   void Call(ExternalReference ext);
   void Call(Handle<Code> code_object, RelocInfo::Mode rmode);
 
+  // The size of the code generated for different call instructions.
+  int CallSize(Address destination, RelocInfo::Mode rmode) {
+    return kCallInstructionLength;
+  }
+  int CallSize(ExternalReference ext) {
+    return kCallInstructionLength;
+  }
+  int CallSize(Handle<Code> code_object) {
+    // Code calls use 32-bit relative addressing.
+    return kShortCallInstructionLength;
+  }
+  int CallSize(Register target) {
+    // Opcode: REX_opt FF /2 m64
+    return (target.high_bit() != 0) ? 3 : 2;
+  }
+  int CallSize(const Operand& target) {
+    // Opcode: REX_opt FF /2 m64
+    return (target.requires_rex() ? 2 : 1) + target.operand_size();
+  }
+
   // Emit call to the code we are currently generating.
   void CallSelf() {
     Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
@@ -1018,7 +1038,7 @@
                       Register code_register,
                       LabelType* done,
                       InvokeFlag flag,
-                      PostCallGenerator* post_call_generator);
+                      CallWrapper* call_wrapper);
 
   // Activation support.
   void EnterFrame(StackFrame::Type type);
@@ -1084,13 +1104,17 @@
 
 
 // Helper class for generating code or data associated with the code
-// right after a call instruction. As an example this can be used to
+// right before or after a call instruction. As an example this can be used to
 // generate safepoint data after calls for crankshaft.
-class PostCallGenerator {
+class CallWrapper {
  public:
-  PostCallGenerator() { }
-  virtual ~PostCallGenerator() { }
-  virtual void Generate() = 0;
+  CallWrapper() { }
+  virtual ~CallWrapper() { }
+  // Called just before emitting a call. Argument is the size of the generated
+  // call code.
+  virtual void BeforeCall(int call_size) = 0;
+  // Called just after emitting a call, i.e., at the return site for the call.
+  virtual void AfterCall() = 0;
 };
 
 
@@ -1801,7 +1825,7 @@
                                     Register code_register,
                                     LabelType* done,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   bool definitely_matches = false;
   NearLabel invoke;
   if (expected.is_immediate()) {
@@ -1851,8 +1875,9 @@
     }
 
     if (flag == CALL_FUNCTION) {
+      if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(adaptor));
       Call(adaptor, RelocInfo::CODE_TARGET);
-      if (post_call_generator != NULL) post_call_generator->Generate();
+      if (call_wrapper != NULL) call_wrapper->AfterCall();
       jmp(done);
     } else {
       Jump(adaptor, RelocInfo::CODE_TARGET);