Version 2.2.16.

Remove the SetExternalStringDiposeCallback API. Changed the disposal of external string resources to call a virtual Dispose method on the resource.

Added support for more precise break points when debugging and stepping.

Memory usage improvements on all platforms.


git-svn-id: http://v8.googlecode.com/svn/trunk@4829 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 321ba00..e277c7a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2010-06-07: Version 2.2.16
+
+        Remove the SetExternalStringDiposeCallback API. Changed the 
+        disposal of external string resources to call a virtual Dispose
+        method on the resource.
+
+        Added support for more precise break points when debugging and 
+        stepping.
+
+        Memory usage improvements on all platforms.
+
+
 2010-06-07: Version 2.2.15
 
         Add an API to control the disposal of external string resources.
diff --git a/include/v8.h b/include/v8.h
index fe01e30..24b4cbe 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -134,6 +134,7 @@
 
 class Arguments;
 class Object;
+class Heap;
 class Top;
 
 }
@@ -513,6 +514,7 @@
 class V8EXPORT ScriptData {  // NOLINT
  public:
   virtual ~ScriptData() { }
+
   /**
    * Pre-compiles the specified script (context-independent).
    *
@@ -522,6 +524,16 @@
   static ScriptData* PreCompile(const char* input, int length);
 
   /**
+   * Pre-compiles the specified script (context-independent).
+   *
+   * NOTE: Pre-compilation using this method cannot happen on another thread
+   * without using Lockers.
+   *
+   * \param source Script source code.
+   */
+  static ScriptData* PreCompile(Handle<String> source);
+
+  /**
    * Load previous pre-compilation data.
    *
    * \param data Pointer to data returned by a call to Data() of a previous
@@ -1026,12 +1038,24 @@
   class V8EXPORT ExternalStringResourceBase {
    public:
     virtual ~ExternalStringResourceBase() {}
+
    protected:
     ExternalStringResourceBase() {}
+
+    /**
+     * Internally V8 will call this Dispose method when the external string
+     * resource is no longer needed. The default implementation will use the
+     * delete operator. This method can be overridden in subclasses to
+     * control how allocated external string resources are disposed.
+     */
+    virtual void Dispose() { delete this; }
+
    private:
     // Disallow copying and assigning.
     ExternalStringResourceBase(const ExternalStringResourceBase&);
     void operator=(const ExternalStringResourceBase&);
+
+    friend class v8::internal::Heap;
   };
 
   /**
@@ -1048,10 +1072,17 @@
      * buffer.
      */
     virtual ~ExternalStringResource() {}
-    /** The string data from the underlying buffer.*/
+
+    /**
+     * The string data from the underlying buffer.
+     */
     virtual const uint16_t* data() const = 0;
-    /** The length of the string. That is, the number of two-byte characters.*/
+
+    /**
+     * The length of the string. That is, the number of two-byte characters.
+     */
     virtual size_t length() const = 0;
+
    protected:
     ExternalStringResource() {}
   };
@@ -1123,12 +1154,10 @@
   /**
    * Creates a new external string using the data defined in the given
    * resource. When the external string is no longer live on V8's heap the
-   * resource will be disposed. If a disposal callback has been set using
-   * SetExternalStringDiposeCallback this callback will be called to dispose
-   * the resource. Otherwise, V8 will dispose the resource using the C++ delete
-   * operator. The caller of this function should not otherwise delete or
-   * modify the resource. Neither should the underlying buffer be deallocated
-   * or modified except through the destructor of the external string resource.
+   * resource will be disposed by calling its Dispose method. The caller of
+   * this function should not otherwise delete or modify the resource. Neither
+   * should the underlying buffer be deallocated or modified except through the
+   * destructor of the external string resource.
    */
   static Local<String> NewExternal(ExternalStringResource* resource);
 
@@ -1146,12 +1175,10 @@
   /**
    * Creates a new external string using the ascii data defined in the given
    * resource. When the external string is no longer live on V8's heap the
-   * resource will be disposed. If a disposal callback has been set using
-   * SetExternalStringDiposeCallback this callback will be called to dispose
-   * the resource. Otherwise, V8 will dispose the resource using the C++ delete
-   * operator. The caller of this function should not otherwise delete or
-   * modify the resource. Neither should the underlying buffer be deallocated
-   * or modified except through the destructor of the external string resource.
+   * resource will be disposed by calling its Dispose method. The caller of
+   * this function should not otherwise delete or modify the resource. Neither
+   * should the underlying buffer be deallocated or modified except through the
+   * destructor of the external string resource.
    */
   static Local<String> NewExternal(ExternalAsciiStringResource* resource);
 
@@ -1251,10 +1278,6 @@
 };
 
 
-typedef void (*ExternalStringDiposeCallback)
-    (String::ExternalStringResourceBase* resource);
-
-
 /**
  * A JavaScript number value (ECMA-262, 4.3.20)
  */
@@ -2472,15 +2495,6 @@
   static void RemoveMessageListeners(MessageCallback that);
 
   /**
-   * Set a callback to be called when an external string is no longer live on
-   * V8's heap. The resource will no longer be needed by V8 and the embedder
-   * can dispose of if. If this callback is not set V8 will free the resource
-   * using the C++ delete operator.
-   */
-  static void SetExternalStringDiposeCallback(
-      ExternalStringDiposeCallback that);
-
-  /**
    * Sets V8 flags from a string.
    */
   static void SetFlagsFromString(const char* str, int length);
diff --git a/src/api.cc b/src/api.cc
index dfdd7bd..cb5e96d 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1120,6 +1120,12 @@
 }
 
 
+ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
+  i::Handle<i::String> str = Utils::OpenHandle(*source);
+  return i::PreParse(str, NULL, NULL);
+}
+
+
 ScriptData* ScriptData::New(const char* data, int length) {
   // Return an empty ScriptData if the length is obviously invalid.
   if (length % sizeof(unsigned) != 0) {
@@ -3692,14 +3698,6 @@
 }
 
 
-void V8::SetExternalStringDiposeCallback(
-    ExternalStringDiposeCallback callback) {
-  if (IsDeadCheck("v8::V8::SetExternalStringDiposeCallback()"))
-    return;
-  i::Heap::SetExternalStringDiposeCallback(callback);
-}
-
-
 void V8::SetCounterFunction(CounterLookupCallback callback) {
   if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
   i::StatsTable::SetCounterFunction(callback);
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index e292cef..8ca9126 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -116,9 +116,10 @@
 
 
 Address RelocInfo::call_address() {
-  ASSERT(IsPatchedReturnSequence());
-  // The 2 instructions offset assumes patched return sequence.
-  ASSERT(IsJSReturn(rmode()));
+  // The 2 instructions offset assumes patched debug break slot or return
+  // sequence.
+  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
   return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize);
 }
 
@@ -168,6 +169,12 @@
 }
 
 
+bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
+  Instr current_instr = Assembler::instr_at(pc_);
+  return !Assembler::IsNop(current_instr, 2);
+}
+
+
 void RelocInfo::Visit(ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
@@ -178,8 +185,10 @@
     visitor->VisitExternalReference(target_reference_address());
 #ifdef ENABLE_DEBUGGER_SUPPORT
   } else if (Debug::has_break_points() &&
-             RelocInfo::IsJSReturn(mode) &&
-             IsPatchedReturnSequence()) {
+             ((RelocInfo::IsJSReturn(mode) &&
+              IsPatchedReturnSequence()) ||
+             (RelocInfo::IsDebugBreakSlot(mode) &&
+              IsPatchedDebugBreakSlotSequence()))) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 846464a..025f28e 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -2040,6 +2040,13 @@
 }
 
 
+void Assembler::RecordDebugBreakSlot() {
+  WriteRecordedPositions();
+  CheckBuffer();
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
+}
+
+
 void Assembler::RecordComment(const char* msg) {
   if (FLAG_debug_code) {
     CheckBuffer();
@@ -2062,13 +2069,16 @@
 }
 
 
-void Assembler::WriteRecordedPositions() {
+bool Assembler::WriteRecordedPositions() {
+  bool written = false;
+
   // Write the statement position if it is different from what was written last
   // time.
   if (current_statement_position_ != written_statement_position_) {
     CheckBuffer();
     RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
     written_statement_position_ = current_statement_position_;
+    written = true;
   }
 
   // Write the position if it is different from what was written last time and
@@ -2078,7 +2088,11 @@
     CheckBuffer();
     RecordRelocInfo(RelocInfo::POSITION, current_position_);
     written_position_ = current_position_;
+    written = true;
   }
+
+  // Return whether something was written.
+  return written;
 }
 
 
@@ -2135,9 +2149,10 @@
 
 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
   RelocInfo rinfo(pc_, rmode, data);  // we do not try to reuse pool constants
-  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) {
+  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
     // Adjust code for new modes.
-    ASSERT(RelocInfo::IsJSReturn(rmode)
+    ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
+           || RelocInfo::IsJSReturn(rmode)
            || RelocInfo::IsComment(rmode)
            || RelocInfo::IsPosition(rmode));
     // These modes do not need an entry in the constant pool.
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index d0dee56..e5d42f9 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -629,22 +629,39 @@
   // Distance between start of patched return sequence and the emitted address
   // to jump to.
 #ifdef USE_BLX
-  // Return sequence is:
+  // Patched return sequence is:
   //  ldr  ip, [pc, #0]   @ emited address and start
   //  blx  ip
   static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
 #else
-  // Return sequence is:
+  // Patched return sequence is:
   //  mov  lr, pc         @ start of sequence
   //  ldr  pc, [pc, #-4]  @ emited address
   static const int kPatchReturnSequenceAddressOffset =  kInstrSize;
 #endif
 
+  // Distance between start of patched debug break slot and the emitted address
+  // to jump to.
+#ifdef USE_BLX
+  // Patched debug break slot code is:
+  //  ldr  ip, [pc, #0]   @ emited address and start
+  //  blx  ip
+  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
+#else
+  // Patched debug break slot code is:
+  //  mov  lr, pc         @ start of sequence
+  //  ldr  pc, [pc, #-4]  @ emited address
+  static const int kPatchDebugBreakSlotAddressOffset =  kInstrSize;
+#endif
+
   // Difference between address of current opcode and value read from pc
   // register.
   static const int kPcLoadDelta = 8;
 
-  static const int kJSReturnSequenceLength = 4;
+  static const int kJSReturnSequenceInstructions = 4;
+  static const int kDebugBreakSlotInstructions = 3;
+  static const int kDebugBreakSlotLength =
+      kDebugBreakSlotInstructions * kInstrSize;
 
   // ---------------------------------------------------------------------------
   // Code generation
@@ -981,13 +998,16 @@
   // Mark address of the ExitJSFrame code.
   void RecordJSReturn();
 
+  // Mark address of a debug break slot.
+  void RecordDebugBreakSlot();
+
   // Record a comment relocation entry that can be used by a disassembler.
   // Use --debug_code to enable.
   void RecordComment(const char* msg);
 
   void RecordPosition(int pos);
   void RecordStatementPosition(int pos);
-  void WriteRecordedPositions();
+  bool WriteRecordedPositions();
 
   int pc_offset() const { return pc_ - buffer_; }
   int current_position() const { return current_position_; }
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index d6fdf45..8d4bf14 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -386,8 +386,10 @@
       // the add instruction the add will generate two instructions.
       int return_sequence_length =
           masm_->InstructionsGeneratedSince(&check_exit_codesize);
-      CHECK(return_sequence_length == Assembler::kJSReturnSequenceLength ||
-            return_sequence_length == Assembler::kJSReturnSequenceLength + 1);
+      CHECK(return_sequence_length ==
+            Assembler::kJSReturnSequenceInstructions ||
+            return_sequence_length ==
+            Assembler::kJSReturnSequenceInstructions + 1);
 #endif
     }
   }
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 6a33667..cabdf00 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -226,7 +226,9 @@
                               bool is_toplevel,
                               Handle<Script> script);
 
-  static void RecordPositions(MacroAssembler* masm, int pos);
+  static bool RecordPositions(MacroAssembler* masm,
+                              int pos,
+                              bool right_here = false);
 
   // Accessors
   MacroAssembler* masm() { return masm_; }
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index 69fc504..65f5eea 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -57,7 +57,7 @@
   // #endif
   //   <debug break return code entry point address>
   //   bktp 0
-  CodePatcher patcher(rinfo()->pc(), 4);
+  CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
 #ifdef USE_BLX
   patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
   patcher.masm()->blx(v8::internal::ip);
@@ -73,17 +73,59 @@
 // Restore the JS frame exit code.
 void BreakLocationIterator::ClearDebugBreakAtReturn() {
   rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceLength);
+                     Assembler::kJSReturnSequenceInstructions);
 }
 
 
-// A debug break in the exit code is identified by a call.
+// A debug break in the frame exit code is identified by the JS frame exit code
+// having been patched with a call instruction.
 bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
   ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
   return rinfo->IsPatchedReturnSequence();
 }
 
 
+bool BreakLocationIterator::IsDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  // Check whether the debug break slot instructions have been patched.
+  return rinfo()->IsPatchedDebugBreakSlotSequence();
+}
+
+
+void BreakLocationIterator::SetDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  // Patch the code changing the debug break slot code from
+  //   mov r2, r2
+  //   mov r2, r2
+  //   mov r2, r2
+  // to a call to the debug break slot code.
+  // #if USE_BLX
+  //   ldr ip, [pc, #0]
+  //   blx ip
+  // #else
+  //   mov lr, pc
+  //   ldr pc, [pc, #-4]
+  // #endif
+  //   <debug break slot code entry point address>
+  CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
+#ifdef USE_BLX
+  patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
+  patcher.masm()->blx(v8::internal::ip);
+#else
+  patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
+  patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
+#endif
+  patcher.Emit(Debug::debug_break_return()->entry());
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  rinfo()->PatchCode(original_rinfo()->pc(),
+                     Assembler::kDebugBreakSlotInstructions);
+}
+
+
 #define __ ACCESS_MASM(masm)
 
 
@@ -220,10 +262,33 @@
 }
 
 
+void Debug::GenerateSlot(MacroAssembler* masm) {
+  // Generate enough nop's to make space for a call instruction. Avoid emitting
+  // the constant pool in the debug break slot code.
+  Assembler::BlockConstPoolScope block_const_pool(masm);
+  Label check_codesize;
+  __ bind(&check_codesize);
+  __ RecordDebugBreakSlot();
+  for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
+    __ nop(2);
+  }
+  ASSERT_EQ(Assembler::kDebugBreakSlotInstructions,
+            masm->InstructionsGeneratedSince(&check_codesize));
+}
+
+
+void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
+  // In the places where a debug break slot is inserted no registers can contain
+  // object pointers.
+  Generate_DebugBreakCallHelper(masm, 0);
+}
+
+
 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
   masm->Abort("LiveEdit frame dropping is not supported on arm");
 }
 
+
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   masm->Abort("LiveEdit frame dropping is not supported on arm");
 }
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 5fa412f..e2cd84d 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -238,8 +238,10 @@
     // add instruction the add will generate two instructions.
     int return_sequence_length =
         masm_->InstructionsGeneratedSince(&check_exit_codesize);
-    CHECK(return_sequence_length == Assembler::kJSReturnSequenceLength ||
-          return_sequence_length == Assembler::kJSReturnSequenceLength + 1);
+    CHECK(return_sequence_length ==
+          Assembler::kJSReturnSequenceInstructions ||
+          return_sequence_length ==
+          Assembler::kJSReturnSequenceInstructions + 1);
 #endif
   }
 }
diff --git a/src/assembler.cc b/src/assembler.cc
index 871ca86..6a46f61 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -449,6 +449,11 @@
       return "external reference";
     case RelocInfo::INTERNAL_REFERENCE:
       return "internal reference";
+    case RelocInfo::DEBUG_BREAK_SLOT:
+#ifndef ENABLE_DEBUGGER_SUPPORT
+      UNREACHABLE();
+#endif
+      return "debug break slot";
     case RelocInfo::NUMBER_OF_MODES:
       UNREACHABLE();
       return "number_of_modes";
@@ -513,6 +518,7 @@
     case STATEMENT_POSITION:
     case EXTERNAL_REFERENCE:
     case INTERNAL_REFERENCE:
+    case DEBUG_BREAK_SLOT:
     case NONE:
       break;
     case NUMBER_OF_MODES:
diff --git a/src/assembler.h b/src/assembler.h
index 74613b3..fb75d6d 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -118,9 +118,9 @@
   enum Mode {
     // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
     CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
-    CODE_TARGET_CONTEXT,  // code target used for contextual loads.
-    DEBUG_BREAK,
-    CODE_TARGET,         // code target which is not any of the above.
+    CODE_TARGET_CONTEXT,  // Code target used for contextual loads.
+    DEBUG_BREAK,  // Code target for the debugger statement.
+    CODE_TARGET,  // Code target which is not any of the above.
     EMBEDDED_OBJECT,
 
     // Everything after runtime_entry (inclusive) is not GC'ed.
@@ -129,6 +129,7 @@
     COMMENT,
     POSITION,  // See comment for kNoPosition above.
     STATEMENT_POSITION,  // See comment for kNoPosition above.
+    DEBUG_BREAK_SLOT,  // Additional code inserted for debug break slot.
     EXTERNAL_REFERENCE,  // The address of an external C++ function.
     INTERNAL_REFERENCE,  // An address inside the same function.
 
@@ -174,6 +175,9 @@
   static inline bool IsInternalReference(Mode mode) {
     return mode == INTERNAL_REFERENCE;
   }
+  static inline bool IsDebugBreakSlot(Mode mode) {
+    return mode == DEBUG_BREAK_SLOT;
+  }
   static inline int ModeMask(Mode mode) { return 1 << mode; }
 
   // Accessors
@@ -243,6 +247,10 @@
   // with a call to the debugger.
   INLINE(bool IsPatchedReturnSequence());
 
+  // Check whether this debug break slot has been patched with a call to the
+  // debugger.
+  INLINE(bool IsPatchedDebugBreakSlotSequence());
+
 #ifdef ENABLE_DISASSEMBLER
   // Printing
   static const char* RelocModeName(Mode rmode);
diff --git a/src/ast.h b/src/ast.h
index a3a9734..b9a7a3d 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1469,10 +1469,14 @@
  public:
   Conditional(Expression* condition,
               Expression* then_expression,
-              Expression* else_expression)
+              Expression* else_expression,
+              int then_expression_position,
+              int else_expression_position)
       : condition_(condition),
         then_expression_(then_expression),
-        else_expression_(else_expression) { }
+        else_expression_(else_expression),
+        then_expression_position_(then_expression_position),
+        else_expression_position_(else_expression_position) { }
 
   virtual void Accept(AstVisitor* v);
 
@@ -1482,10 +1486,15 @@
   Expression* then_expression() const { return then_expression_; }
   Expression* else_expression() const { return else_expression_; }
 
+  int then_expression_position() { return then_expression_position_; }
+  int else_expression_position() { return else_expression_position_; }
+
  private:
   Expression* condition_;
   Expression* then_expression_;
   Expression* else_expression_;
+  int then_expression_position_;
+  int else_expression_position_;
 };
 
 
diff --git a/src/builtins.cc b/src/builtins.cc
index 0677809..7116dc9 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -1360,10 +1360,17 @@
   Debug::GenerateStubNoRegistersDebugBreak(masm);
 }
 
+
+static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateSlotDebugBreak(masm);
+}
+
+
 static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) {
   Debug::GeneratePlainReturnLiveEdit(masm);
 }
 
+
 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
   Debug::GenerateFrameDropperLiveEdit(masm);
 }
diff --git a/src/builtins.h b/src/builtins.h
index dd2e3cb..1fab375 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -127,6 +127,7 @@
   V(KeyedLoadIC_DebugBreak,     KEYED_LOAD_IC, DEBUG_BREAK)    \
   V(StoreIC_DebugBreak,         STORE_IC, DEBUG_BREAK)         \
   V(KeyedStoreIC_DebugBreak,    KEYED_STORE_IC, DEBUG_BREAK)   \
+  V(Slot_DebugBreak,            BUILTIN, DEBUG_BREAK)          \
   V(PlainReturn_LiveEdit,       BUILTIN, DEBUG_BREAK)          \
   V(FrameDropper_LiveEdit,      BUILTIN, DEBUG_BREAK)
 #else
diff --git a/src/checks.h b/src/checks.h
index cdcd18a..c2e40ba 100644
--- a/src/checks.h
+++ b/src/checks.h
@@ -285,14 +285,16 @@
 #define ASSERT_RESULT(expr)  CHECK(expr)
 #define ASSERT(condition)    CHECK(condition)
 #define ASSERT_EQ(v1, v2)    CHECK_EQ(v1, v2)
-#define ASSERT_NE(v1, v2)   CHECK_NE(v1, v2)
+#define ASSERT_NE(v1, v2)    CHECK_NE(v1, v2)
+#define ASSERT_GE(v1, v2)    CHECK_GE(v1, v2)
 #define STATIC_ASSERT(test)  STATIC_CHECK(test)
 #define SLOW_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition)
 #else
 #define ASSERT_RESULT(expr)     (expr)
 #define ASSERT(condition)      ((void) 0)
 #define ASSERT_EQ(v1, v2)      ((void) 0)
-#define ASSERT_NE(v1, v2)     ((void) 0)
+#define ASSERT_NE(v1, v2)      ((void) 0)
+#define ASSERT_GE(v1, v2)      ((void) 0)
 #define STATIC_ASSERT(test)    ((void) 0)
 #define SLOW_ASSERT(condition) ((void) 0)
 #endif
diff --git a/src/codegen.cc b/src/codegen.cc
index ff2fa03..686e173 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -415,32 +415,41 @@
 }
 
 
-void CodeGenerator::RecordPositions(MacroAssembler* masm, int pos) {
+bool CodeGenerator::RecordPositions(MacroAssembler* masm,
+                                    int pos,
+                                    bool right_here) {
   if (pos != RelocInfo::kNoPosition) {
     masm->RecordStatementPosition(pos);
     masm->RecordPosition(pos);
+    if (right_here) {
+      return masm->WriteRecordedPositions();
+    }
   }
+  return false;
 }
 
 
 void CodeGenerator::CodeForFunctionPosition(FunctionLiteral* fun) {
-  if (FLAG_debug_info) RecordPositions(masm(), fun->start_position());
+  if (FLAG_debug_info) RecordPositions(masm(), fun->start_position(), false);
 }
 
 
 void CodeGenerator::CodeForReturnPosition(FunctionLiteral* fun) {
-  if (FLAG_debug_info) RecordPositions(masm(), fun->end_position());
+  if (FLAG_debug_info) RecordPositions(masm(), fun->end_position(), false);
 }
 
 
 void CodeGenerator::CodeForStatementPosition(Statement* stmt) {
-  if (FLAG_debug_info) RecordPositions(masm(), stmt->statement_pos());
+  if (FLAG_debug_info) RecordPositions(masm(), stmt->statement_pos(), false);
 }
 
+
 void CodeGenerator::CodeForDoWhileConditionPosition(DoWhileStatement* stmt) {
-  if (FLAG_debug_info) RecordPositions(masm(), stmt->condition_position());
+  if (FLAG_debug_info)
+    RecordPositions(masm(), stmt->condition_position(), false);
 }
 
+
 void CodeGenerator::CodeForSourcePosition(int pos) {
   if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
     masm()->RecordPosition(pos);
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index cec10fd..14252a5 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -79,6 +79,8 @@
   // young generation.
   void Age();
 
+  bool HasFunction(SharedFunctionInfo* function_info);
+
   // GC support.
   void Iterate(ObjectVisitor* v);
 
@@ -204,6 +206,27 @@
 }
 
 
+bool CompilationSubCache::HasFunction(SharedFunctionInfo* function_info) {
+  if (function_info->script()->IsUndefined() ||
+      Script::cast(function_info->script())->source()->IsUndefined()) {
+    return false;
+  }
+
+  String* source =
+      String::cast(Script::cast(function_info->script())->source());
+  // Check all generations.
+  for (int generation = 0; generation < generations(); generation++) {
+    if (tables_[generation]->IsUndefined()) continue;
+
+    CompilationCacheTable* table =
+        CompilationCacheTable::cast(tables_[generation]);
+    Object* object = table->Lookup(source);
+    if (object->IsSharedFunctionInfo()) return true;
+  }
+  return false;
+}
+
+
 void CompilationSubCache::Age() {
   // Age the generations implicitly killing off the oldest.
   for (int i = generations_ - 1; i > 0; i--) {
@@ -506,6 +529,11 @@
 }
 
 
+bool CompilationCache::HasFunction(SharedFunctionInfo* function_info) {
+  return script.HasFunction(function_info);
+}
+
+
 void CompilationCache::Iterate(ObjectVisitor* v) {
   for (int i = 0; i < kSubCacheCount; i++) {
     subcaches[i]->Iterate(v);
diff --git a/src/compilation-cache.h b/src/compilation-cache.h
index 6358a26..583f04c 100644
--- a/src/compilation-cache.h
+++ b/src/compilation-cache.h
@@ -79,6 +79,9 @@
   // Clear the cache - also used to initialize the cache at startup.
   static void Clear();
 
+
+  static bool HasFunction(SharedFunctionInfo* function_info);
+
   // GC support.
   static void Iterate(ObjectVisitor* v);
 
diff --git a/src/compiler.cc b/src/compiler.cc
index ca92ed9..ebb9743 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -601,6 +601,7 @@
       lit->has_only_simple_this_property_assignments(),
       *lit->this_property_assignments());
   function_info->set_try_full_codegen(lit->try_full_codegen());
+  function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
 }
 
 
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index 2968081..c8d29f8 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -294,7 +294,8 @@
 int CpuProfiler::GetProfilesCount() {
   ASSERT(singleton_ != NULL);
   // The count of profiles doesn't depend on a security token.
-  return singleton_->profiles_->Profiles(CodeEntry::kNoSecurityToken)->length();
+  return singleton_->profiles_->Profiles(
+      TokenEnumerator::kNoSecurityToken)->length();
 }
 
 
@@ -380,7 +381,7 @@
 
 
 void CpuProfiler::FunctionCreateEvent(JSFunction* function) {
-  int security_token_id = CodeEntry::kNoSecurityToken;
+  int security_token_id = TokenEnumerator::kNoSecurityToken;
   if (function->unchecked_context()->IsContext()) {
     security_token_id = singleton_->token_enumerator_->GetTokenId(
         function->context()->global_context()->security_token());
@@ -476,9 +477,10 @@
 CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
   const double actual_sampling_rate = generator_->actual_sampling_rate();
   StopProcessorIfLastProfile();
-  CpuProfile* result = profiles_->StopProfiling(CodeEntry::kNoSecurityToken,
-                                                title,
-                                                actual_sampling_rate);
+  CpuProfile* result =
+      profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
+                               title,
+                               actual_sampling_rate);
   if (result != NULL) {
     result->Print();
   }
diff --git a/src/d8.cc b/src/d8.cc
index a69320a..7fd7925 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -576,6 +576,9 @@
 void Shell::RunShell() {
   LineEditor* editor = LineEditor::Get();
   printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
+  if (i::FLAG_debugger) {
+    printf("JavaScript debugger enabled\n");
+  }
   editor->Open();
   while (true) {
     Locker locker;
diff --git a/src/debug.cc b/src/debug.cc
index e279ee9..ca20a65 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -129,10 +129,14 @@
       ASSERT(statement_position_ >= 0);
     }
 
-    // Check for breakable code target. Look in the original code as setting
-    // break points can cause the code targets in the running (debugged) code to
-    // be of a different kind than in the original code.
-    if (RelocInfo::IsCodeTarget(rmode())) {
+    if (IsDebugBreakSlot()) {
+      // There is always a possible break point at a debug break slot.
+      break_point_++;
+      return;
+    } else if (RelocInfo::IsCodeTarget(rmode())) {
+      // Check for breakable code target. Look in the original code as setting
+      // break points can cause the code targets in the running (debugged) code
+      // to be of a different kind than in the original code.
       Address target = original_rinfo()->target_address();
       Code* code = Code::GetCodeFromTargetAddress(target);
       if ((code->is_inline_cache_stub() &&
@@ -329,6 +333,9 @@
   if (RelocInfo::IsJSReturn(rmode())) {
     // Patch the frame exit code with a break point.
     SetDebugBreakAtReturn();
+  } else if (IsDebugBreakSlot()) {
+    // Patch the code in the break slot.
+    SetDebugBreakAtSlot();
   } else {
     // Patch the IC call.
     SetDebugBreakAtIC();
@@ -346,6 +353,9 @@
   if (RelocInfo::IsJSReturn(rmode())) {
     // Restore the frame exit code.
     ClearDebugBreakAtReturn();
+  } else if (IsDebugBreakSlot()) {
+    // Restore the code in the break slot.
+    ClearDebugBreakAtSlot();
   } else {
     // Patch the IC call.
     ClearDebugBreakAtIC();
@@ -417,6 +427,8 @@
 bool BreakLocationIterator::IsDebugBreak() {
   if (RelocInfo::IsJSReturn(rmode())) {
     return IsDebugBreakAtReturn();
+  } else if (IsDebugBreakSlot()) {
+    return IsDebugBreakAtSlot();
   } else {
     return Debug::IsDebugBreak(rinfo()->target_address());
   }
@@ -478,6 +490,11 @@
 }
 
 
+bool BreakLocationIterator::IsDebugBreakSlot() {
+  return RelocInfo::DEBUG_BREAK_SLOT == rmode();
+}
+
+
 Object* BreakLocationIterator::BreakPointObjects() {
   return debug_info_->GetBreakPointObjects(code_position());
 }
@@ -573,6 +590,7 @@
 
 Handle<Context> Debug::debug_context_ = Handle<Context>();
 Code* Debug::debug_break_return_ = NULL;
+Code* Debug::debug_break_slot_ = NULL;
 
 
 void ScriptCache::Add(Handle<Script> script) {
@@ -656,6 +674,10 @@
     debug_break_return_ =
         Builtins::builtin(Builtins::Return_DebugBreak);
     ASSERT(debug_break_return_->IsCode());
+    // Get code to handle debug break in debug break slots.
+    debug_break_slot_ =
+        Builtins::builtin(Builtins::Slot_DebugBreak);
+    ASSERT(debug_break_slot_->IsCode());
   }
 }
 
@@ -824,6 +846,7 @@
 
 void Debug::Iterate(ObjectVisitor* v) {
   v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_return_)));
+  v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_slot_)));
 }
 
 
@@ -1631,16 +1654,21 @@
   // break point is still active after processing the break point.
   Address addr = frame->pc() - Assembler::kCallTargetAddressOffset;
 
-  // Check if the location is at JS exit.
+  // Check if the location is at JS exit or debug break slot.
   bool at_js_return = false;
   bool break_at_js_return_active = false;
+  bool at_debug_break_slot = false;
   RelocIterator it(debug_info->code());
-  while (!it.done()) {
+  while (!it.done() && !at_js_return && !at_debug_break_slot) {
     if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
       at_js_return = (it.rinfo()->pc() ==
           addr - Assembler::kPatchReturnSequenceAddressOffset);
       break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
     }
+    if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
+      at_debug_break_slot = (it.rinfo()->pc() ==
+          addr - Assembler::kPatchDebugBreakSlotAddressOffset);
+    }
     it.next();
   }
 
@@ -1657,25 +1685,30 @@
     // Move back to where the call instruction sequence started.
     thread_local_.after_break_target_ =
         addr - Assembler::kPatchReturnSequenceAddressOffset;
-  } else {
-    // Check if there still is a debug break call at the target address. If the
-    // break point has been removed it will have disappeared. If it have
-    // disappeared don't try to look in the original code as the running code
-    // will have the right address. This takes care of the case where the last
-    // break point is removed from the function and therefore no "original code"
-    // is available. If the debug break call is still there find the address in
-    // the original code.
-    if (IsDebugBreak(Assembler::target_address_at(addr))) {
-      // If the break point is still there find the call address which was
-      // overwritten in the original code by the call to DebugBreakXXX.
+  } else if (at_debug_break_slot) {
+    // Address of where the debug break slot starts.
+    addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
 
-      // Find the corresponding address in the original code.
-      addr += original_code->instruction_start() - code->instruction_start();
-    }
+    // Continue just after the slot.
+    thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
+  } else if (IsDebugBreak(Assembler::target_address_at(addr))) {
+    // We now know that there is still a debug break call at the target address,
+    // so the break point is still there and the original code will hold the
+    // address to jump to in order to complete the call which is replaced by a
+    // call to DebugBreakXXX.
+
+    // Find the corresponding address in the original code.
+    addr += original_code->instruction_start() - code->instruction_start();
 
     // Install jump to the call address in the original code. This will be the
     // call which was overwritten by the call to DebugBreakXXX.
     thread_local_.after_break_target_ = Assembler::target_address_at(addr);
+  } else {
+    // There is no longer a break point present. Don't try to look in the
+    // original code as the running code will have the right address. This takes
+    // care of the case where the last break point is removed from the function
+    // and therefore no "original code" is available.
+    thread_local_.after_break_target_ = Assembler::target_address_at(addr);
   }
 }
 
diff --git a/src/debug.h b/src/debug.h
index e2eecb8..0e12c76 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -146,6 +146,11 @@
   void SetDebugBreakAtReturn();
   void ClearDebugBreakAtReturn();
 
+  bool IsDebugBreakSlot();
+  bool IsDebugBreakAtSlot();
+  void SetDebugBreakAtSlot();
+  void ClearDebugBreakAtSlot();
+
   DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
 };
 
@@ -323,6 +328,7 @@
   enum AddressId {
     k_after_break_target_address,
     k_debug_break_return_address,
+    k_debug_break_slot_address,
     k_register_address
   };
 
@@ -342,6 +348,12 @@
     return &debug_break_return_;
   }
 
+  // Access to the debug break in debug break slot code.
+  static Code* debug_break_slot() { return debug_break_slot_; }
+  static Code** debug_break_slot_address() {
+    return &debug_break_slot_;
+  }
+
   static const int kEstimatedNofDebugInfoEntries = 16;
   static const int kEstimatedNofBreakPointsInFunction = 16;
 
@@ -370,6 +382,7 @@
   static void AfterGarbageCollection();
 
   // Code generator routines.
+  static void GenerateSlot(MacroAssembler* masm);
   static void GenerateLoadICDebugBreak(MacroAssembler* masm);
   static void GenerateStoreICDebugBreak(MacroAssembler* masm);
   static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
@@ -377,6 +390,7 @@
   static void GenerateConstructCallDebugBreak(MacroAssembler* masm);
   static void GenerateReturnDebugBreak(MacroAssembler* masm);
   static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm);
+  static void GenerateSlotDebugBreak(MacroAssembler* masm);
   static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
   static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
 
@@ -472,6 +486,9 @@
   // Code to call for handling debug break on return.
   static Code* debug_break_return_;
 
+  // Code to call for handling debug break in debug break slots.
+  static Code* debug_break_slot_;
+
   DISALLOW_COPY_AND_ASSIGN(Debug);
 };
 
@@ -895,6 +912,8 @@
         return reinterpret_cast<Address>(Debug::after_break_target_address());
       case Debug::k_debug_break_return_address:
         return reinterpret_cast<Address>(Debug::debug_break_return_address());
+      case Debug::k_debug_break_slot_address:
+        return reinterpret_cast<Address>(Debug::debug_break_slot_address());
       case Debug::k_register_address:
         return reinterpret_cast<Address>(Debug::register_address(reg_));
       default:
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 0e6dd88..dc8efcc 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -277,7 +277,7 @@
 
 DEFINE_bool(help, false, "Print usage message, including flags, on console")
 DEFINE_bool(dump_counters, false, "Dump counters on exit")
-DEFINE_bool(debugger, true, "Enable JavaScript debugger")
+DEFINE_bool(debugger, false, "Enable JavaScript debugger")
 DEFINE_bool(remote_debugger, false, "Connect JavaScript debugger to the "
                                     "debugger agent in another process")
 DEFINE_bool(debugger_agent, false, "Enable debugger agent")
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index f7a063a..6316158 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -439,6 +439,231 @@
 #undef CHECK_BAILOUT
 
 
+void BreakableStatementChecker::Check(Statement* stmt) {
+  Visit(stmt);
+}
+
+
+void BreakableStatementChecker::Check(Expression* expr) {
+  Visit(expr);
+}
+
+
+void BreakableStatementChecker::VisitDeclaration(Declaration* decl) {
+}
+
+
+void BreakableStatementChecker::VisitBlock(Block* stmt) {
+}
+
+
+void BreakableStatementChecker::VisitExpressionStatement(
+    ExpressionStatement* stmt) {
+  // Check if expression is breakable.
+  Visit(stmt->expression());
+}
+
+
+void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
+}
+
+
+void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
+  // If the condition is breakable the if statement is breakable.
+  Visit(stmt->condition());
+}
+
+
+void BreakableStatementChecker::VisitContinueStatement(
+    ContinueStatement* stmt) {
+}
+
+
+void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
+}
+
+
+void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
+  // Return is breakable if the expression is.
+  Visit(stmt->expression());
+}
+
+
+void BreakableStatementChecker::VisitWithEnterStatement(
+    WithEnterStatement* stmt) {
+  Visit(stmt->expression());
+}
+
+
+void BreakableStatementChecker::VisitWithExitStatement(
+    WithExitStatement* stmt) {
+}
+
+
+void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
+  // Switch statements breakable if the tag expression is.
+  Visit(stmt->tag());
+}
+
+
+void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
+  // Mark do while as breakable to avoid adding a break slot in front of it.
+  is_breakable_ = true;
+}
+
+
+void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
+  // Mark while statements breakable if the condition expression is.
+  Visit(stmt->cond());
+}
+
+
+void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
+  // Mark for statements breakable if the condition expression is.
+  if (stmt->cond() != NULL) {
+    Visit(stmt->cond());
+  }
+}
+
+
+void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
+  // Mark for in statements breakable if the enumerable expression is.
+  Visit(stmt->enumerable());
+}
+
+
+void BreakableStatementChecker::VisitTryCatchStatement(
+    TryCatchStatement* stmt) {
+  // Mark try catch as breakable to avoid adding a break slot in front of it.
+  is_breakable_ = true;
+}
+
+
+void BreakableStatementChecker::VisitTryFinallyStatement(
+    TryFinallyStatement* stmt) {
+  // Mark try finally as breakable to avoid adding a break slot in front of it.
+  is_breakable_ = true;
+}
+
+
+void BreakableStatementChecker::VisitDebuggerStatement(
+    DebuggerStatement* stmt) {
+  // The debugger statement is breakable.
+  is_breakable_ = true;
+}
+
+
+void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
+}
+
+
+void BreakableStatementChecker::VisitSharedFunctionInfoLiteral(
+    SharedFunctionInfoLiteral* expr) {
+}
+
+
+void BreakableStatementChecker::VisitConditional(Conditional* expr) {
+}
+
+
+void BreakableStatementChecker::VisitSlot(Slot* expr) {
+}
+
+
+void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
+}
+
+
+void BreakableStatementChecker::VisitLiteral(Literal* expr) {
+}
+
+
+void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
+}
+
+
+void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
+}
+
+
+void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
+}
+
+
+void BreakableStatementChecker::VisitCatchExtensionObject(
+    CatchExtensionObject* expr) {
+}
+
+
+void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
+  // If assigning to a property (including a global property) the assignment is
+  // breakable.
+  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+  Property* prop = expr->target()->AsProperty();
+  if (prop != NULL || (var != NULL && var->is_global())) {
+    is_breakable_ = true;
+    return;
+  }
+
+  // Otherwise the assignment is breakable if the assigned value is.
+  Visit(expr->value());
+}
+
+
+void BreakableStatementChecker::VisitThrow(Throw* expr) {
+  // Throw is breakable if the expression is.
+  Visit(expr->exception());
+}
+
+
+void BreakableStatementChecker::VisitProperty(Property* expr) {
+  // Property load is breakable.
+  is_breakable_ = true;
+}
+
+
+void BreakableStatementChecker::VisitCall(Call* expr) {
+  // Function calls both through IC and call stub are breakable.
+  is_breakable_ = true;
+}
+
+
+void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
+  // Function calls through new are breakable.
+  is_breakable_ = true;
+}
+
+
+void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
+}
+
+
+void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
+  Visit(expr->expression());
+}
+
+
+void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
+  Visit(expr->expression());
+}
+
+
+void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
+  Visit(expr->left());
+  Visit(expr->right());
+}
+
+
+void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
+  Visit(expr->left());
+  Visit(expr->right());
+}
+
+
+void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
+}
+
+
 #define __ ACCESS_MASM(masm())
 
 Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
@@ -552,7 +777,60 @@
 
 void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
   if (FLAG_debug_info) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+    if (!Debugger::IsDebuggerActive()) {
+      CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
+    } else {
+      // Check if the statement will be breakable without adding a debug break
+      // slot.
+      BreakableStatementChecker checker;
+      checker.Check(stmt);
+      // Record the statement position right here if the statement is not
+      // breakable. For breakable statements the actual recording of the
+      // position will be postponed to the breakable code (typically an IC).
+      bool position_recorded = CodeGenerator::RecordPositions(
+          masm_, stmt->statement_pos(), !checker.is_breakable());
+      // If the position recording did record a new position generate a debug
+      // break slot to make the statement breakable.
+      if (position_recorded) {
+        Debug::GenerateSlot(masm_);
+      }
+    }
+#else
     CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
+#endif
+  }
+}
+
+
+void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
+  if (FLAG_debug_info) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+    if (!Debugger::IsDebuggerActive()) {
+      CodeGenerator::RecordPositions(masm_, pos);
+    } else {
+      // Check if the expression will be breakable without adding a debug break
+      // slot.
+      BreakableStatementChecker checker;
+      checker.Check(expr);
+      // Record a statement position right here if the expression is not
+      // breakable. For breakable expressions the actual recording of the
+      // position will be postponed to the breakable code (typically an IC).
+      // NOTE this will record a statement position for something which might
+      // not be a statement. As stepping in the debugger will only stop at
+      // statement positions this is used for e.g. the condition expression of
+      // a do while loop.
+      bool position_recorded = CodeGenerator::RecordPositions(
+          masm_, pos, !checker.is_breakable());
+      // If the position recording did record a new position generate a debug
+      // break slot to make the statement breakable.
+      if (position_recorded) {
+        Debug::GenerateSlot(masm_);
+      }
+    }
+#else
+    CodeGenerator::RecordPositions(masm_, pos);
+#endif
   }
 }
 
@@ -848,7 +1126,11 @@
   __ bind(&stack_check_success);
 
   __ bind(loop_statement.continue_target());
-  SetStatementPosition(stmt->condition_position());
+
+  // Record the position of the do while condition and make sure it is possible
+  // to break on the condition.
+  SetExpressionPosition(stmt->cond(), stmt->condition_position());
+
   VisitForControl(stmt->cond(), &body, loop_statement.break_target());
 
   __ bind(&stack_limit_hit);
@@ -864,7 +1146,6 @@
 
 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
   Comment cmnt(masm_, "[ WhileStatement");
-  SetStatementPosition(stmt);
   Label body, stack_limit_hit, stack_check_success;
 
   Iteration loop_statement(this, stmt);
@@ -877,6 +1158,9 @@
   Visit(stmt->body());
 
   __ bind(loop_statement.continue_target());
+  // Emit the statement position here as this is where the while statement code
+  // starts.
+  SetStatementPosition(stmt);
 
   // Check stack before looping.
   __ StackLimitCheck(&stack_limit_hit);
@@ -896,7 +1180,6 @@
 
 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
   Comment cmnt(masm_, "[ ForStatement");
-  SetStatementPosition(stmt);
   Label test, body, stack_limit_hit, stack_check_success;
 
   Iteration loop_statement(this, stmt);
@@ -919,6 +1202,9 @@
   }
 
   __ bind(&test);
+  // Emit the statement position here as this is where the for statement code
+  // starts.
+  SetStatementPosition(stmt);
 
   // Check stack before looping.
   __ StackLimitCheck(&stack_limit_hit);
@@ -1064,6 +1350,8 @@
   VisitForControl(expr->condition(), &true_case, &false_case);
 
   __ bind(&true_case);
+  SetExpressionPosition(expr->then_expression(),
+                        expr->then_expression_position());
   Visit(expr->then_expression());
   // If control flow falls through Visit, jump to done.
   if (context_ == Expression::kEffect || context_ == Expression::kValue) {
@@ -1071,6 +1359,8 @@
   }
 
   __ bind(&false_case);
+  SetExpressionPosition(expr->else_expression(),
+                        expr->else_expression_position());
   Visit(expr->else_expression());
   // If control flow falls through Visit, merge it with true case here.
   if (context_ == Expression::kEffect || context_ == Expression::kValue) {
diff --git a/src/full-codegen.h b/src/full-codegen.h
index ac70d99..0ce600b 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -59,6 +59,31 @@
 };
 
 
+// AST node visitor which can tell whether a given statement will be breakable
+// when the code is compiled by the full compiler in the debugger. This means
+// that there will be an IC (load/store/call) in the code generated for the
+// debugger to piggybag on.
+class BreakableStatementChecker: public AstVisitor {
+ public:
+  BreakableStatementChecker() : is_breakable_(false) {}
+
+  void Check(Statement* stmt);
+  void Check(Expression* stmt);
+
+  bool is_breakable() { return is_breakable_; }
+
+ private:
+  // AST node visit functions.
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
+  AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+  bool is_breakable_;
+
+  DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker);
+};
+
+
 // -----------------------------------------------------------------------------
 // Full code generator.
 
@@ -458,6 +483,7 @@
   void SetFunctionPosition(FunctionLiteral* fun);
   void SetReturnPosition(FunctionLiteral* fun);
   void SetStatementPosition(Statement* stmt);
+  void SetExpressionPosition(Expression* expr, int pos);
   void SetStatementPosition(int pos);
   void SetSourcePosition(int pos);
 
diff --git a/src/heap-inl.h b/src/heap-inl.h
index feda2d1..cc558b8 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -118,11 +118,9 @@
           ExternalString::kResourceOffset -
           kHeapObjectTag);
 
-  // Dispose of the C++ object.
-  if (external_string_dispose_callback_ != NULL) {
-    external_string_dispose_callback_(*resource_addr);
-  } else {
-    delete *resource_addr;
+  // Dispose of the C++ object if it has not already been disposed.
+  if (*resource_addr != NULL) {
+    (*resource_addr)->Dispose();
   }
 
   // Clear the resource pointer in the string.
diff --git a/src/heap.cc b/src/heap.cc
index 9f811c0..3115cb3 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -98,8 +98,6 @@
 // set up by ConfigureHeap otherwise.
 int Heap::reserved_semispace_size_ = Heap::max_semispace_size_;
 
-ExternalStringDiposeCallback Heap::external_string_dispose_callback_ = NULL;
-
 List<Heap::GCPrologueCallbackPair> Heap::gc_prologue_callbacks_;
 List<Heap::GCEpilogueCallbackPair> Heap::gc_epilogue_callbacks_;
 
@@ -607,6 +605,9 @@
   EnsureFromSpaceIsCommitted();
 
   if (collector == MARK_COMPACTOR) {
+    // Flush all potentially unused code.
+    FlushCode();
+
     // Perform mark-sweep with optional compaction.
     MarkCompact(tracer);
 
@@ -659,18 +660,19 @@
 
 void Heap::MarkCompact(GCTracer* tracer) {
   gc_state_ = MARK_COMPACT;
-  if (MarkCompactCollector::IsCompacting()) {
-    mc_count_++;
-  } else {
-    ms_count_++;
-  }
-  tracer->set_full_gc_count(mc_count_);
   LOG(ResourceEvent("markcompact", "begin"));
 
   MarkCompactCollector::Prepare(tracer);
 
   bool is_compacting = MarkCompactCollector::IsCompacting();
 
+  if (is_compacting) {
+    mc_count_++;
+  } else {
+    ms_count_++;
+  }
+  tracer->set_full_gc_count(mc_count_ + ms_count_);
+
   MarkCompactPrologue(is_compacting);
 
   MarkCompactCollector::CollectGarbage();
@@ -2185,6 +2187,87 @@
 }
 
 
+// The StackVisitor is used to traverse all the archived threads to see if
+// there are activations on any of the stacks corresponding to the code.
+class FlushingStackVisitor : public ThreadVisitor {
+ public:
+  explicit FlushingStackVisitor(Code* code) : found_(false), code_(code) {}
+
+  void VisitThread(ThreadLocalTop* top) {
+    // If we already found the code in a previous traversed thread we return.
+    if (found_) return;
+
+    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
+      if (code_->contains(it.frame()->pc())) {
+        found_ = true;
+        return;
+      }
+    }
+  }
+  bool FoundCode() {return found_;}
+
+ private:
+  bool found_;
+  Code* code_;
+};
+
+
+static void FlushCodeForFunction(SharedFunctionInfo* function_info) {
+  // The function must be compiled and have the source code available,
+  // to be able to recompile it in case we need the function again.
+  if (!(function_info->is_compiled() && function_info->HasSourceCode())) return;
+
+  // We never flush code for Api functions.
+  if (function_info->IsApiFunction()) return;
+
+  // Only flush code for functions.
+  if (!function_info->code()->kind() == Code::FUNCTION) return;
+
+  // Function must be lazy compilable.
+  if (!function_info->allows_lazy_compilation()) return;
+
+  // If this is a full script wrapped in a function we do no flush the code.
+  if (function_info->is_toplevel()) return;
+
+  // If this function is in the compilation cache we do not flush the code.
+  if (CompilationCache::HasFunction(function_info)) return;
+
+  // Make sure we are not referencing the code from the stack.
+  for (StackFrameIterator it; !it.done(); it.Advance()) {
+    if (function_info->code()->contains(it.frame()->pc())) return;
+  }
+  // Iterate the archived stacks in all threads to check if
+  // the code is referenced.
+  FlushingStackVisitor threadvisitor(function_info->code());
+  ThreadManager::IterateArchivedThreads(&threadvisitor);
+  if (threadvisitor.FoundCode()) return;
+
+  HandleScope scope;
+  // Compute the lazy compilable version of the code.
+  function_info->set_code(*ComputeLazyCompile(function_info->length()));
+}
+
+
+void Heap::FlushCode() {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  // Do not flush code if the debugger is loaded or there are breakpoints.
+  if (Debug::IsLoaded() || Debug::has_break_points()) return;
+#endif
+  HeapObjectIterator it(old_pointer_space());
+  for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
+    if (obj->IsJSFunction()) {
+      JSFunction* jsfunction = JSFunction::cast(obj);
+
+      // The function must have a valid context and not be a builtin.
+      if (jsfunction->unchecked_context()->IsContext() &&
+          !jsfunction->IsBuiltin()) {
+        FlushCodeForFunction(jsfunction->shared());
+      }
+    }
+  }
+}
+
+
 Object* Heap::CreateCode(const CodeDesc& desc,
                          ZoneScopeInfo* sinfo,
                          Code::Flags flags,
diff --git a/src/heap.h b/src/heap.h
index e99c538..0db4008 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -690,11 +690,6 @@
   static bool GarbageCollectionGreedyCheck();
 #endif
 
-  static void SetExternalStringDiposeCallback(
-      ExternalStringDiposeCallback callback) {
-    external_string_dispose_callback_ = callback;
-  }
-
   static void AddGCPrologueCallback(
       GCEpilogueCallback callback, GCType gc_type_filter);
   static void RemoveGCPrologueCallback(GCEpilogueCallback callback);
@@ -1143,9 +1138,6 @@
   // any string when looked up in properties.
   static String* hidden_symbol_;
 
-  static ExternalStringDiposeCallback
-       external_string_dispose_callback_;
-
   // GC callback function, called before and after mark-compact GC.
   // Allocations in the callback function are disallowed.
   struct GCPrologueCallbackPair {
@@ -1274,6 +1266,10 @@
   // Flush the number to string cache.
   static void FlushNumberStringCache();
 
+  // Flush code from functions we do not expect to use again. The code will
+  // be replaced with a lazy compilable version.
+  static void FlushCode();
+
   static const int kInitialSymbolTableSize = 2048;
   static const int kInitialEvalCacheSize = 64;
 
diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
index 9c96e19..a851b42 100644
--- a/src/ia32/assembler-ia32-inl.h
+++ b/src/ia32/assembler-ia32-inl.h
@@ -52,16 +52,21 @@
 void RelocInfo::apply(intptr_t delta) {
   if (rmode_ == RUNTIME_ENTRY || IsCodeTarget(rmode_)) {
     int32_t* p = reinterpret_cast<int32_t*>(pc_);
-    *p -= delta;  // relocate entry
+    *p -= delta;  // Relocate entry.
   } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) {
     // Special handling of js_return when a break point is set (call
     // instruction has been inserted).
     int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
-    *p -= delta;  // relocate entry
+    *p -= delta;  // Relocate entry.
+  } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) {
+    // Special handling of a debug break slot when a break point is set (call
+    // instruction has been inserted).
+    int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
+    *p -= delta;  // Relocate entry.
   } else if (IsInternalReference(rmode_)) {
     // absolute code pointer inside code object moves with the code object.
     int32_t* p = reinterpret_cast<int32_t*>(pc_);
-    *p += delta;  // relocate entry
+    *p += delta;  // Relocate entry.
   }
 }
 
@@ -154,6 +159,11 @@
 }
 
 
+bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
+  return !Assembler::IsNop(pc());
+}
+
+
 void RelocInfo::Visit(ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
@@ -164,8 +174,10 @@
     visitor->VisitExternalReference(target_reference_address());
 #ifdef ENABLE_DEBUGGER_SUPPORT
   } else if (Debug::has_break_points() &&
-             RelocInfo::IsJSReturn(mode) &&
-             IsPatchedReturnSequence()) {
+             ((RelocInfo::IsJSReturn(mode) &&
+              IsPatchedReturnSequence()) ||
+             (RelocInfo::IsDebugBreakSlot(mode) &&
+              IsPatchedDebugBreakSlotSequence()))) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index a436827..d4dff33 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -206,6 +206,7 @@
             patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 
   // Add the requested number of int3 instructions after the call.
+  ASSERT_GE(guard_bytes, 0);
   for (int i = 0; i < guard_bytes; i++) {
     patcher.masm()->int3();
   }
@@ -2371,6 +2372,13 @@
 }
 
 
+void Assembler::RecordDebugBreakSlot() {
+  WriteRecordedPositions();
+  EnsureSpace ensure_space(this);
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
+}
+
+
 void Assembler::RecordComment(const char* msg) {
   if (FLAG_debug_code) {
     EnsureSpace ensure_space(this);
@@ -2393,13 +2401,16 @@
 }
 
 
-void Assembler::WriteRecordedPositions() {
+bool Assembler::WriteRecordedPositions() {
+  bool written = false;
+
   // Write the statement position if it is different from what was written last
   // time.
   if (current_statement_position_ != written_statement_position_) {
     EnsureSpace ensure_space(this);
     RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
     written_statement_position_ = current_statement_position_;
+    written = true;
   }
 
   // Write the position if it is different from what was written last time and
@@ -2409,7 +2420,11 @@
     EnsureSpace ensure_space(this);
     RecordRelocInfo(RelocInfo::POSITION, current_position_);
     written_position_ = current_position_;
+    written = true;
   }
+
+  // Return whether something was written.
+  return written;
 }
 
 
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 76dfe7c..7dcbab5 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -468,9 +468,16 @@
   // to jump to.
   static const int kPatchReturnSequenceAddressOffset = 1;  // JMP imm32.
 
+  // Distance between start of patched debug break slot and the emitted address
+  // to jump to.
+  static const int kPatchDebugBreakSlotAddressOffset = 1;  // JMP imm32.
+
   static const int kCallInstructionLength = 5;
   static const int kJSReturnSequenceLength = 6;
 
+  // The debug break slot must be able to contain a call instruction.
+  static const int kDebugBreakSlotLength = kCallInstructionLength;
+
   // ---------------------------------------------------------------------------
   // Code generation
   //
@@ -809,13 +816,16 @@
   // Mark address of the ExitJSFrame code.
   void RecordJSReturn();
 
+  // Mark address of a debug break slot.
+  void RecordDebugBreakSlot();
+
   // Record a comment relocation entry that can be used by a disassembler.
   // Use --debug_code to enable.
   void RecordComment(const char* msg);
 
   void RecordPosition(int pos);
   void RecordStatementPosition(int pos);
-  void WriteRecordedPositions();
+  bool WriteRecordedPositions();
 
   // Writes a single word of data in the code stream.
   // Used for inline tables, e.g., jump-tables.
@@ -833,6 +843,8 @@
   // Get the number of bytes available in the buffer.
   inline int available_space() const { return reloc_info_writer.pos() - pc_; }
 
+  static bool IsNop(Address addr) { return *addr == 0x90; }
+
   // Avoid overflows for displacements etc.
   static const int kMaximalBufferSize = 512*MB;
   static const int kMinimalBufferSize = 4*KB;
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index b3ddad9..180b9a6 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -316,7 +316,9 @@
   static bool ShouldGenerateLog(Expression* type);
 #endif
 
-  static void RecordPositions(MacroAssembler* masm, int pos);
+  static bool RecordPositions(MacroAssembler* masm,
+                              int pos,
+                              bool right_here = false);
 
   // Accessors
   MacroAssembler* masm() { return masm_; }
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index 9780f3b..9b558bd 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -69,6 +69,27 @@
 }
 
 
+bool BreakLocationIterator::IsDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  // Check whether the debug break slot instructions have been patched.
+  return rinfo()->IsPatchedDebugBreakSlotSequence();
+}
+
+
+void BreakLocationIterator::SetDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  rinfo()->PatchCodeWithCall(
+      Debug::debug_break_slot()->entry(),
+      Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
+}
+
+
 #define __ ACCESS_MASM(masm)
 
 
@@ -208,10 +229,31 @@
 }
 
 
+void Debug::GenerateSlot(MacroAssembler* masm) {
+  // Generate enough nop's to make space for a call instruction.
+  Label check_codesize;
+  __ bind(&check_codesize);
+  __ RecordDebugBreakSlot();
+  for (int i = 0; i < Assembler::kDebugBreakSlotLength; i++) {
+    __ nop();
+  }
+  ASSERT_EQ(Assembler::kDebugBreakSlotLength,
+            masm->SizeOfCodeGeneratedSince(&check_codesize));
+}
+
+
+void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
+  // In the places where a debug break slot is inserted no registers can contain
+  // object pointers.
+  Generate_DebugBreakCallHelper(masm, 0, true);
+}
+
+
 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
   masm->ret(0);
 }
 
+
 // FrameDropper is a code replacement for a JavaScript frame with possibly
 // several frames above.
 // There is no calling conventions here, because it never actually gets called,
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 44afdd6..dc4c27e 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -924,14 +924,18 @@
         break;
 
       case 0xF6:
-        { int mod, regop, rm;
-          get_modrm(*(data+1), &mod, &regop, &rm);
-          if (mod == 3 && regop == eax) {
-            AppendToBuffer("test_b %s,%d", NameOfCPURegister(rm), *(data+2));
+        { data++;
+          int mod, regop, rm;
+          get_modrm(*data, &mod, &regop, &rm);
+          if (regop == eax) {
+            AppendToBuffer("test_b ");
+            data += PrintRightOperand(data);
+            int32_t imm = *data;
+            AppendToBuffer(",0x%x", imm);
+            data++;
           } else {
             UnimplementedInstruction();
           }
-          data += 3;
         }
         break;
 
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 0dc3e0f..95afb4a 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -273,8 +273,10 @@
   }
 
   void VisitDebugTarget(RelocInfo* rinfo) {
-    ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
-           rinfo->IsPatchedReturnSequence());
+    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
+            rinfo->IsPatchedReturnSequence()) ||
+           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
+            rinfo->IsPatchedDebugBreakSlotSequence()));
     HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address());
     MarkCompactCollector::MarkObject(code);
   }
@@ -1106,8 +1108,10 @@
   }
 
   void VisitDebugTarget(RelocInfo* rinfo) {
-    ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
-           rinfo->IsPatchedReturnSequence());
+    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
+            rinfo->IsPatchedReturnSequence()) ||
+           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
+            rinfo->IsPatchedDebugBreakSlotSequence()));
     Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
     VisitPointer(&target);
     rinfo->set_call_address(Code::cast(target)->instruction_start());
@@ -1856,8 +1860,10 @@
   }
 
   void VisitDebugTarget(RelocInfo* rinfo) {
-    ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
-           rinfo->IsPatchedReturnSequence());
+    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
+            rinfo->IsPatchedReturnSequence()) ||
+           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
+            rinfo->IsPatchedDebugBreakSlotSequence()));
     Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
     VisitPointer(&target);
     rinfo->set_call_address(
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index d9617dc..a3b316b 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -1046,13 +1046,16 @@
 }
 
 
-void Assembler::WriteRecordedPositions() {
+bool Assembler::WriteRecordedPositions() {
+  bool written = false;
+
   // Write the statement position if it is different from what was written last
   // time.
   if (current_statement_position_ != written_statement_position_) {
     CheckBuffer();
     RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
     written_statement_position_ = current_statement_position_;
+    written = true;
   }
 
   // Write the position if it is different from what was written last time and
@@ -1062,7 +1065,11 @@
     CheckBuffer();
     RecordRelocInfo(RelocInfo::POSITION, current_position_);
     written_position_ = current_position_;
+    written = true;
   }
+
+  // Return whether something was written.
+  return written;
 }
 
 
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index cc730f2..b7c3ebc 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -355,6 +355,9 @@
   // to jump to.
   static const int kPatchReturnSequenceAddressOffset = kInstrSize;
 
+  // Distance between start of patched debug break slot and the emitted address
+  // to jump to.
+  static const int kPatchDebugBreakSlotAddressOffset = kInstrSize;
 
   // ---------------------------------------------------------------------------
   // Code generation.
@@ -518,7 +521,7 @@
 
   void RecordPosition(int pos);
   void RecordStatementPosition(int pos);
-  void WriteRecordedPositions();
+  bool WriteRecordedPositions();
 
   int32_t pc_offset() const { return pc_ - buffer_; }
   int32_t current_position() const { return current_position_; }
diff --git a/src/objects-inl.h b/src/objects-inl.h
index fceb76f..4112f93 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2468,6 +2468,10 @@
                compiler_hints,
                try_full_codegen,
                kTryFullCodegen)
+BOOL_ACCESSORS(SharedFunctionInfo,
+               compiler_hints,
+               allows_lazy_compilation,
+               kAllowLazyCompilation)
 
 #if V8_HOST_ARCH_32_BIT
 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
diff --git a/src/objects.cc b/src/objects.cc
index dffacf7..1e4d4a4 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5264,8 +5264,10 @@
 
 
 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
-  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
-         rinfo->IsPatchedReturnSequence());
+  ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
+          rinfo->IsPatchedReturnSequence()) ||
+         (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
+          rinfo->IsPatchedDebugBreakSlotSequence()));
   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
   Object* old_target = target;
   VisitPointer(&target);
@@ -5278,6 +5280,7 @@
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
+                  RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
 
   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
diff --git a/src/objects.h b/src/objects.h
index 94b2253..095dd98 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3308,6 +3308,12 @@
   inline bool try_full_codegen();
   inline void set_try_full_codegen(bool flag);
 
+  // Indicates if this function can be lazy compiled.
+  // This is used to determine if we can safely flush code from a function
+  // when doing GC if we expect that the function will no longer be used.
+  inline bool allows_lazy_compilation();
+  inline void set_allows_lazy_compilation(bool flag);
+
   // Check whether a inlined constructor can be generated with the given
   // prototype.
   bool CanGenerateInlineConstructor(Object* prototype);
@@ -3433,6 +3439,7 @@
   // Bit positions in compiler_hints.
   static const int kHasOnlySimpleThisPropertyAssignments = 0;
   static const int kTryFullCodegen = 1;
+  static const int kAllowLazyCompilation = 2;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
 };
diff --git a/src/parser.cc b/src/parser.cc
index bbf71bc..31bac91 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2867,10 +2867,13 @@
   // In parsing the first assignment expression in conditional
   // expressions we always accept the 'in' keyword; see ECMA-262,
   // section 11.12, page 58.
+  int left_position = scanner().peek_location().beg_pos;
   Expression* left = ParseAssignmentExpression(true, CHECK_OK);
   Expect(Token::COLON, CHECK_OK);
+  int right_position = scanner().peek_location().beg_pos;
   Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
-  return NEW(Conditional(expression, left, right));
+  return NEW(Conditional(expression, left, right,
+                         left_position, right_position));
 }
 
 
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 105c1a8..44163a0 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -55,7 +55,7 @@
 
 
 int TokenEnumerator::GetTokenId(Object* token) {
-  if (token == NULL) return CodeEntry::kNoSecurityToken;
+  if (token == NULL) return TokenEnumerator::kNoSecurityToken;
   for (int i = 0; i < token_locations_.length(); ++i) {
     if (*token_locations_[i] == token && !token_removed_[i]) return i;
   }
@@ -86,6 +86,37 @@
 }
 
 
+StringsStorage::StringsStorage()
+    : names_(StringsMatch) {
+}
+
+
+StringsStorage::~StringsStorage() {
+  for (HashMap::Entry* p = names_.Start();
+       p != NULL;
+       p = names_.Next(p)) {
+    DeleteArray(reinterpret_cast<const char*>(p->value));
+  }
+}
+
+
+const char* StringsStorage::GetName(String* name) {
+  if (name->IsString()) {
+    char* c_name =
+        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
+    HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true);
+    if (cache_entry->value == NULL) {
+      // New entry added.
+      cache_entry->value = c_name;
+    } else {
+      DeleteArray(c_name);
+    }
+    return reinterpret_cast<const char*>(cache_entry->value);
+  }
+  return "";
+}
+
+
 const char* CodeEntry::kEmptyNamePrefix = "";
 unsigned CodeEntry::next_call_uid_ = 1;
 
@@ -171,7 +202,7 @@
                   "(root)",
                   "",
                   0,
-                  CodeEntry::kNoSecurityToken),
+                  TokenEnumerator::kNoSecurityToken),
       root_(new ProfileNode(this, &root_entry_)) {
 }
 
@@ -248,11 +279,11 @@
 
  private:
   bool IsTokenAcceptable(int token, int parent_token) {
-    if (token == CodeEntry::kNoSecurityToken
+    if (token == TokenEnumerator::kNoSecurityToken
         || token == security_token_id_) return true;
-    if (token == CodeEntry::kInheritsSecurityToken) {
-      ASSERT(parent_token != CodeEntry::kInheritsSecurityToken);
-      return parent_token == CodeEntry::kNoSecurityToken
+    if (token == TokenEnumerator::kInheritsSecurityToken) {
+      ASSERT(parent_token != TokenEnumerator::kInheritsSecurityToken);
+      return parent_token == TokenEnumerator::kNoSecurityToken
           || parent_token == security_token_id_;
     }
     return false;
@@ -373,7 +404,7 @@
 
 
 CpuProfile* CpuProfile::FilteredClone(int security_token_id) {
-  ASSERT(security_token_id != CodeEntry::kNoSecurityToken);
+  ASSERT(security_token_id != TokenEnumerator::kNoSecurityToken);
   CpuProfile* clone = new CpuProfile(title_, uid_);
   clone->top_down_.FilteredClone(&top_down_, security_token_id);
   clone->bottom_up_.FilteredClone(&bottom_up_, security_token_id);
@@ -438,8 +469,7 @@
 
 
 CpuProfilesCollection::CpuProfilesCollection()
-    : function_and_resource_names_(StringsMatch),
-      profiles_uids_(UidsMatch),
+    : profiles_uids_(UidsMatch),
       current_profiles_semaphore_(OS::CreateSemaphore(1)) {
   // Create list of unabridged profiles.
   profiles_by_token_.Add(new List<CpuProfile*>());
@@ -470,11 +500,6 @@
   profiles_by_token_.Iterate(DeleteProfilesList);
   code_entries_.Iterate(DeleteCodeEntry);
   args_count_names_.Iterate(DeleteArgsCountName);
-  for (HashMap::Entry* p = function_and_resource_names_.Start();
-       p != NULL;
-       p = function_and_resource_names_.Next(p)) {
-    DeleteArray(reinterpret_cast<const char*>(p->value));
-  }
 }
 
 
@@ -517,7 +542,7 @@
     profile->CalculateTotalTicks();
     profile->SetActualSamplingRate(actual_sampling_rate);
     List<CpuProfile*>* unabridged_list =
-        profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
+        profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
     unabridged_list->Add(profile);
     HashMap::Entry* entry =
         profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()),
@@ -550,8 +575,8 @@
     return NULL;
   }
   List<CpuProfile*>* unabridged_list =
-      profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
-  if (security_token_id == CodeEntry::kNoSecurityToken) {
+      profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
+  if (security_token_id == TokenEnumerator::kNoSecurityToken) {
     return unabridged_list->at(index);
   }
   List<CpuProfile*>* list = GetProfilesList(security_token_id);
@@ -564,7 +589,7 @@
 
 
 int CpuProfilesCollection::TokenToIndex(int security_token_id) {
-  ASSERT(CodeEntry::kNoSecurityToken == -1);
+  ASSERT(TokenEnumerator::kNoSecurityToken == -1);
   return security_token_id + 1;  // kNoSecurityToken -> 0, 0 -> 1, ...
 }
 
@@ -575,7 +600,7 @@
   const int lists_to_add = index - profiles_by_token_.length() + 1;
   if (lists_to_add > 0) profiles_by_token_.AddBlock(NULL, lists_to_add);
   List<CpuProfile*>* unabridged_list =
-      profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
+      profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
   const int current_count = unabridged_list->length();
   if (profiles_by_token_[index] == NULL) {
     profiles_by_token_[index] = new List<CpuProfile*>(current_count);
@@ -589,8 +614,8 @@
 
 List<CpuProfile*>* CpuProfilesCollection::Profiles(int security_token_id) {
   List<CpuProfile*>* unabridged_list =
-      profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
-  if (security_token_id == CodeEntry::kNoSecurityToken) {
+      profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
+  if (security_token_id == TokenEnumerator::kNoSecurityToken) {
     return unabridged_list;
   }
   List<CpuProfile*>* list = GetProfilesList(security_token_id);
@@ -613,7 +638,7 @@
                                    GetFunctionName(name),
                                    GetName(resource_name),
                                    line_number,
-                                   CodeEntry::kNoSecurityToken);
+                                   TokenEnumerator::kNoSecurityToken);
   code_entries_.Add(entry);
   return entry;
 }
@@ -626,7 +651,7 @@
                                    GetFunctionName(name),
                                    "",
                                    v8::CpuProfileNode::kNoLineNumberInfo,
-                                   CodeEntry::kNoSecurityToken);
+                                   TokenEnumerator::kNoSecurityToken);
   code_entries_.Add(entry);
   return entry;
 }
@@ -640,7 +665,7 @@
                                    GetName(name),
                                    "",
                                    v8::CpuProfileNode::kNoLineNumberInfo,
-                                   CodeEntry::kInheritsSecurityToken);
+                                   TokenEnumerator::kInheritsSecurityToken);
   code_entries_.Add(entry);
   return entry;
 }
@@ -653,7 +678,7 @@
                                    GetName(args_count),
                                    "",
                                    v8::CpuProfileNode::kNoLineNumberInfo,
-                                   CodeEntry::kInheritsSecurityToken);
+                                   TokenEnumerator::kInheritsSecurityToken);
   code_entries_.Add(entry);
   return entry;
 }
@@ -666,27 +691,6 @@
 }
 
 
-const char* CpuProfilesCollection::GetName(String* name) {
-  if (name->IsString()) {
-    char* c_name =
-        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
-    HashMap::Entry* cache_entry =
-        function_and_resource_names_.Lookup(c_name,
-                                            name->Hash(),
-                                            true);
-    if (cache_entry->value == NULL) {
-      // New entry added.
-      cache_entry->value = c_name;
-    } else {
-      DeleteArray(c_name);
-    }
-    return reinterpret_cast<const char*>(cache_entry->value);
-  } else {
-    return "";
-  }
-}
-
-
 const char* CpuProfilesCollection::GetName(int args_count) {
   ASSERT(args_count >= 0);
   if (args_count_names_.length() <= args_count) {
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 18265f1..be0e94e 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -41,6 +41,9 @@
   ~TokenEnumerator();
   int GetTokenId(Object* token);
 
+  static const int kNoSecurityToken = -1;
+  static const int kInheritsSecurityToken = -2;
+
  private:
   static void TokenRemovedCallback(v8::Persistent<v8::Value> handle,
                                    void* parameter);
@@ -53,6 +56,28 @@
 };
 
 
+// Provides a storage of strings allocated in C++ heap, to hold them
+// forever, even if they disappear from JS heap or external storage.
+class StringsStorage {
+ public:
+  StringsStorage();
+  ~StringsStorage();
+
+  const char* GetName(String* name);
+
+ private:
+  INLINE(static bool StringsMatch(void* key1, void* key2)) {
+    return strcmp(reinterpret_cast<char*>(key1),
+                  reinterpret_cast<char*>(key2)) == 0;
+  }
+
+  // String::Hash -> const char*
+  HashMap names_;
+
+  DISALLOW_COPY_AND_ASSIGN(StringsStorage);
+};
+
+
 class CodeEntry {
  public:
   explicit INLINE(CodeEntry(int security_token_id));
@@ -78,8 +103,6 @@
   void CopyData(const CodeEntry& source);
 
   static const char* kEmptyNamePrefix;
-  static const int kNoSecurityToken = -1;
-  static const int kInheritsSecurityToken = -2;
 
  private:
   unsigned call_uid_;
@@ -257,10 +280,12 @@
                             String* title,
                             double actual_sampling_rate);
   List<CpuProfile*>* Profiles(int security_token_id);
+  const char* GetName(String* name) {
+    return function_and_resource_names_.GetName(name);
+  }
   CpuProfile* GetProfile(int security_token_id, unsigned uid);
   inline bool is_last_profile();
 
-  const char* GetName(String* name);
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
                           String* name, String* resource_name, int line_number);
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name);
@@ -279,17 +304,11 @@
   List<CpuProfile*>* GetProfilesList(int security_token_id);
   int TokenToIndex(int security_token_id);
 
-  INLINE(static bool StringsMatch(void* key1, void* key2)) {
-    return strcmp(reinterpret_cast<char*>(key1),
-                  reinterpret_cast<char*>(key2)) == 0;
-  }
-
   INLINE(static bool UidsMatch(void* key1, void* key2)) {
     return key1 == key2;
   }
 
-  // String::Hash -> const char*
-  HashMap function_and_resource_names_;
+  StringsStorage function_and_resource_names_;
   // args_count -> char*
   List<char*> args_count_names_;
   List<CodeEntry*> code_entries_;
diff --git a/src/serialize.cc b/src/serialize.cc
index 06c6df7..e610e28 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -229,6 +229,10 @@
       DEBUG_ADDRESS,
       Debug::k_after_break_target_address << kDebugIdShift,
       "Debug::after_break_target_address()");
+  Add(Debug_Address(Debug::k_debug_break_slot_address).address(),
+      DEBUG_ADDRESS,
+      Debug::k_debug_break_slot_address << kDebugIdShift,
+      "Debug::debug_break_slot_address()");
   Add(Debug_Address(Debug::k_debug_break_return_address).address(),
       DEBUG_ADDRESS,
       Debug::k_debug_break_return_address << kDebugIdShift,
diff --git a/src/version.cc b/src/version.cc
index 7fa25a2..2172524 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     2
-#define BUILD_NUMBER      15
+#define BUILD_NUMBER      16
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index 4c69510..70bcdb1 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -210,6 +210,10 @@
     // Special handling of js_return when a break point is set (call
     // instruction has been inserted).
     Memory::int32_at(pc_ + 1) -= static_cast<int32_t>(delta);  // relocate entry
+  } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) {
+    // Special handling of debug break slot when a break point is set (call
+    // instruction has been inserted).
+    Memory::int32_at(pc_ + 1) -= static_cast<int32_t>(delta);  // relocate entry
   }
 }
 
@@ -298,6 +302,11 @@
 }
 
 
+bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
+  return !Assembler::IsNop(pc());
+}
+
+
 Address RelocInfo::call_address() {
   ASSERT(IsPatchedReturnSequence());
   return Memory::Address_at(
@@ -341,8 +350,10 @@
     visitor->VisitExternalReference(target_reference_address());
 #ifdef ENABLE_DEBUGGER_SUPPORT
   } else if (Debug::has_break_points() &&
-             RelocInfo::IsJSReturn(mode) &&
-             IsPatchedReturnSequence()) {
+             ((RelocInfo::IsJSReturn(mode) &&
+              IsPatchedReturnSequence()) ||
+             (RelocInfo::IsDebugBreakSlot(mode) &&
+              IsPatchedDebugBreakSlotSequence()))) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 9f26496..d77c09f 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -2800,6 +2800,13 @@
 }
 
 
+void Assembler::RecordDebugBreakSlot() {
+  WriteRecordedPositions();
+  EnsureSpace ensure_space(this);
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
+}
+
+
 void Assembler::RecordComment(const char* msg) {
   if (FLAG_debug_code) {
     EnsureSpace ensure_space(this);
@@ -2822,13 +2829,16 @@
 }
 
 
-void Assembler::WriteRecordedPositions() {
+bool Assembler::WriteRecordedPositions() {
+  bool written = false;
+
   // Write the statement position if it is different from what was written last
   // time.
   if (current_statement_position_ != written_statement_position_) {
     EnsureSpace ensure_space(this);
     RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
     written_statement_position_ = current_statement_position_;
+    written = true;
   }
 
   // Write the position if it is different from what was written last time and
@@ -2838,7 +2848,11 @@
     EnsureSpace ensure_space(this);
     RecordRelocInfo(RelocInfo::POSITION, current_position_);
     written_position_ = current_position_;
+    written = true;
   }
+
+  // Return whether something was written.
+  return written;
 }
 
 
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index cceaccf..c7e737c 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -455,6 +455,11 @@
   // return address.  TODO: Use return sequence length instead.
   // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
   static const int kPatchReturnSequenceAddressOffset = 13 - 4;
+  // Distance between start of patched debug break slot and where the
+  // 32-bit displacement of a near call would be, relative to the pushed
+  // return address.  TODO: Use return sequence length instead.
+  // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
+  static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
   // TODO(X64): Rename this, removing the "Real", after changing the above.
   static const int kRealPatchReturnSequenceAddressOffset = 2;
 
@@ -463,6 +468,10 @@
   static const int kCallInstructionLength = 13;
   static const int kJSReturnSequenceLength = 13;
 
+  // The debug break slot must be able to contain a call instruction.
+  static const int kDebugBreakSlotLength = kCallInstructionLength;
+
+
   // ---------------------------------------------------------------------------
   // Code generation
   //
@@ -1135,13 +1144,16 @@
   // Mark address of the ExitJSFrame code.
   void RecordJSReturn();
 
+  // Mark address of a debug break slot.
+  void RecordDebugBreakSlot();
+
   // Record a comment relocation entry that can be used by a disassembler.
   // Use --debug_code to enable.
   void RecordComment(const char* msg);
 
   void RecordPosition(int pos);
   void RecordStatementPosition(int pos);
-  void WriteRecordedPositions();
+  bool WriteRecordedPositions();
 
   int pc_offset() const  { return static_cast<int>(pc_ - buffer_); }
   int current_statement_position() const { return current_statement_position_; }
@@ -1159,6 +1171,8 @@
     return static_cast<int>(reloc_info_writer.pos() - pc_);
   }
 
+  static bool IsNop(Address addr) { return *addr == 0x90; }
+
   // Avoid overflows for displacements etc.
   static const int kMaximalBufferSize = 512*MB;
   static const int kMinimalBufferSize = 4*KB;
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 823a257..5b1c8af 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -314,7 +314,9 @@
   static bool ShouldGenerateLog(Expression* type);
 #endif
 
-  static void RecordPositions(MacroAssembler* masm, int pos);
+  static bool RecordPositions(MacroAssembler* masm,
+                              int pos,
+                              bool right_here = false);
 
   // Accessors
   MacroAssembler* masm() { return masm_; }
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 2f62cba..9659254 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -181,10 +181,31 @@
 }
 
 
+void Debug::GenerateSlot(MacroAssembler* masm) {
+  // Generate enough nop's to make space for a call instruction.
+  Label check_codesize;
+  __ bind(&check_codesize);
+  __ RecordDebugBreakSlot();
+  for (int i = 0; i < Assembler::kDebugBreakSlotLength; i++) {
+    __ nop();
+  }
+  ASSERT_EQ(Assembler::kDebugBreakSlotLength,
+            masm->SizeOfCodeGeneratedSince(&check_codesize));
+}
+
+
+void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
+  // In the places where a debug break slot is inserted no registers can contain
+  // object pointers.
+  Generate_DebugBreakCallHelper(masm, 0, true);
+}
+
+
 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
   masm->Abort("LiveEdit frame dropping is not supported on x64");
 }
 
+
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   masm->Abort("LiveEdit frame dropping is not supported on x64");
 }
@@ -217,6 +238,28 @@
       Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
 }
 
+
+bool BreakLocationIterator::IsDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  // Check whether the debug break slot instructions have been patched.
+  return !Assembler::IsNop(rinfo()->pc());
+}
+
+
+void BreakLocationIterator::SetDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  rinfo()->PatchCodeWithCall(
+      Debug::debug_break_slot()->entry(),
+      Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
+}
+
+
 #endif  // ENABLE_DEBUGGER_SUPPORT
 
 } }  // namespace v8::internal
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index b520e56..9123125 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -612,30 +612,33 @@
 }
 
 
-static int dispose_count = 0;
-static void DisposeExternalStringCount(
-    String::ExternalStringResourceBase* resource) {
-  dispose_count++;
-}
+class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
+ public:
+  static int dispose_calls;
+
+  TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
+      : TestAsciiResource(data),
+        dispose_(dispose) { }
+
+  void Dispose() {
+    ++dispose_calls;
+    if (dispose_) delete this;
+  }
+ private:
+  bool dispose_;
+};
 
 
-static void DisposeExternalStringDeleteAndCount(
-    String::ExternalStringResourceBase* resource) {
-  delete resource;
-  dispose_count++;
-}
+int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
 
 
-TEST(ExternalStringWithResourceDisposeCallback) {
+TEST(ExternalStringWithDisposeHandling) {
   const char* c_source = "1 + 2 * 3";
 
-  // Set an external string collected callback which does not delete the object.
-  v8::V8::SetExternalStringDiposeCallback(DisposeExternalStringCount);
-
   // Use a stack allocated external string resource allocated object.
-  dispose_count = 0;
   TestAsciiResource::dispose_count = 0;
-  TestAsciiResource res_stack(i::StrDup(c_source));
+  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
+  TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
   {
     v8::HandleScope scope;
     LocalContext env;
@@ -649,16 +652,14 @@
   }
   v8::internal::CompilationCache::Clear();
   v8::internal::Heap::CollectAllGarbage(false);
-  CHECK_EQ(1, dispose_count);
+  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
   CHECK_EQ(0, TestAsciiResource::dispose_count);
 
-  // Set an external string collected callback which does delete the object.
-  v8::V8::SetExternalStringDiposeCallback(DisposeExternalStringDeleteAndCount);
-
   // Use a heap allocated external string resource allocated object.
-  dispose_count = 0;
   TestAsciiResource::dispose_count = 0;
-  TestAsciiResource* res_heap = new TestAsciiResource(i::StrDup(c_source));
+  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
+  TestAsciiResource* res_heap =
+      new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
   {
     v8::HandleScope scope;
     LocalContext env;
@@ -672,7 +673,7 @@
   }
   v8::internal::CompilationCache::Clear();
   v8::internal::Heap::CollectAllGarbage(false);
-  CHECK_EQ(1, dispose_count);
+  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
 
@@ -8497,6 +8498,30 @@
 }
 
 
+// Verifies that the Handle<String> and const char* versions of the API produce
+// the same results (at least for one trivial case).
+TEST(PreCompileAPIVariationsAreSame) {
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+
+  const char* cstring = "function foo(a) { return a+1; }";
+  v8::ScriptData* sd_from_cstring =
+      v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
+
+  TestAsciiResource* resource = new TestAsciiResource(cstring);
+  v8::ScriptData* sd_from_istring = v8::ScriptData::PreCompile(
+      v8::String::NewExternal(resource));
+
+  CHECK_EQ(sd_from_cstring->Length(), sd_from_istring->Length());
+  CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
+                     sd_from_istring->Data(),
+                     sd_from_cstring->Length()));
+
+  delete sd_from_cstring;
+  delete sd_from_istring;
+}
+
+
 // This tests that we do not allow dictionary load/call inline caches
 // to use functions that have not yet been compiled.  The potential
 // problem of loading a function that has not yet been compiled can
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index f587fc8..0e6f09d 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -16,6 +16,7 @@
 using i::ProfileGenerator;
 using i::ProfileNode;
 using i::ProfilerEventsProcessor;
+using i::TokenEnumerator;
 
 
 TEST(StartStop) {
@@ -115,7 +116,7 @@
   processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
   processor.CodeDeleteEvent(ToAddress(0x1600));
   processor.FunctionCreateEvent(ToAddress(0x1700), ToAddress(0x1000),
-                                CodeEntry::kNoSecurityToken);
+                                TokenEnumerator::kNoSecurityToken);
   // Enqueue a tick event to enable code events processing.
   EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
 
@@ -178,7 +179,7 @@
   processor.Stop();
   processor.Join();
   CpuProfile* profile =
-      profiles.StopProfiling(CodeEntry::kNoSecurityToken, "", 1);
+      profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
   CHECK_NE(NULL, profile);
 
   // Check call trees.
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 612e4fc..4c3ff5e 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -1231,6 +1231,11 @@
   SetBreakPoint(foo, 0);
   CallWithBreakPoints(env->Global(), foo, 1, 25);
 
+  // Test debug break slot break point with garbage collection.
+  foo = CompileFunction(&env, "function foo(){var a;}", "foo");
+  SetBreakPoint(foo, 0);
+  CallWithBreakPoints(env->Global(), foo, 1, 25);
+
   v8::Debug::SetDebugEventListener(NULL);
   CheckDebuggerUnloaded();
 }
@@ -1660,7 +1665,7 @@
   f->Call(env->Global(), 0, NULL);
   CHECK_EQ(1, break_point_hit_count);
 
-  ChangeScriptBreakPointConditionFromJS(sbp1, "a % 2 == 0");
+  ChangeScriptBreakPointConditionFromJS(sbp1, "x % 2 == 0");
   break_point_hit_count = 0;
   for (int i = 0; i < 10; i++) {
     f->Call(env->Global(), 0, NULL);
@@ -2144,17 +2149,19 @@
   v8::Local<v8::Function> foo = CompileFunction(&env,
     "function foo(x) {"
     "  var a;"
-    "  y=0; /* To ensure break location.*/"
+    "  y=0;"  // To ensure break location 1.
     "  a=x;"
+    "  y=0;"  // To ensure break location 2.
     "}",
     "foo");
-  const int foo_break_position = 15;
+  const int foo_break_position_1 = 15;
+  const int foo_break_position_2 = 29;
 
   // Arguments with one parameter "Hello, world!"
   v8::Handle<v8::Value> argv_foo[1] = { v8::String::New("Hello, world!") };
 
   // Call foo with breakpoint set before a=x and undefined as parameter.
-  int bp = SetBreakPoint(foo, foo_break_position);
+  int bp = SetBreakPoint(foo, foo_break_position_1);
   checks = checks_uu;
   foo->Call(env->Global(), 0, NULL);
 
@@ -2164,7 +2171,7 @@
 
   // Call foo with breakpoint set after a=x and parameter "Hello, world!".
   ClearBreakPoint(bp);
-  SetBreakPoint(foo, foo_break_position + 1);
+  SetBreakPoint(foo, foo_break_position_2);
   checks = checks_hh;
   foo->Call(env->Global(), 1, argv_foo);
 
@@ -2426,6 +2433,9 @@
   v8::HandleScope scope;
   DebugLocalContext env;
 
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
   // Create a function for testing stepping of keyed load. The statement 'y=1'
   // is there to have more than one breakable statement in the loop, TODO(315).
   v8::Local<v8::Function> foo = CompileFunction(
@@ -2451,9 +2461,6 @@
   v8::Handle<v8::Value> args[kArgc] = { a };
   foo->Call(env->Global(), kArgc, args);
 
-  // Register a debug event listener which steps and counts.
-  v8::Debug::SetDebugEventListener(DebugEventStep);
-
   // Setup break point and step through the function.
   SetBreakPoint(foo, 3);
   step_action = StepNext;
@@ -2461,7 +2468,7 @@
   foo->Call(env->Global(), kArgc, args);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(22, break_point_hit_count);
+  CHECK_EQ(33, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener(NULL);
   CheckDebuggerUnloaded();
@@ -2473,6 +2480,9 @@
   v8::HandleScope scope;
   DebugLocalContext env;
 
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
   // Create a function for testing stepping of keyed store. The statement 'y=1'
   // is there to have more than one breakable statement in the loop, TODO(315).
   v8::Local<v8::Function> foo = CompileFunction(
@@ -2497,9 +2507,6 @@
   v8::Handle<v8::Value> args[kArgc] = { a };
   foo->Call(env->Global(), kArgc, args);
 
-  // Register a debug event listener which steps and counts.
-  v8::Debug::SetDebugEventListener(DebugEventStep);
-
   // Setup break point and step through the function.
   SetBreakPoint(foo, 3);
   step_action = StepNext;
@@ -2507,7 +2514,7 @@
   foo->Call(env->Global(), kArgc, args);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(22, break_point_hit_count);
+  CHECK_EQ(32, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener(NULL);
   CheckDebuggerUnloaded();
@@ -2519,6 +2526,9 @@
   v8::HandleScope scope;
   DebugLocalContext env;
 
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
   // Create a function for testing stepping of named load.
   v8::Local<v8::Function> foo = CompileFunction(
       &env,
@@ -2541,9 +2551,6 @@
   // Call function without any break points to ensure inlining is in place.
   foo->Call(env->Global(), 0, NULL);
 
-  // Register a debug event listener which steps and counts.
-  v8::Debug::SetDebugEventListener(DebugEventStep);
-
   // Setup break point and step through the function.
   SetBreakPoint(foo, 4);
   step_action = StepNext;
@@ -2551,7 +2558,7 @@
   foo->Call(env->Global(), 0, NULL);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(41, break_point_hit_count);
+  CHECK_EQ(53, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener(NULL);
   CheckDebuggerUnloaded();
@@ -2563,6 +2570,9 @@
   v8::HandleScope scope;
   DebugLocalContext env;
 
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
   // Create a function for testing stepping.
   v8::Local<v8::Function> foo = CompileFunction(&env,
       "function bar() {};"
@@ -2573,15 +2583,12 @@
       "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
   SetBreakPoint(foo, 0);
 
-  // Register a debug event listener which steps and counts.
-  v8::Debug::SetDebugEventListener(DebugEventStep);
-
   step_action = StepIn;
   break_point_hit_count = 0;
   foo->Call(env->Global(), 0, NULL);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(8, break_point_hit_count);
+  CHECK_EQ(11, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener(NULL);
   CheckDebuggerUnloaded();
@@ -2601,6 +2608,66 @@
 }
 
 
+TEST(DebugStepDeclarations) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const char* src = "function foo() { "
+                    "  var a;"
+                    "  var b = 1;"
+                    "  var c = foo;"
+                    "  var d = Math.floor;"
+                    "  var e = b + d(1.2);"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 0);
+
+  // Stepping through the declarations.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(6, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepLocals) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const char* src = "function foo() { "
+                    "  var a,b;"
+                    "  a = 1;"
+                    "  b = a + 2;"
+                    "  b = 1 + 2 + 3;"
+                    "  a = Math.floor(b);"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 0);
+
+  // Stepping through the declarations.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(6, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
 TEST(DebugStepIf) {
   v8::HandleScope scope;
   DebugLocalContext env;
@@ -2627,14 +2694,14 @@
   break_point_hit_count = 0;
   v8::Handle<v8::Value> argv_true[argc] = { v8::True() };
   foo->Call(env->Global(), argc, argv_true);
-  CHECK_EQ(3, break_point_hit_count);
+  CHECK_EQ(4, break_point_hit_count);
 
   // Stepping through the false part.
   step_action = StepIn;
   break_point_hit_count = 0;
   v8::Handle<v8::Value> argv_false[argc] = { v8::False() };
   foo->Call(env->Global(), argc, argv_false);
-  CHECK_EQ(4, break_point_hit_count);
+  CHECK_EQ(5, break_point_hit_count);
 
   // Get rid of the debug event listener.
   v8::Debug::SetDebugEventListener(NULL);
@@ -2662,6 +2729,7 @@
                     "    case 3:"
                     "      d = 1;"
                     "      e = 1;"
+                    "      f = 1;"
                     "      break;"
                     "  }"
                     "}";
@@ -2673,21 +2741,97 @@
   break_point_hit_count = 0;
   v8::Handle<v8::Value> argv_1[argc] = { v8::Number::New(1) };
   foo->Call(env->Global(), argc, argv_1);
-  CHECK_EQ(4, break_point_hit_count);
+  CHECK_EQ(6, break_point_hit_count);
 
   // Another case.
   step_action = StepIn;
   break_point_hit_count = 0;
   v8::Handle<v8::Value> argv_2[argc] = { v8::Number::New(2) };
   foo->Call(env->Global(), argc, argv_2);
-  CHECK_EQ(3, break_point_hit_count);
+  CHECK_EQ(5, break_point_hit_count);
 
   // Last case.
   step_action = StepIn;
   break_point_hit_count = 0;
   v8::Handle<v8::Value> argv_3[argc] = { v8::Number::New(3) };
   foo->Call(env->Global(), argc, argv_3);
-  CHECK_EQ(4, break_point_hit_count);
+  CHECK_EQ(7, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepWhile) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const int argc = 1;
+  const char* src = "function foo(x) { "
+                    "  var a = 0;"
+                    "  while (a < x) {"
+                    "    a++;"
+                    "  }"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 8);  // "var a = 0;"
+
+  // Looping 10 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
+  foo->Call(env->Global(), argc, argv_10);
+  CHECK_EQ(23, break_point_hit_count);
+
+  // Looping 100 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
+  foo->Call(env->Global(), argc, argv_100);
+  CHECK_EQ(203, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepDoWhile) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const int argc = 1;
+  const char* src = "function foo(x) { "
+                    "  var a = 0;"
+                    "  do {"
+                    "    a++;"
+                    "  } while (a < x)"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 8);  // "var a = 0;"
+
+  // Looping 10 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
+  foo->Call(env->Global(), argc, argv_10);
+  CHECK_EQ(22, break_point_hit_count);
+
+  // Looping 100 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
+  foo->Call(env->Global(), argc, argv_100);
+  CHECK_EQ(202, break_point_hit_count);
 
   // Get rid of the debug event listener.
   v8::Debug::SetDebugEventListener(NULL);
@@ -2733,6 +2877,210 @@
 }
 
 
+TEST(DebugStepForContinue) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const int argc = 1;
+  const char* src = "function foo(x) { "
+                    "  var a = 0;"
+                    "  var b = 0;"
+                    "  var c = 0;"
+                    "  for (var i = 0; i < x; i++) {"
+                    "    a++;"
+                    "    if (a % 2 == 0) continue;"
+                    "    b++;"
+                    "    c++;"
+                    "  }"
+                    "  return b;"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  v8::Handle<v8::Value> result;
+  SetBreakPoint(foo, 8);  // "var a = 0;"
+
+  // Each loop generates 4 or 5 steps depending on whether a is equal.
+
+  // Looping 10 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
+  result = foo->Call(env->Global(), argc, argv_10);
+  CHECK_EQ(5, result->Int32Value());
+  CHECK_EQ(50, break_point_hit_count);
+
+  // Looping 100 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
+  result = foo->Call(env->Global(), argc, argv_100);
+  CHECK_EQ(50, result->Int32Value());
+  CHECK_EQ(455, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepForBreak) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const int argc = 1;
+  const char* src = "function foo(x) { "
+                    "  var a = 0;"
+                    "  var b = 0;"
+                    "  var c = 0;"
+                    "  for (var i = 0; i < 1000; i++) {"
+                    "    a++;"
+                    "    if (a == x) break;"
+                    "    b++;"
+                    "    c++;"
+                    "  }"
+                    "  return b;"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  v8::Handle<v8::Value> result;
+  SetBreakPoint(foo, 8);  // "var a = 0;"
+
+  // Each loop generates 5 steps except for the last (when break is executed)
+  // which only generates 4.
+
+  // Looping 10 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
+  result = foo->Call(env->Global(), argc, argv_10);
+  CHECK_EQ(9, result->Int32Value());
+  CHECK_EQ(53, break_point_hit_count);
+
+  // Looping 100 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
+  result = foo->Call(env->Global(), argc, argv_100);
+  CHECK_EQ(99, result->Int32Value());
+  CHECK_EQ(503, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepForIn) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  v8::Local<v8::Function> foo;
+  const char* src_1 = "function foo() { "
+                      "  var a = [1, 2];"
+                      "  for (x in a) {"
+                      "    b = 0;"
+                      "  }"
+                      "}";
+  foo = CompileFunction(&env, src_1, "foo");
+  SetBreakPoint(foo, 0);  // "var a = ..."
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(6, break_point_hit_count);
+
+  const char* src_2 = "function foo() { "
+                      "  var a = {a:[1, 2, 3]};"
+                      "  for (x in a.a) {"
+                      "    b = 0;"
+                      "  }"
+                      "}";
+  foo = CompileFunction(&env, src_2, "foo");
+  SetBreakPoint(foo, 0);  // "var a = ..."
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(8, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepWith) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const char* src = "function foo(x) { "
+                    "  var a = {};"
+                    "  with (a) {}"
+                    "  with (b) {}"
+                    "}";
+  env->Global()->Set(v8::String::New("b"), v8::Object::New());
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  v8::Handle<v8::Value> result;
+  SetBreakPoint(foo, 8);  // "var a = {};"
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(4, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugConditional) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const char* src = "function foo(x) { "
+                    "  var a;"
+                    "  a = x ? 1 : 2;"
+                    "  return a;"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 0);  // "var a;"
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(5, break_point_hit_count);
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  const int argc = 1;
+  v8::Handle<v8::Value> argv_true[argc] = { v8::True() };
+  foo->Call(env->Global(), argc, argv_true);
+  CHECK_EQ(5, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
 TEST(StepInOutSimple) {
   v8::HandleScope scope;
   DebugLocalContext env;
@@ -2854,7 +3202,7 @@
   // Step through invocation of a.
   step_action = StepIn;
   break_point_hit_count = 0;
-  expected_step_sequence = "abaca";
+  expected_step_sequence = "abbaca";
   a->Call(env->Global(), 0, NULL);
   CHECK_EQ(StrLength(expected_step_sequence),
            break_point_hit_count);
@@ -2923,7 +3271,7 @@
   foo->Call(env->Global(), 0, NULL);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(6, break_point_hit_count);
+  CHECK_EQ(7, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener(NULL);
   CheckDebuggerUnloaded();
@@ -2967,14 +3315,14 @@
   // Check stepping where the if condition in bar is false.
   break_point_hit_count = 0;
   foo->Call(env->Global(), 0, NULL);
-  CHECK_EQ(4, break_point_hit_count);
+  CHECK_EQ(6, break_point_hit_count);
 
   // Check stepping where the if condition in bar is true.
   break_point_hit_count = 0;
   const int argc = 1;
   v8::Handle<v8::Value> argv[argc] = { v8::True() };
   foo->Call(env->Global(), argc, argv);
-  CHECK_EQ(6, break_point_hit_count);
+  CHECK_EQ(8, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener(NULL);
   CheckDebuggerUnloaded();
@@ -3267,14 +3615,13 @@
   b->Call(env->Global(), 0, NULL);
   CHECK_EQ(StrLength(expected_step_sequence),
            break_point_hit_count);
-
   // Step through invocation of d + e.
   v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
   SetBreakPoint(d, 0);
   ChangeBreakOnException(false, true);
   step_action = StepIn;
   break_point_hit_count = 0;
-  expected_step_sequence = "dded";
+  expected_step_sequence = "ddedd";
   d->Call(env->Global(), 0, NULL);
   CHECK_EQ(StrLength(expected_step_sequence),
            break_point_hit_count);
@@ -3283,7 +3630,7 @@
   ChangeBreakOnException(true, true);
   step_action = StepIn;
   break_point_hit_count = 0;
-  expected_step_sequence = "ddeed";
+  expected_step_sequence = "ddeedd";
   d->Call(env->Global(), 0, NULL);
   CHECK_EQ(StrLength(expected_step_sequence),
            break_point_hit_count);
@@ -3294,7 +3641,7 @@
   ChangeBreakOnException(false, true);
   step_action = StepIn;
   break_point_hit_count = 0;
-  expected_step_sequence = "ffghf";
+  expected_step_sequence = "ffghhff";
   f->Call(env->Global(), 0, NULL);
   CHECK_EQ(StrLength(expected_step_sequence),
            break_point_hit_count);
@@ -3303,7 +3650,7 @@
   ChangeBreakOnException(true, true);
   step_action = StepIn;
   break_point_hit_count = 0;
-  expected_step_sequence = "ffghhf";
+  expected_step_sequence = "ffghhhff";
   f->Call(env->Global(), 0, NULL);
   CHECK_EQ(StrLength(expected_step_sequence),
            break_point_hit_count);
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index f94cd45..c8e0197 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -244,6 +244,9 @@
 
   __ test(edx, Immediate(12345));
   __ test(edx, Operand(ebx, ecx, times_8, 10000));
+  __ test(Operand(esi, edi, times_1, -20000000), Immediate(300000000));
+  __ test_b(edx, Operand(ecx, ebx, times_2, 1000));
+  __ test_b(Operand(eax, -20), 0x9A);
   __ nop();
 
   __ xor_(edx, 12345);
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 0a919a1..d30b5ab 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -957,3 +957,42 @@
   // Check that region covering inobject property 1 is marked dirty.
   CHECK(page->IsRegionDirty(clone_addr + (object_size - kPointerSize)));
 }
+
+TEST(TestCodeFlushing) {
+  i::FLAG_allow_natives_syntax = true;
+  InitializeVM();
+  v8::HandleScope scope;
+  const char* source = "function foo() {"
+                       "  var x = 42;"
+                       "  var y = 42;"
+                       "  var z = x + y;"
+                       "};"
+                       "foo()";
+  Handle<String> foo_name = Factory::LookupAsciiSymbol("foo");
+
+  // This compile will add the code to the compilation cache.
+  CompileRun(source);
+
+  // Check function is compiled.
+  Object* func_value = Top::context()->global()->GetProperty(*foo_name);
+  CHECK(func_value->IsJSFunction());
+  Handle<JSFunction> function(JSFunction::cast(func_value));
+  CHECK(function->shared()->is_compiled());
+
+  Heap::CollectAllGarbage(true);
+  Heap::CollectAllGarbage(true);
+
+  // foo should still be in the compilation cache and therefore not
+  // have been removed.
+  CHECK(function->shared()->is_compiled());
+  Heap::CollectAllGarbage(true);
+  Heap::CollectAllGarbage(true);
+  Heap::CollectAllGarbage(true);
+  Heap::CollectAllGarbage(true);
+
+  // foo should no longer be in the compilation cache
+  CHECK(!function->shared()->is_compiled());
+  // Call foo to get it recompiled.
+  CompileRun("foo()");
+  CHECK(function->shared()->is_compiled());
+}
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 418fd36..308f764 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -39,7 +39,7 @@
 
 TEST(TokenEnumerator) {
   TokenEnumerator te;
-  CHECK_EQ(CodeEntry::kNoSecurityToken, te.GetTokenId(NULL));
+  CHECK_EQ(TokenEnumerator::kNoSecurityToken, te.GetTokenId(NULL));
   v8::HandleScope hs;
   v8::Local<v8::String> token1(v8::String::New("1"));
   CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
@@ -65,20 +65,20 @@
 
 TEST(ProfileNodeFindOrAddChild) {
   ProfileNode node(NULL, NULL);
-  CodeEntry entry1(
-      i::Logger::FUNCTION_TAG, "", "aaa", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
   CHECK_NE(NULL, childNode1);
   CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
-  CodeEntry entry2(
-      i::Logger::FUNCTION_TAG, "", "bbb", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   ProfileNode* childNode2 = node.FindOrAddChild(&entry2);
   CHECK_NE(NULL, childNode2);
   CHECK_NE(childNode1, childNode2);
   CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
   CHECK_EQ(childNode2, node.FindOrAddChild(&entry2));
-  CodeEntry entry3(
-      i::Logger::FUNCTION_TAG, "", "ccc", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   ProfileNode* childNode3 = node.FindOrAddChild(&entry3);
   CHECK_NE(NULL, childNode3);
   CHECK_NE(childNode1, childNode3);
@@ -119,12 +119,12 @@
 }  // namespace
 
 TEST(ProfileTreeAddPathFromStart) {
-  CodeEntry entry1(
-      i::Logger::FUNCTION_TAG, "", "aaa", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry2(
-      i::Logger::FUNCTION_TAG, "", "bbb", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry3(
-      i::Logger::FUNCTION_TAG, "", "ccc", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   ProfileTree tree;
   ProfileTreeTestHelper helper(&tree);
   CHECK_EQ(NULL, helper.Walk(&entry1));
@@ -189,12 +189,12 @@
 
 
 TEST(ProfileTreeAddPathFromEnd) {
-  CodeEntry entry1(
-      i::Logger::FUNCTION_TAG, "", "aaa", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry2(
-      i::Logger::FUNCTION_TAG, "", "bbb", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry3(
-      i::Logger::FUNCTION_TAG, "", "ccc", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   ProfileTree tree;
   ProfileTreeTestHelper helper(&tree);
   CHECK_EQ(NULL, helper.Walk(&entry1));
@@ -272,8 +272,8 @@
   CHECK_EQ(1, empty_tree.root()->total_ticks());
   CHECK_EQ(1, empty_tree.root()->self_ticks());
 
-  CodeEntry entry1(
-      i::Logger::FUNCTION_TAG, "", "aaa", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   CodeEntry* e1_path[] = {&entry1};
   Vector<CodeEntry*> e1_path_vec(
       e1_path, sizeof(e1_path) / sizeof(e1_path[0]));
@@ -294,8 +294,8 @@
   CHECK_EQ(1, node1->total_ticks());
   CHECK_EQ(1, node1->self_ticks());
 
-  CodeEntry entry2(
-      i::Logger::FUNCTION_TAG, "", "bbb", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   CodeEntry* e1_e2_path[] = {&entry1, &entry2};
   Vector<CodeEntry*> e1_e2_path_vec(
       e1_e2_path, sizeof(e1_e2_path) / sizeof(e1_e2_path[0]));
@@ -330,8 +330,8 @@
   CodeEntry* e2_path[] = {&entry2};
   Vector<CodeEntry*> e2_path_vec(
       e2_path, sizeof(e2_path) / sizeof(e2_path[0]));
-  CodeEntry entry3(
-      i::Logger::FUNCTION_TAG, "", "ccc", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   CodeEntry* e3_path[] = {&entry3};
   Vector<CodeEntry*> e3_path_vec(
       e3_path, sizeof(e3_path) / sizeof(e3_path[0]));
@@ -394,7 +394,7 @@
   CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0, token0);
   CodeEntry entry4(
       i::Logger::FUNCTION_TAG, "", "ddd", "", 0,
-      CodeEntry::kInheritsSecurityToken);
+      TokenEnumerator::kInheritsSecurityToken);
 
   {
     CodeEntry* e1_e2_path[] = {&entry1, &entry2};
@@ -491,14 +491,14 @@
 
 TEST(CodeMapAddCode) {
   CodeMap code_map;
-  CodeEntry entry1(
-      i::Logger::FUNCTION_TAG, "", "aaa", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry2(
-      i::Logger::FUNCTION_TAG, "", "bbb", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry3(
-      i::Logger::FUNCTION_TAG, "", "ccc", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry4(
-      i::Logger::FUNCTION_TAG, "", "ddd", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
   code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
   code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
@@ -525,10 +525,10 @@
 
 TEST(CodeMapMoveAndDeleteCode) {
   CodeMap code_map;
-  CodeEntry entry1(
-      i::Logger::FUNCTION_TAG, "", "aaa", "", 0, CodeEntry::kNoSecurityToken);
-  CodeEntry entry2(
-      i::Logger::FUNCTION_TAG, "", "bbb", "", 0, CodeEntry::kNoSecurityToken);
+  CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
+  CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0,
+                   TokenEnumerator::kNoSecurityToken);
   code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
   code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
   CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
@@ -601,7 +601,7 @@
   generator.RecordTickSample(sample3);
 
   CpuProfile* profile =
-      profiles.StopProfiling(CodeEntry::kNoSecurityToken, "", 1);
+      profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
   CHECK_NE(NULL, profile);
   ProfileTreeTestHelper top_down_test_helper(profile->top_down());
   CHECK_EQ(NULL, top_down_test_helper.Walk(entry2));
diff --git a/test/mjsunit/const-eval-init.js b/test/mjsunit/const-eval-init.js
index d3636de..5bcd917 100644
--- a/test/mjsunit/const-eval-init.js
+++ b/test/mjsunit/const-eval-init.js
@@ -91,7 +91,7 @@
   var source = "";
   // Introduce 100 properties on the context extension object to force
   // it in slow case.
-  for (var i = 0; i < 100; i++) source += ("var a" + i + " = i;");
+  for (var i = 0; i < 100; i++) source += ("var a" + i + " = " + i + ";");
   source += "const x = 10; assertEquals(10, x); x = 11; assertEquals(10, x)";
   eval(source);
 }
diff --git a/test/mjsunit/debug-conditional-breakpoints.js b/test/mjsunit/debug-conditional-breakpoints.js
index 5859451..bd4cdd1 100644
--- a/test/mjsunit/debug-conditional-breakpoints.js
+++ b/test/mjsunit/debug-conditional-breakpoints.js
@@ -45,7 +45,7 @@
 count = 0;
 function f() {};
 function g() {h(count++)};
-function h(x) {var a=x;};
+function h(x) {var a=x; return a};
 
 
 // Conditional breakpoint which syntax error.
@@ -136,7 +136,7 @@
 
 // Conditional breakpoint which checks a local variable.
 break_point_hit_count = 0;
-bp = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
+bp = Debug.setBreakPoint(h, 0, 23, 'a % 2 == 0');
 for (var i = 0; i < 10; i++) {
   g();
 }
@@ -146,8 +146,8 @@
 
 // Multiple conditional breakpoint which the same condition.
 break_point_hit_count = 0;
-bp1 = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
-bp2 = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
+bp1 = Debug.setBreakPoint(h, 0, 23, 'a % 2 == 0');
+bp2 = Debug.setBreakPoint(h, 0, 23, 'a % 2 == 0');
 for (var i = 0; i < 10; i++) {
   g();
 }
@@ -159,8 +159,8 @@
 
 // Multiple conditional breakpoint which different conditions.
 break_point_hit_count = 0;
-bp1 = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
-bp2 = Debug.setBreakPoint(h, 0, 0, '(a + 1) % 2 == 0');
+bp1 = Debug.setBreakPoint(h, 0, 23, 'a % 2 == 0');
+bp2 = Debug.setBreakPoint(h, 0, 23, '(a + 1) % 2 == 0');
 for (var i = 0; i < 10; i++) {
   g();
 }
diff --git a/test/mjsunit/debug-step.js b/test/mjsunit/debug-step.js
index a887514..2233e36 100644
--- a/test/mjsunit/debug-step.js
+++ b/test/mjsunit/debug-step.js
@@ -55,8 +55,9 @@
 
 // Test debug event for break point.
 function f() {
-  for (i = 0; i < 1000; i++) {  //  Line 1.
-    x = 1;                      //  Line 2.
+  var i;                        // Line 1.
+  for (i = 0; i < 1000; i++) {  // Line 2.
+    x = 1;                      // Line 3.
   }
 };
 
@@ -74,7 +75,7 @@
 // multiple steps have been requested.
 state = 0;
 result = -1;
-bp2 = Debug.setBreakPoint(f, 2);
+bp2 = Debug.setBreakPoint(f, 3);
 f();
 assertEquals(0, result);