Push version 1.2.0 to trunk.

Optimized floating-point operations on ARM.

Added a number of extensions to the debugger API.

Changed the enumeration order for unsigned integer keys to always be numerical order.

Added a "read" extension to the shell sample.

Added support for Array.prototype.reduce and Array.prototype.reduceRight.

Added an option to the SCons build to control Microsoft Visual C++ link-time code generation.

Fixed a number of bugs (in particular issue 315, issue 316, issue 317 and issue 318).


git-svn-id: http://v8.googlecode.com/svn/trunk@1781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index d5c30c7..7e28abd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2009-04-23: Version 1.2.0
+
+        Optimized floating-point operations on ARM.
+
+        Added a number of extensions to the debugger API.
+
+        Changed the enumeration order for unsigned integer keys to always
+        be numerical order.
+
+        Added a "read" extension to the shell sample.
+
+        Added support for Array.prototype.reduce and
+        Array.prototype.reduceRight.
+
+        Added an option to the SCons build to control Microsoft Visual C++
+        link-time code generation.
+
+        Fixed a number of bugs (in particular issue 315, issue 316,
+        issue 317 and issue 318).
+
+
 2009-04-15: Version 1.1.10
 
         Fixed crash bug that occurred when loading a const variable in the
@@ -27,13 +48,13 @@
 
         Changed test-debug/ThreadedDebugging to be non-flaky (issue 96).
 
-        Fixed step-in handling for Function.prototype.apply and call in 
+        Fixed step-in handling for Function.prototype.apply and call in
         the debugger (issue 269).
 
         Fixed v8::Object::DeleteHiddenValue to not bail out when there
         are no hidden properties.
 
-        Added workaround for crash bug, where external symbol table 
+        Added workaround for crash bug, where external symbol table
         entries with deleted resources would lead to NPEs when looking
         up in the symbol table.
 
diff --git a/SConstruct b/SConstruct
index 01083cc..0c8e3c0 100644
--- a/SConstruct
+++ b/SConstruct
@@ -94,6 +94,7 @@
       'CCFLAGS':      ['-g', '-O0'],
       'CPPDEFINES':   ['ENABLE_DISASSEMBLER', 'DEBUG'],
       'os:android': {
+        'CPPDEFINES': ['ENABLE_DEBUGGER_SUPPORT'],
         'CCFLAGS':    ['-mthumb']
       }
     },
@@ -102,13 +103,13 @@
                        '-ffunction-sections'],
       'os:android': {
         'CCFLAGS':    ['-mthumb', '-Os'],
-        'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
+        'CPPDEFINES': ['SK_RELEASE', 'NDEBUG', 'ENABLE_DEBUGGER_SUPPORT']
       }
     },
     'os:linux': {
       'CCFLAGS':      ['-ansi'],
       'library:shared': {
-        'LIBS': ['pthread', 'rt']
+        'LIBS': ['pthread']
       }
     },
     'os:macos': {
@@ -160,14 +161,18 @@
       }
     },
     'mode:release': {
-      'CCFLAGS':      ['/O2', '/GL'],
-      'LINKFLAGS':    ['/OPT:REF', '/OPT:ICF', '/LTCG'],
-      'ARFLAGS':      ['/LTCG'],
+      'CCFLAGS':      ['/O2'],
+      'LINKFLAGS':    ['/OPT:REF', '/OPT:ICF'],
       'msvcrt:static': {
         'CCFLAGS': ['/MT']
       },
       'msvcrt:shared': {
         'CCFLAGS': ['/MD']
+      },
+      'msvcltcg:on': {
+        'CCFLAGS':      ['/GL'],
+        'LINKFLAGS':    ['/LTCG'],
+        'ARFLAGS':      ['/LTCG'],
       }
     },
   }
@@ -224,7 +229,7 @@
 MKSNAPSHOT_EXTRA_FLAGS = {
   'gcc': {
     'os:linux': {
-      'LIBS': ['pthread', 'rt'],
+      'LIBS': ['pthread'],
     },
     'os:macos': {
       'LIBS': ['pthread'],
@@ -238,6 +243,7 @@
   },
   'msvc': {
     'all': {
+      'CPPDEFINES': ['_HAS_EXCEPTIONS=0'],
       'LIBS': ['winmm', 'ws2_32']
     }
   }
@@ -268,7 +274,7 @@
       'LIBPATH': [abspath('.')]
     },
     'os:linux': {
-      'LIBS':         ['pthread', 'rt'],
+      'LIBS':         ['pthread'],
     },
     'os:macos': {
       'LIBS':         ['pthread'],
@@ -307,7 +313,7 @@
       'CCFLAGS': ['-fno-rtti', '-fno-exceptions']
     },
     'os:linux': {
-      'LIBS':         ['pthread', 'rt'],
+      'LIBS':         ['pthread'],
     },
     'os:macos': {
       'LIBS':         ['pthread'],
@@ -359,12 +365,16 @@
     },
     'mode:release': {
       'CCFLAGS':   ['/O2'],
-      'LINKFLAGS': ['/OPT:REF', '/OPT:ICF', '/LTCG'],
+      'LINKFLAGS': ['/OPT:REF', '/OPT:ICF'],
       'msvcrt:static': {
         'CCFLAGS': ['/MT']
       },
       'msvcrt:shared': {
         'CCFLAGS': ['/MD']
+      },
+      'msvcltcg:on': {
+        'CCFLAGS':      ['/GL'],
+        'LINKFLAGS':    ['/LTCG'],
       }
     },
     'mode:debug': {
@@ -387,7 +397,7 @@
       'LIBS': ['readline']
     },
     'os:linux': {
-      'LIBS': ['pthread', 'rt'],
+      'LIBS': ['pthread'],
     },
     'os:macos': {
       'LIBS': ['pthread'],
@@ -473,7 +483,12 @@
   'msvcrt': {
     'values': ['static', 'shared'],
     'default': 'static',
-    'help': 'the type of MSVCRT library to use'
+    'help': 'the type of Microsoft Visual C++ runtime library to use'
+  },
+  'msvcltcg': {
+    'values': ['on', 'off'],
+    'default': 'on',
+    'help': 'use Microsoft Visual C++ link-time code generation'
   },
   'wordsize': {
     'values': ['64', '32'],
diff --git a/include/v8-debug.h b/include/v8-debug.h
index 4c639c1..debeac1 100644
--- a/include/v8-debug.h
+++ b/include/v8-debug.h
@@ -79,48 +79,56 @@
 };
 
 
-/**
- * Debug event callback function.
- *
- * \param event the type of the debug event that triggered the callback
- *   (enum DebugEvent)
- * \param exec_state execution state (JavaScript object)
- * \param event_data event specific data (JavaScript object)
- * \param data value passed by the user to SetDebugEventListener
- */
-typedef void (*DebugEventCallback)(DebugEvent event,
-                                   Handle<Object> exec_state,
-                                   Handle<Object> event_data,
-                                   Handle<Value> data);
-
-
-/**
- * Debug message callback function.
- *
- * \param message the debug message
- * \param length length of the message
- * \param data the data value passed when registering the message handler
- * A DebugMessageHandler does not take posession of the message string,
- * and must not rely on the data persisting after the handler returns.
- */
-typedef void (*DebugMessageHandler)(const uint16_t* message, int length,
-                                    void* data);
-
-/**
- * Debug host dispatch callback function.
- *
- * \param dispatch the dispatch value
- * \param data the data value passed when registering the dispatch handler
- */
-typedef void (*DebugHostDispatchHandler)(void* dispatch,
-                                         void* data);
-
-
-
 class EXPORT Debug {
  public:
+  /**
+   * A client object passed to the v8 debugger whose ownership will be taken by
+   * it. v8 is always responsible for deleting the object.
+   */
+  class ClientData {
+   public:
+    virtual ~ClientData() {}
+  };
+
+
+  /**
+   * Debug event callback function.
+   *
+   * \param event the type of the debug event that triggered the callback
+   *   (enum DebugEvent)
+   * \param exec_state execution state (JavaScript object)
+   * \param event_data event specific data (JavaScript object)
+   * \param data value passed by the user to SetDebugEventListener
+   */
+  typedef void (*EventCallback)(DebugEvent event,
+                                     Handle<Object> exec_state,
+                                     Handle<Object> event_data,
+                                     Handle<Value> data);
+
+
+  /**
+   * Debug message callback function.
+   *
+   * \param message the debug message
+   * \param length length of the message
+   * \param data the data value passed when registering the message handler
+   * \param client_data the data value passed into Debug::SendCommand along
+   *     with the request that led to the message or NULL if the message is an
+   *     asynchronous event. The debugger takes ownership of the data and will
+   *     delete it before dying even if there is no message handler.
+   * A MessageHandler does not take posession of the message string,
+   * and must not rely on the data persisting after the handler returns.
+   */
+  typedef void (*MessageHandler)(const uint16_t* message, int length,
+                                      ClientData* client_data);
+
+  /**
+   * Debug host dispatch callback function.
+   */
+  typedef void (*HostDispatchHandler)();
+
   // Set a C debug event listener.
-  static bool SetDebugEventListener(DebugEventCallback that,
+  static bool SetDebugEventListener(EventCallback that,
                                     Handle<Value> data = Handle<Value>());
 
   // Set a JavaScript debug event listener.
@@ -131,14 +139,14 @@
   static void DebugBreak();
 
   // Message based interface. The message protocol is JSON.
-  static void SetMessageHandler(DebugMessageHandler handler, void* data = NULL,
+  static void SetMessageHandler(MessageHandler handler,
                                 bool message_handler_thread = true);
-  static void SendCommand(const uint16_t* command, int length);
+  static void SendCommand(const uint16_t* command, int length,
+                          ClientData* client_data = NULL);
 
   // Dispatch interface.
-  static void SetHostDispatchHandler(DebugHostDispatchHandler handler,
-                                     void* data = NULL);
-  static void SendHostDispatch(void* dispatch);
+  static void SetHostDispatchHandler(HostDispatchHandler handler,
+                                     int period = 100);
 
  /**
   * Run a JavaScript function in the debugger.
diff --git a/include/v8.h b/include/v8.h
index 1ddaee0..1013cab 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -529,6 +529,13 @@
    * Returns the script id value.
    */
   Local<Value> Id();
+
+  /**
+   * Associate an additional data object with the script. This is mainly used
+   * with the debugger as this data object is only available through the
+   * debugger API.
+   */
+  void SetData(Handle<Value> data);
 };
 
 
@@ -540,9 +547,19 @@
   Local<String> Get() const;
   Local<String> GetSourceLine() const;
 
+  /**
+   * Returns the resource name for the script from where the function causing
+   * the error originates.
+   */
   Handle<Value> GetScriptResourceName() const;
 
   /**
+   * Returns the resource data for the script from where the function causing
+   * the error originates.
+   */
+  Handle<Value> GetScriptData() const;
+
+  /**
    * Returns the number, 1-based, of the line where the error occurred.
    */
   int GetLineNumber() const;
@@ -1028,6 +1045,18 @@
   bool Set(Handle<Value> key,
            Handle<Value> value,
            PropertyAttribute attribs = None);
+
+  // Sets a local property on this object, bypassing interceptors and
+  // overriding accessors or read-only properties.
+  //
+  // Note that if the object has an interceptor the property will be set
+  // locally, but since the interceptor takes precedence the local property
+  // will only be returned if the interceptor doesn't return a value.
+  //
+  // Note also that this only works for named properties.
+  bool ForceSet(Handle<Value> key,
+                Handle<Value> value,
+                PropertyAttribute attribs = None);
   Local<Value> Get(Handle<Value> key);
 
   // TODO(1245389): Replace the type-specific versions of these
diff --git a/samples/shell.cc b/samples/shell.cc
index 087d4fd..27ed293 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -38,6 +38,7 @@
                    bool print_result,
                    bool report_exceptions);
 v8::Handle<v8::Value> Print(const v8::Arguments& args);
+v8::Handle<v8::Value> Read(const v8::Arguments& args);
 v8::Handle<v8::Value> Load(const v8::Arguments& args);
 v8::Handle<v8::Value> Quit(const v8::Arguments& args);
 v8::Handle<v8::Value> Version(const v8::Arguments& args);
@@ -52,6 +53,8 @@
   v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
   // Bind the global 'print' function to the C++ Print callback.
   global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
+  // Bind the global 'read' function to the C++ Read callback.
+  global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
   // Bind the global 'load' function to the C++ Load callback.
   global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
   // Bind the 'quit' function
@@ -135,6 +138,25 @@
 }
 
 
+// The callback that is invoked by v8 whenever the JavaScript 'read'
+// function is called.  This function loads the content of the file named in
+// the argument into a JavaScript string.
+v8::Handle<v8::Value> Read(const v8::Arguments& args) {
+  if (args.Length() != 1) {
+    return v8::ThrowException(v8::String::New("Bad parameters"));
+  }
+  v8::String::Utf8Value file(args[0]);
+  if (*file == NULL) {
+    return v8::ThrowException(v8::String::New("Error loading file"));
+  }
+  v8::Handle<v8::String> source = ReadFile(*file);
+  if (source.IsEmpty()) {
+    return v8::ThrowException(v8::String::New("Error loading file"));
+  }
+  return source;
+}
+
+
 // The callback that is invoked by v8 whenever the JavaScript 'load'
 // function is called.  Loads, compiles and executes its argument
 // JavaScript file.
diff --git a/src/accessors.cc b/src/accessors.cc
index d779eb2..2d6a3a1 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -252,6 +252,24 @@
 
 
 //
+// Accessors::ScriptData
+//
+
+
+Object* Accessors::ScriptGetData(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  return Script::cast(script)->data();
+}
+
+
+const AccessorDescriptor Accessors::ScriptData = {
+  ScriptGetData,
+  IllegalSetter,
+  0
+};
+
+
+//
 // Accessors::ScriptType
 //
 
diff --git a/src/accessors.h b/src/accessors.h
index 938b014..d174c90 100644
--- a/src/accessors.h
+++ b/src/accessors.h
@@ -45,6 +45,7 @@
   V(ScriptId)            \
   V(ScriptLineOffset)    \
   V(ScriptColumnOffset)  \
+  V(ScriptData)          \
   V(ScriptType)          \
   V(ScriptLineEnds)      \
   V(ObjectPrototype)
@@ -84,6 +85,7 @@
   static Object* ScriptGetSource(Object* object, void*);
   static Object* ScriptGetLineOffset(Object* object, void*);
   static Object* ScriptGetColumnOffset(Object* object, void*);
+  static Object* ScriptGetData(Object* object, void*);
   static Object* ScriptGetType(Object* object, void*);
   static Object* ScriptGetLineEnds(Object* object, void*);
   static Object* ObjectGetPrototype(Object* receiver, void*);
diff --git a/src/api.cc b/src/api.cc
index a190b9c..449926c 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1108,6 +1108,19 @@
 }
 
 
+void Script::SetData(v8::Handle<Value> data) {
+  ON_BAILOUT("v8::Script::SetData()", return);
+  LOG_API("Script::SetData");
+  {
+    HandleScope scope;
+    i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+    i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
+    i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
+    script->set_data(*raw_data);
+  }
+}
+
+
 // --- E x c e p t i o n s ---
 
 
@@ -1199,6 +1212,22 @@
 }
 
 
+v8::Handle<Value> Message::GetScriptData() const {
+  if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
+    return Local<Value>();
+  }
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> obj =
+      i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+  // Return this.script.data.
+  i::Handle<i::JSValue> script =
+      i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
+  i::Handle<i::Object> data(i::Script::cast(script->value())->data());
+  return scope.Close(Utils::ToLocal(data));
+}
+
+
 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
                                                i::Handle<i::Object> recv,
                                                int argc,
@@ -1806,6 +1835,26 @@
 }
 
 
+bool v8::Object::ForceSet(v8::Handle<Value> key,
+                          v8::Handle<Value> value,
+                          v8::PropertyAttribute attribs) {
+  ON_BAILOUT("v8::Object::ForceSet()", return false);
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> obj = i::ForceSetProperty(
+      self,
+      key_obj,
+      value_obj,
+      static_cast<PropertyAttributes>(attribs));
+  has_pending_exception = obj.is_null();
+  EXCEPTION_BAILOUT_CHECK(false);
+  return true;
+}
+
+
 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
   ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
   ENTER_V8;
@@ -2373,7 +2422,7 @@
 
 
 const char* v8::V8::GetVersion() {
-  return "1.1.10.4";
+  return "1.2.0";
 }
 
 
@@ -3180,8 +3229,8 @@
 
 // --- D e b u g   S u p p o r t ---
 
-
-bool Debug::SetDebugEventListener(DebugEventCallback that, Handle<Value> data) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
   EnsureInitialized("v8::Debug::SetDebugEventListener()");
   ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
   ENTER_V8;
@@ -3211,31 +3260,27 @@
 }
 
 
-void Debug::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
+void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
                               bool message_handler_thread) {
   EnsureInitialized("v8::Debug::SetMessageHandler");
   ENTER_V8;
-  i::Debugger::SetMessageHandler(handler, data, message_handler_thread);
+  i::Debugger::SetMessageHandler(handler, message_handler_thread);
 }
 
 
-void Debug::SendCommand(const uint16_t* command, int length) {
+void Debug::SendCommand(const uint16_t* command, int length,
+                        ClientData* client_data) {
   if (!i::V8::HasBeenSetup()) return;
-  i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length));
+  i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
+                              client_data);
 }
 
 
-void Debug::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
-                                   void* data) {
+void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
+                                   int period) {
   EnsureInitialized("v8::Debug::SetHostDispatchHandler");
   ENTER_V8;
-  i::Debugger::SetHostDispatchHandler(handler, data);
-}
-
-
-void Debug::SendHostDispatch(void* dispatch) {
-  if (!i::V8::HasBeenSetup()) return;
-  i::Debugger::ProcessHostDispatch(dispatch);
+  i::Debugger::SetHostDispatchHandler(handler, period);
 }
 
 
@@ -3263,7 +3308,7 @@
 bool Debug::EnableAgent(const char* name, int port) {
   return i::Debugger::StartAgent(name, port);
 }
-
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 namespace internal {
 
diff --git a/src/array.js b/src/array.js
index d30a989..0adbf9d 100644
--- a/src/array.js
+++ b/src/array.js
@@ -879,6 +879,62 @@
 }
 
 
+function ArrayReduce(callback, current) {
+  if (!IS_FUNCTION(callback)) {
+    throw MakeTypeError('called_non_callable', [callback]);
+  }
+  // Pull out the length so that modifications to the length in the
+  // loop will not affect the looping.
+  var length = this.length;
+  var i = 0;
+
+  find_initial: if (%_ArgumentsLength() < 2) {
+    for (; i < length; i++) {
+      current = this[i];
+      if (!IS_UNDEFINED(current) || i in this) {
+        i++;
+        break find_initial;
+      }
+    }
+    throw MakeTypeError('reduce_no_initial', []);
+  }
+
+  for (; i < length; i++) {
+    var element = this[i];
+    if (!IS_UNDEFINED(element) || i in this) {
+      current = callback.call(null, current, element, i, this);
+    }
+  }
+  return current;
+}
+
+function ArrayReduceRight(callback, current) {
+  if (!IS_FUNCTION(callback)) {
+    throw MakeTypeError('called_non_callable', [callback]);
+  }
+  var i = this.length - 1;
+
+  find_initial: if (%_ArgumentsLength() < 2) {
+    for (; i >= 0; i--) {
+      current = this[i];
+      if (!IS_UNDEFINED(current) || i in this) {
+        i--;
+        break find_initial;
+      }
+    }
+    throw MakeTypeError('reduce_no_initial', []);
+  }
+
+  for (; i >= 0; i--) {
+    var element = this[i];
+    if (!IS_UNDEFINED(element) || i in this) {
+      current = callback.call(null, current, element, i, this);
+    }
+  }
+  return current;
+}
+
+
 // -------------------------------------------------------------------
 
 
@@ -917,7 +973,9 @@
     "every", ArrayEvery,
     "map", ArrayMap,
     "indexOf", ArrayIndexOf,
-    "lastIndexOf", ArrayLastIndexOf
+    "lastIndexOf", ArrayLastIndexOf,
+    "reduce", ArrayReduce,
+    "reduceRight", ArrayReduceRight
   ));
 
   // Manipulate the length of some of the functions to meet
@@ -930,7 +988,9 @@
     ArrayMap: 1,
     ArrayIndexOf: 1,
     ArrayLastIndexOf: 1,
-    ArrayPush: 1
+    ArrayPush: 1,
+    ArrayReduce: 1,
+    ArrayReduceRight: 1
   });
 }
 
diff --git a/src/assembler-ia32.cc b/src/assembler-ia32.cc
index 8549261..3a2d3f8 100644
--- a/src/assembler-ia32.cc
+++ b/src/assembler-ia32.cc
@@ -283,6 +283,10 @@
   *pc_++ = (x)
 
 
+#ifdef GENERATED_CODE_COVERAGE
+static void InitCoverageLog();
+#endif
+
 // spare_buffer_
 static byte* spare_buffer_ = NULL;
 
@@ -315,9 +319,11 @@
   // Clear the buffer in debug mode unless it was provided by the
   // caller in which case we can't be sure it's okay to overwrite
   // existing code in it; see CodePatcher::CodePatcher(...).
-  if (kDebug && own_buffer_) {
+#ifdef DEBUG
+  if (own_buffer_) {
     memset(buffer_, 0xCC, buffer_size);  // int3
   }
+#endif
 
   // setup buffer pointers
   ASSERT(buffer_ != NULL);
@@ -329,6 +335,9 @@
   current_position_ = RelocInfo::kNoPosition;
   written_statement_position_ = current_statement_position_;
   written_position_ = current_position_;
+#ifdef GENERATED_CODE_COVERAGE
+  InitCoverageLog();
+#endif
 }
 
 
@@ -2073,9 +2082,9 @@
 
   // Clear the buffer in debug mode. Use 'int3' instructions to make
   // sure to get into problems if we ever run uninitialized code.
-  if (kDebug) {
-    memset(desc.buffer, 0xCC, desc.buffer_size);
-  }
+#ifdef DEBUG
+  memset(desc.buffer, 0xCC, desc.buffer_size);
+#endif
 
   // copy the data
   int pc_delta = desc.buffer - buffer_;
@@ -2202,4 +2211,30 @@
   long_at_put(position, label_loc);
 }
 
+
+#ifdef GENERATED_CODE_COVERAGE
+static FILE* coverage_log = NULL;
+
+
+static void InitCoverageLog() {
+  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
+  if (file_name != NULL) {
+    coverage_log = fopen(file_name, "aw+");
+  }
+}
+
+
+void LogGeneratedCodeCoverage(const char* file_line) {
+  const char* return_address = (&file_line)[-1];
+  char* push_insn = const_cast<char*>(return_address - 12);
+  push_insn[0] = 0xeb;  // Relative branch insn.
+  push_insn[1] = 13;    // Skip over coverage insns.
+  if (coverage_log != NULL) {
+    fprintf(coverage_log, "%s\n", file_line);
+    fflush(coverage_log);
+  }
+}
+
+#endif
+
 } }  // namespace v8::internal
diff --git a/src/assembler.cc b/src/assembler.cc
index ad4b24c..ec0e4fd 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -521,10 +521,10 @@
 ExternalReference::ExternalReference(const IC_Utility& ic_utility)
   : address_(ic_utility.address()) {}
 
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
 ExternalReference::ExternalReference(const Debug_Address& debug_address)
   : address_(debug_address.address()) {}
-
+#endif
 
 ExternalReference::ExternalReference(StatsCounter* counter)
   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
@@ -557,29 +557,71 @@
 }
 
 
-ExternalReference ExternalReference::debug_break() {
-  return ExternalReference(FUNCTION_ADDR(Debug::Break));
-}
-
-
 ExternalReference ExternalReference::new_space_start() {
   return ExternalReference(Heap::NewSpaceStart());
 }
 
+
 ExternalReference ExternalReference::new_space_allocation_top_address() {
   return ExternalReference(Heap::NewSpaceAllocationTopAddress());
 }
 
+
 ExternalReference ExternalReference::heap_always_allocate_scope_depth() {
   return ExternalReference(Heap::always_allocate_scope_depth_address());
 }
 
+
 ExternalReference ExternalReference::new_space_allocation_limit_address() {
   return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
 }
 
+
+static double add_two_doubles(double x, double y) {
+  return x + y;
+}
+
+
+static double sub_two_doubles(double x, double y) {
+  return x - y;
+}
+
+
+static double mul_two_doubles(double x, double y) {
+  return x * y;
+}
+
+
+ExternalReference ExternalReference::double_fp_operation(
+    Token::Value operation) {
+  typedef double BinaryFPOperation(double x, double y);
+  BinaryFPOperation* function = NULL;
+  switch (operation) {
+    case Token::ADD:
+      function = &add_two_doubles;
+      break;
+    case Token::SUB:
+      function = &sub_two_doubles;
+      break;
+    case Token::MUL:
+      function = &mul_two_doubles;
+      break;
+    default:
+      UNREACHABLE();
+  }
+  return ExternalReference(FUNCTION_ADDR(function));
+}
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ExternalReference ExternalReference::debug_break() {
+  return ExternalReference(FUNCTION_ADDR(Debug::Break));
+}
+
+
 ExternalReference ExternalReference::debug_step_in_fp_address() {
   return ExternalReference(Debug::step_in_fp_addr());
 }
+#endif
 
 } }  // namespace v8::internal
diff --git a/src/assembler.h b/src/assembler.h
index 49c9b90..8abdbc7 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -38,6 +38,7 @@
 #include "runtime.h"
 #include "top.h"
 #include "zone-inl.h"
+#include "token.h"
 
 namespace v8 { namespace internal {
 
@@ -340,29 +341,15 @@
 };
 
 
-// A stack-allocated code region logs a name for the code generated
-// while the region is in effect.  This information is used by the
-// profiler to categorize ticks within generated code.
-class CodeRegion BASE_EMBEDDED {
- public:
-  inline CodeRegion(Assembler* assm, const char *name) : assm_(assm) {
-    LOG(BeginCodeRegionEvent(this, assm, name));
-  }
-  inline ~CodeRegion() {
-    LOG(EndCodeRegionEvent(this, assm_));
-  }
- private:
-  Assembler* assm_;
-};
-
-
 //------------------------------------------------------------------------------
 // External function
 
 //----------------------------------------------------------------------------
 class IC_Utility;
-class Debug_Address;
 class SCTableReference;
+#ifdef ENABLE_DEBUGGER_SUPPORT
+class Debug_Address;
+#endif
 
 // An ExternalReference represents a C++ address called from the generated
 // code. All references to C++ functions and must be encapsulated in an
@@ -380,7 +367,9 @@
 
   explicit ExternalReference(const IC_Utility& ic_utility);
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   explicit ExternalReference(const Debug_Address& debug_address);
+#endif
 
   explicit ExternalReference(StatsCounter* counter);
 
@@ -403,9 +392,6 @@
   // Static variable RegExpStack::limit_address()
   static ExternalReference address_of_regexp_stack_limit();
 
-  // Function Debug::Break()
-  static ExternalReference debug_break();
-
   // Static variable Heap::NewSpaceStart()
   static ExternalReference new_space_start();
   static ExternalReference heap_always_allocate_scope_depth();
@@ -414,11 +400,18 @@
   static ExternalReference new_space_allocation_top_address();
   static ExternalReference new_space_allocation_limit_address();
 
-  // Used to check if single stepping is enabled in generated code.
-  static ExternalReference debug_step_in_fp_address();
+  static ExternalReference double_fp_operation(Token::Value operation);
 
   Address address() const {return address_;}
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  // Function Debug::Break()
+  static ExternalReference debug_break();
+
+  // Used to check if single stepping is enabled in generated code.
+  static ExternalReference debug_step_in_fp_address();
+#endif
+
  private:
   explicit ExternalReference(void* address)
     : address_(reinterpret_cast<Address>(address)) {}
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 0a0ed83..eebec74 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -832,12 +832,16 @@
 
 bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) {
   HandleScope scope;
+#ifdef ENABLE_DEBUGGER_SUPPORT
   Debugger::set_compiling_natives(true);
+#endif
   bool result =
       CompileScriptCached(name, source, &natives_cache, NULL, true);
   ASSERT(Top::has_pending_exception() != result);
   if (!result) Top::clear_pending_exception();
+#ifdef ENABLE_DEBUGGER_SUPPORT
   Debugger::set_compiling_natives(false);
+#endif
   return result;
 }
 
@@ -1015,6 +1019,13 @@
             Factory::LookupAsciiSymbol("column_offset"),
             proxy_column_offset,
             common_attributes);
+    Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptData);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("data"),
+            proxy_data,
+            common_attributes);
     Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType);
     script_descriptors =
         Factory::CopyAppendProxyDescriptor(
@@ -1132,6 +1143,7 @@
                 Handle<JSObject>(js_global->builtins()), DONT_ENUM);
   }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Expose the debug global object in global if a name for it is specified.
   if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
     // If loading fails we just bail out without installing the
@@ -1149,6 +1161,7 @@
     SetProperty(js_global, debug_string,
         Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
   }
+#endif
 
   return true;
 }
diff --git a/src/builtins-arm.cc b/src/builtins-arm.cc
index 2e6f255..58eeca8 100644
--- a/src/builtins-arm.cc
+++ b/src/builtins-arm.cc
@@ -34,7 +34,7 @@
 namespace v8 { namespace internal {
 
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
@@ -218,8 +218,9 @@
   __ mov(r5, Operand(r4));
   __ mov(r6, Operand(r4));
   __ mov(r7, Operand(r4));
-  if (kR9Available == 1)
+  if (kR9Available == 1) {
     __ mov(r9, Operand(r4));
+  }
 
   // Invoke the code and pass argc as r0.
   __ mov(r0, Operand(r3));
diff --git a/src/builtins-ia32.cc b/src/builtins-ia32.cc
index 0e9de8c..9baeb5e 100644
--- a/src/builtins-ia32.cc
+++ b/src/builtins-ia32.cc
@@ -32,7 +32,7 @@
 namespace v8 { namespace internal {
 
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
@@ -69,10 +69,12 @@
   Label rt_call, allocated;
   if (FLAG_inline_new) {
     Label undo_allocation;
+#ifdef ENABLE_DEBUGGER_SUPPORT
     ExternalReference debug_step_in_fp =
         ExternalReference::debug_step_in_fp_address();
     __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
     __ j(not_equal, &rt_call);
+#endif
     // Check that function is not a Smi.
     __ test(edi, Immediate(kSmiTagMask));
     __ j(zero, &rt_call);
diff --git a/src/builtins.cc b/src/builtins.cc
index c3935f1..b27974f 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -559,6 +559,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
   Debug::GenerateLoadICDebugBreak(masm);
 }
@@ -597,7 +598,7 @@
 static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
   Debug::GenerateStubNoRegistersDebugBreak(masm);
 }
-
+#endif
 
 Object* Builtins::builtins_[builtin_count] = { NULL, };
 const char* Builtins::names_[builtin_count] = { NULL, };
diff --git a/src/builtins.h b/src/builtins.h
index 853c90e..4e74a3c 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -83,6 +83,7 @@
   V(FunctionApply,              BUILTIN, UNINITIALIZED)
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 // Define list of builtins used by the debugger implemented in assembly.
 #define BUILTIN_LIST_DEBUG_A(V)                                \
   V(Return_DebugBreak,          BUILTIN, DEBUG_BREAK)          \
@@ -93,7 +94,9 @@
   V(KeyedLoadIC_DebugBreak,     KEYED_LOAD_IC, DEBUG_BREAK)    \
   V(StoreIC_DebugBreak,         STORE_IC, DEBUG_BREAK)         \
   V(KeyedStoreIC_DebugBreak,    KEYED_STORE_IC, DEBUG_BREAK)
-
+#else
+#define BUILTIN_LIST_DEBUG_A(V)
+#endif
 
 // Define list of builtins implemented in JavaScript.
 #define BUILTINS_LIST_JS(V)    \
diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc
index 6fdabc3..9337454 100644
--- a/src/codegen-arm.cc
+++ b/src/codegen-arm.cc
@@ -38,7 +38,8 @@
 
 namespace v8 { namespace internal {
 
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
+
 
 // -------------------------------------------------------------------------
 // CodeGenState implementation.
@@ -146,13 +147,13 @@
       frame_->EmitPush(r0);
       frame_->CallRuntime(Runtime::kNewContext, 1);  // r0 holds the result
 
-      if (kDebug) {
-        JumpTarget verified_true(this);
-        __ cmp(r0, Operand(cp));
-        verified_true.Branch(eq);
-        __ stop("NewContext: r0 is expected to be the same as cp");
-        verified_true.Bind();
-      }
+#ifdef DEBUG
+      JumpTarget verified_true(this);
+      __ cmp(r0, Operand(cp));
+      verified_true.Branch(eq);
+      __ stop("NewContext: r0 is expected to be the same as cp");
+      verified_true.Bind();
+#endif
       // Update context local.
       __ str(cp, frame_->Context());
     }
@@ -653,37 +654,27 @@
 }
 
 
-class GetPropertyStub : public CodeStub {
- public:
-  GetPropertyStub() { }
-
- private:
-  Major MajorKey() { return GetProperty; }
-  int MinorKey() { return 0; }
-  void Generate(MacroAssembler* masm);
-};
-
-
-class SetPropertyStub : public CodeStub {
- public:
-  SetPropertyStub() { }
-
- private:
-  Major MajorKey() { return SetProperty; }
-  int MinorKey() { return 0; }
-  void Generate(MacroAssembler* masm);
-};
-
-
 class GenericBinaryOpStub : public CodeStub {
  public:
-  explicit GenericBinaryOpStub(Token::Value op) : op_(op) { }
+  GenericBinaryOpStub(Token::Value op,
+                      OverwriteMode mode)
+      : op_(op), mode_(mode) { }
 
  private:
   Token::Value op_;
+  OverwriteMode mode_;
+
+  // Minor key encoding in 16 bits.
+  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+  class OpBits: public BitField<Token::Value, 2, 14> {};
 
   Major MajorKey() { return GenericBinaryOp; }
-  int MinorKey() { return static_cast<int>(op_); }
+  int MinorKey() {
+    // Encode the parameters in a unique 16 bit value.
+    return OpBits::encode(op_)
+           | ModeBits::encode(mode_);
+  }
+
   void Generate(MacroAssembler* masm);
 
   const char* GetName() {
@@ -708,7 +699,8 @@
 };
 
 
-void CodeGenerator::GenericBinaryOperation(Token::Value op) {
+void CodeGenerator::GenericBinaryOperation(Token::Value op,
+                                           OverwriteMode overwrite_mode) {
   VirtualFrame::SpilledScope spilled_scope(this);
   // sp[0] : y
   // sp[1] : x
@@ -727,7 +719,7 @@
     case Token::SAR: {
       frame_->EmitPop(r0);  // r0 : y
       frame_->EmitPop(r1);  // r1 : x
-      GenericBinaryOpStub stub(op);
+      GenericBinaryOpStub stub(op, overwrite_mode);
       frame_->CallStub(&stub, 0);
       break;
     }
@@ -767,11 +759,13 @@
   DeferredInlineSmiOperation(CodeGenerator* generator,
                              Token::Value op,
                              int value,
-                             bool reversed)
+                             bool reversed,
+                             OverwriteMode overwrite_mode)
       : DeferredCode(generator),
         op_(op),
         value_(value),
-        reversed_(reversed) {
+        reversed_(reversed),
+        overwrite_mode_(overwrite_mode) {
     set_comment("[ DeferredInlinedSmiOperation");
   }
 
@@ -781,6 +775,7 @@
   Token::Value op_;
   int value_;
   bool reversed_;
+  OverwriteMode overwrite_mode_;
 };
 
 
@@ -844,7 +839,7 @@
       break;
   }
 
-  GenericBinaryOpStub igostub(op_);
+  GenericBinaryOpStub igostub(op_, overwrite_mode_);
   Result arg0 = generator()->allocator()->Allocate(r1);
   ASSERT(arg0.is_valid());
   Result arg1 = generator()->allocator()->Allocate(r0);
@@ -856,7 +851,8 @@
 
 void CodeGenerator::SmiOperation(Token::Value op,
                                  Handle<Object> value,
-                                 bool reversed) {
+                                 bool reversed,
+                                 OverwriteMode mode) {
   VirtualFrame::SpilledScope spilled_scope(this);
   // NOTE: This is an attempt to inline (a bit) more of the code for
   // some possible smi operations (like + and -) when (at least) one
@@ -875,7 +871,7 @@
   switch (op) {
     case Token::ADD: {
       DeferredCode* deferred =
-        new DeferredInlineSmiOperation(this, op, int_value, reversed);
+        new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
 
       __ add(r0, r0, Operand(value), SetCC);
       deferred->enter()->Branch(vs);
@@ -887,7 +883,7 @@
 
     case Token::SUB: {
       DeferredCode* deferred =
-        new DeferredInlineSmiOperation(this, op, int_value, reversed);
+        new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
 
       if (!reversed) {
         __ sub(r0, r0, Operand(value), SetCC);
@@ -905,7 +901,7 @@
     case Token::BIT_XOR:
     case Token::BIT_AND: {
       DeferredCode* deferred =
-        new DeferredInlineSmiOperation(this, op, int_value, reversed);
+        new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
       __ tst(r0, Operand(kSmiTagMask));
       deferred->enter()->Branch(ne);
       switch (op) {
@@ -925,12 +921,12 @@
         __ mov(ip, Operand(value));
         frame_->EmitPush(ip);
         frame_->EmitPush(r0);
-        GenericBinaryOperation(op);
+        GenericBinaryOperation(op, mode);
 
       } else {
         int shift_value = int_value & 0x1f;  // least significant 5 bits
         DeferredCode* deferred =
-          new DeferredInlineSmiOperation(this, op, shift_value, false);
+          new DeferredInlineSmiOperation(this, op, shift_value, false, mode);
         __ tst(r0, Operand(kSmiTagMask));
         deferred->enter()->Branch(ne);
         __ mov(r2, Operand(r0, ASR, kSmiTagSize));  // remove tags
@@ -982,7 +978,7 @@
         frame_->EmitPush(ip);
         frame_->EmitPush(r0);
       }
-      GenericBinaryOperation(op);
+      GenericBinaryOperation(op, mode);
       break;
   }
 
@@ -1427,13 +1423,13 @@
   } else {
     frame_->CallRuntime(Runtime::kPushContext, 1);
   }
-  if (kDebug) {
-    JumpTarget verified_true(this);
-    __ cmp(r0, Operand(cp));
-    verified_true.Branch(eq);
-    __ stop("PushContext: r0 is expected to be the same as cp");
-    verified_true.Bind();
-  }
+#ifdef DEBUG
+  JumpTarget verified_true(this);
+  __ cmp(r0, Operand(cp));
+  verified_true.Branch(eq);
+  __ stop("PushContext: r0 is expected to be the same as cp");
+  verified_true.Bind();
+#endif
   // Update context local.
   __ str(cp, frame_->Context());
   ASSERT(frame_->height() == original_height);
@@ -1487,8 +1483,8 @@
   // Test for a Smi value in a HeapNumber.
   __ tst(r0, Operand(kSmiTagMask));
   is_smi.Branch(eq);
-  __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
-  __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
+  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
   __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
   default_target->Branch(ne);
   frame_->EmitPush(r0);
@@ -2339,7 +2335,9 @@
   VirtualFrame::SpilledScope spilled_scope(this);
   Comment cmnt(masm_, "[ DebuggerStatament");
   CodeForStatementPosition(node);
+#ifdef ENABLE_DEBUGGER_SUPPORT
   frame_->CallRuntime(Runtime::kDebugBreak, 0);
+#endif
   // Ignore the return value.
   ASSERT(frame_->height() == original_height);
 }
@@ -2523,7 +2521,9 @@
 
   if (s->is_eval_scope()) {
     Label next, fast;
-    if (!context.is(tmp)) __ mov(tmp, Operand(context));
+    if (!context.is(tmp)) {
+      __ mov(tmp, Operand(context));
+    }
     __ bind(&next);
     // Terminate at global context.
     __ ldr(tmp2, FieldMemOperand(tmp, HeapObject::kMapOffset));
@@ -2934,15 +2934,24 @@
       LoadAndSpill(node->value());
 
     } else {
+      // +=, *= and similar binary assignments.
+      // Get the old value of the lhs.
       target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
       Literal* literal = node->value()->AsLiteral();
+      bool overwrite =
+          (node->value()->AsBinaryOperation() != NULL &&
+           node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
       if (literal != NULL && literal->handle()->IsSmi()) {
-        SmiOperation(node->binary_op(), literal->handle(), false);
+        SmiOperation(node->binary_op(),
+                     literal->handle(),
+                     false,
+                     overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
         frame_->EmitPush(r0);
 
       } else {
         LoadAndSpill(node->value());
-        GenericBinaryOperation(node->binary_op());
+        GenericBinaryOperation(node->binary_op(),
+                               overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
         frame_->EmitPush(r0);
       }
     }
@@ -3822,19 +3831,39 @@
     // is a literal small integer.
     Literal* lliteral = node->left()->AsLiteral();
     Literal* rliteral = node->right()->AsLiteral();
+    // NOTE: The code below assumes that the slow cases (calls to runtime)
+    // never return a constant/immutable object.
+    bool overwrite_left =
+        (node->left()->AsBinaryOperation() != NULL &&
+         node->left()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_right =
+        (node->right()->AsBinaryOperation() != NULL &&
+         node->right()->AsBinaryOperation()->ResultOverwriteAllowed());
 
     if (rliteral != NULL && rliteral->handle()->IsSmi()) {
       LoadAndSpill(node->left());
-      SmiOperation(node->op(), rliteral->handle(), false);
+      SmiOperation(node->op(),
+                   rliteral->handle(),
+                   false,
+                   overwrite_right ? OVERWRITE_RIGHT : NO_OVERWRITE);
 
     } else if (lliteral != NULL && lliteral->handle()->IsSmi()) {
       LoadAndSpill(node->right());
-      SmiOperation(node->op(), lliteral->handle(), true);
+      SmiOperation(node->op(),
+                   lliteral->handle(),
+                   true,
+                   overwrite_left ? OVERWRITE_LEFT : NO_OVERWRITE);
 
     } else {
+      OverwriteMode overwrite_mode = NO_OVERWRITE;
+      if (overwrite_left) {
+        overwrite_mode = OVERWRITE_LEFT;
+      } else if (overwrite_right) {
+        overwrite_mode = OVERWRITE_RIGHT;
+      }
       LoadAndSpill(node->left());
       LoadAndSpill(node->right());
-      GenericBinaryOperation(node->op());
+      GenericBinaryOperation(node->op(), overwrite_mode);
     }
     frame_->EmitPush(r0);
   }
@@ -4067,7 +4096,8 @@
 
 
 #undef __
-#define __ masm->
+#define __ ACCESS_MASM(masm)
+
 
 Handle<String> Reference::GetName() {
   ASSERT(type_ == NAMED);
@@ -4305,167 +4335,80 @@
 }
 
 
-void GetPropertyStub::Generate(MacroAssembler* masm) {
-  // sp[0]: key
-  // sp[1]: receiver
-  Label slow, fast;
-  // Get the key and receiver object from the stack.
-  __ ldm(ia, sp, r0.bit() | r1.bit());
-  // Check that the key is a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(ne, &slow);
-  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
-  // Check that the object isn't a smi.
-  __ tst(r1, Operand(kSmiTagMask));
-  __ b(eq, &slow);
-
-  // Check that the object is some kind of JS object EXCEPT JS Value type.
-  // In the case that the object is a value-wrapper object,
-  // we enter the runtime system to make sure that indexing into string
-  // objects work as intended.
-  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
-  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
-  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
-  __ cmp(r2, Operand(JS_OBJECT_TYPE));
-  __ b(lt, &slow);
-
-  // Get the elements array of the object.
-  __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
-  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
-  __ cmp(r3, Operand(Factory::hash_table_map()));
-  __ b(eq, &slow);
-  // Check that the key (index) is within bounds.
-  __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset));
-  __ cmp(r0, Operand(r3));
-  __ b(lo, &fast);
-
-  // Slow case: Push extra copies of the arguments (2).
+static void HandleBinaryOpSlowCases(MacroAssembler* masm,
+                                    Label* not_smi,
+                                    const Builtins::JavaScript& builtin,
+                                    Token::Value operation,
+                                    int swi_number,
+                                    OverwriteMode mode) {
+  Label slow;
+  if (mode == NO_OVERWRITE) {
+    __ bind(not_smi);
+  }
   __ bind(&slow);
-  __ ldm(ia, sp, r0.bit() | r1.bit());
-  __ stm(db_w, sp, r0.bit() | r1.bit());
-  // Do tail-call to runtime routine.
-  __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2);
+  __ push(r1);
+  __ push(r0);
+  __ mov(r0, Operand(1));  // Set number of arguments.
+  __ InvokeBuiltin(builtin, JUMP_JS);  // Tail call.
 
-  // Fast case: Do the load.
-  __ bind(&fast);
-  __ add(r3, r1, Operand(Array::kHeaderSize - kHeapObjectTag));
-  __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
-  __ cmp(r0, Operand(Factory::the_hole_value()));
-  // In case the loaded value is the_hole we have to consult GetProperty
-  // to ensure the prototype chain is searched.
-  __ b(eq, &slow);
-
-  __ StubReturn(1);
-}
-
-
-void SetPropertyStub::Generate(MacroAssembler* masm) {
-  // r0 : value
-  // sp[0] : key
-  // sp[1] : receiver
-
-  Label slow, fast, array, extra, exit;
-  // Get the key and the object from the stack.
-  __ ldm(ia, sp, r1.bit() | r3.bit());  // r1 = key, r3 = receiver
-  // Check that the key is a smi.
-  __ tst(r1, Operand(kSmiTagMask));
-  __ b(ne, &slow);
-  // Check that the object isn't a smi.
-  __ tst(r3, Operand(kSmiTagMask));
-  __ b(eq, &slow);
-  // Get the type of the object from its map.
-  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
-  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
-  // Check if the object is a JS array or not.
-  __ cmp(r2, Operand(JS_ARRAY_TYPE));
-  __ b(eq, &array);
-  // Check that the object is some kind of JS object.
-  __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
-  __ b(lt, &slow);
-
-
-  // Object case: Check key against length in the elements array.
-  __ ldr(r3, FieldMemOperand(r3, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
-  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
-  __ cmp(r2, Operand(Factory::hash_table_map()));
-  __ b(eq, &slow);
-  // Untag the key (for checking against untagged length in the fixed array).
-  __ mov(r1, Operand(r1, ASR, kSmiTagSize));
-  // Compute address to store into and check array bounds.
-  __ add(r2, r3, Operand(Array::kHeaderSize - kHeapObjectTag));
-  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2));
-  __ ldr(ip, FieldMemOperand(r3, Array::kLengthOffset));
-  __ cmp(r1, Operand(ip));
-  __ b(lo, &fast);
-
-
-  // Slow case: Push extra copies of the arguments (3).
-  __ bind(&slow);
-  __ ldm(ia, sp, r1.bit() | r3.bit());  // r0 == value, r1 == key, r3 == object
-  __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
-  // Do tail-call to runtime routine.
-  __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
-
-
-  // Extra capacity case: Check if there is extra capacity to
-  // perform the store and update the length. Used for adding one
-  // element to the array by writing to array[array.length].
-  // r0 == value, r1 == key, r2 == elements, r3 == object
-  __ bind(&extra);
-  __ b(ne, &slow);  // do not leave holes in the array
-  __ mov(r1, Operand(r1, ASR, kSmiTagSize));  // untag
-  __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset));
-  __ cmp(r1, Operand(ip));
-  __ b(hs, &slow);
-  __ mov(r1, Operand(r1, LSL, kSmiTagSize));  // restore tag
-  __ add(r1, r1, Operand(1 << kSmiTagSize));  // and increment
-  __ str(r1, FieldMemOperand(r3, JSArray::kLengthOffset));
-  __ mov(r3, Operand(r2));
-  // NOTE: Computing the address to store into must take the fact
-  // that the key has been incremented into account.
-  int displacement = Array::kHeaderSize - kHeapObjectTag -
-      ((1 << kSmiTagSize) * 2);
-  __ add(r2, r2, Operand(displacement));
-  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
-  __ b(&fast);
-
-
-  // Array case: Get the length and the elements array from the JS
-  // array. Check that the array is in fast mode; if it is the
-  // length is always a smi.
-  // r0 == value, r3 == object
-  __ bind(&array);
-  __ ldr(r2, FieldMemOperand(r3, JSObject::kElementsOffset));
-  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
-  __ cmp(r1, Operand(Factory::hash_table_map()));
-  __ b(eq, &slow);
-
-  // Check the key against the length in the array, compute the
-  // address to store into and fall through to fast case.
-  __ ldr(r1, MemOperand(sp));
-  // r0 == value, r1 == key, r2 == elements, r3 == object.
-  __ ldr(ip, FieldMemOperand(r3, JSArray::kLengthOffset));
-  __ cmp(r1, Operand(ip));
-  __ b(hs, &extra);
-  __ mov(r3, Operand(r2));
-  __ add(r2, r2, Operand(Array::kHeaderSize - kHeapObjectTag));
-  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
-
-
-  // Fast case: Do the store.
-  // r0 == value, r2 == address to store into, r3 == elements
-  __ bind(&fast);
-  __ str(r0, MemOperand(r2));
-  // Skip write barrier if the written value is a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &exit);
-  // Update write barrier for the elements array address.
-  __ sub(r1, r2, Operand(r3));
-  __ RecordWrite(r3, r1, r2);
-  __ bind(&exit);
-  __ StubReturn(1);
+  // Could it be a double-double op?  If we already have a place to put
+  // the answer then we can do the op and skip the builtin and runtime call.
+  if (mode != NO_OVERWRITE) {
+    __ bind(not_smi);
+    __ tst(r0, Operand(kSmiTagMask));
+    __ b(eq, &slow);  // We can't handle a Smi-double combination yet.
+    __ tst(r1, Operand(kSmiTagMask));
+    __ b(eq, &slow);  // We can't handle a Smi-double combination yet.
+    // Get map of r0 into r2.
+    __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
+    // Get type of r0 into r3.
+    __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+    __ cmp(r3, Operand(HEAP_NUMBER_TYPE));
+    __ b(ne, &slow);
+    // Get type of r1 into r3.
+    __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+    // Check they are both the same map (heap number map).
+    __ cmp(r2, r3);
+    __ b(ne, &slow);
+    // Both are doubles.
+    // Calling convention says that second double is in r2 and r3.
+    __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
+    __ push(lr);
+    if (mode == OVERWRITE_LEFT) {
+      __ push(r1);
+    } else {
+      __ push(r0);
+    }
+    // Calling convention says that first double is in r0 and r1.
+    __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
+    // Call C routine that may not cause GC or other trouble.
+    __ mov(r5, Operand(ExternalReference::double_fp_operation(operation)));
+#if !defined(__arm__)
+    // Notify the simulator that we are calling an add routine in C.
+    __ swi(swi_number);
+#else
+    // Actually call the add routine written in C.
+    __ Call(r5);
+#endif
+    // Store answer in the overwritable heap number.
+    __ pop(r4);
+#if !defined(__ARM_EABI__) && defined(__arm__)
+    // Double returned in fp coprocessor register 0 and 1, encoded as register
+    // cr8.  Offsets must be divisible by 4 for coprocessor so we need to
+    // substract the tag from r4.
+    __ sub(r5, r4, Operand(kHeapObjectTag));
+    __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset));
+#else
+    // Double returned in fp coprocessor register 0 and 1.
+    __ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset));
+    __ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + kPointerSize));
+#endif
+    __ mov(r0, Operand(r4));
+    // And we are done.
+    __ pop(pc);
+  }
 }
 
 
@@ -4474,89 +4417,84 @@
   // r0 : y
   // result : r0
 
+  // All ops need to know whether we are dealing with two Smis.  Set up r2 to
+  // tell us that.
+  __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+
   switch (op_) {
     case Token::ADD: {
-      Label slow, exit;
-      // fast path
-      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
-      __ add(r0, r1, Operand(r0), SetCC);  // add y optimistically
-      // go slow-path in case of overflow
-      __ b(vs, &slow);
-      // go slow-path in case of non-smi operands
-      ASSERT(kSmiTag == 0);  // adjust code below
+      Label not_smi;
+      // Fast path.
+      ASSERT(kSmiTag == 0);  // Adjust code below.
       __ tst(r2, Operand(kSmiTagMask));
-      __ b(eq, &exit);
-      // slow path
-      __ bind(&slow);
-      __ sub(r0, r0, Operand(r1));  // revert optimistic add
-      __ push(r1);
-      __ push(r0);
-      __ mov(r0, Operand(1));  // set number of arguments
-      __ InvokeBuiltin(Builtins::ADD, JUMP_JS);
-      // done
-      __ bind(&exit);
+      __ b(ne, &not_smi);
+      __ add(r0, r1, Operand(r0), SetCC);  // Add y optimistically.
+      // Return if no overflow.
+      __ Ret(vc);
+      __ sub(r0, r0, Operand(r1));  // Revert optimistic add.
+
+      HandleBinaryOpSlowCases(masm,
+                              &not_smi,
+                              Builtins::ADD,
+                              Token::ADD,
+                              assembler::arm::simulator_fp_add,
+                              mode_);
       break;
     }
 
     case Token::SUB: {
-      Label slow, exit;
-      // fast path
-      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
-      __ sub(r3, r1, Operand(r0), SetCC);  // subtract y optimistically
-      // go slow-path in case of overflow
-      __ b(vs, &slow);
-      // go slow-path in case of non-smi operands
-      ASSERT(kSmiTag == 0);  // adjust code below
+      Label not_smi;
+      // Fast path.
+      ASSERT(kSmiTag == 0);  // Adjust code below.
       __ tst(r2, Operand(kSmiTagMask));
-      __ mov(r0, Operand(r3), LeaveCC, eq);  // conditionally set r0 to result
-      __ b(eq, &exit);
-      // slow path
-      __ bind(&slow);
-      __ push(r1);
-      __ push(r0);
-      __ mov(r0, Operand(1));  // set number of arguments
-      __ InvokeBuiltin(Builtins::SUB, JUMP_JS);
-      // done
-      __ bind(&exit);
+      __ b(ne, &not_smi);
+      __ sub(r0, r1, Operand(r0), SetCC);  // Subtract y optimistically.
+      // Return if no overflow.
+      __ Ret(vc);
+      __ sub(r0, r1, Operand(r0));  // Revert optimistic subtract.
+
+      HandleBinaryOpSlowCases(masm,
+                              &not_smi,
+                              Builtins::SUB,
+                              Token::SUB,
+                              assembler::arm::simulator_fp_sub,
+                              mode_);
       break;
     }
 
     case Token::MUL: {
-      Label slow, exit;
-      // tag check
-      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      Label not_smi, slow;
       ASSERT(kSmiTag == 0);  // adjust code below
       __ tst(r2, Operand(kSmiTagMask));
-      __ b(ne, &slow);
-      // remove tag from one operand (but keep sign), so that result is smi
+      __ b(ne, &not_smi);
+      // Remove tag from one operand (but keep sign), so that result is Smi.
       __ mov(ip, Operand(r0, ASR, kSmiTagSize));
-      // do multiplication
-      __ smull(r3, r2, r1, ip);  // r3 = lower 32 bits of ip*r1
-      // go slow on overflows (overflow bit is not set)
+      // Do multiplication
+      __ smull(r3, r2, r1, ip);  // r3 = lower 32 bits of ip*r1.
+      // Go slow on overflows (overflow bit is not set).
       __ mov(ip, Operand(r3, ASR, 31));
       __ cmp(ip, Operand(r2));  // no overflow if higher 33 bits are identical
       __ b(ne, &slow);
-      // go slow on zero result to handle -0
+      // Go slow on zero result to handle -0.
       __ tst(r3, Operand(r3));
       __ mov(r0, Operand(r3), LeaveCC, ne);
-      __ b(ne, &exit);
-      // slow case
+      __ Ret(ne);
+      // Slow case.
       __ bind(&slow);
-      __ push(r1);
-      __ push(r0);
-      __ mov(r0, Operand(1));  // set number of arguments
-      __ InvokeBuiltin(Builtins::MUL, JUMP_JS);
-      // done
-      __ bind(&exit);
+
+      HandleBinaryOpSlowCases(masm,
+                              &not_smi,
+                              Builtins::MUL,
+                              Token::MUL,
+                              assembler::arm::simulator_fp_mul,
+                              mode_);
       break;
     }
 
     case Token::BIT_OR:
     case Token::BIT_AND:
     case Token::BIT_XOR: {
-      Label slow, exit;
-      // tag check
-      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      Label slow;
       ASSERT(kSmiTag == 0);  // adjust code below
       __ tst(r2, Operand(kSmiTagMask));
       __ b(ne, &slow);
@@ -4566,7 +4504,7 @@
         case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;
         default: UNREACHABLE();
       }
-      __ b(&exit);
+      __ Ret();
       __ bind(&slow);
       __ push(r1);  // restore stack
       __ push(r0);
@@ -4584,16 +4522,13 @@
         default:
           UNREACHABLE();
       }
-      __ bind(&exit);
       break;
     }
 
     case Token::SHL:
     case Token::SHR:
     case Token::SAR: {
-      Label slow, exit;
-      // tag check
-      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      Label slow;
       ASSERT(kSmiTag == 0);  // adjust code below
       __ tst(r2, Operand(kSmiTagMask));
       __ b(ne, &slow);
@@ -4633,7 +4568,7 @@
       // tag result and store it in r0
       ASSERT(kSmiTag == 0);  // adjust code below
       __ mov(r0, Operand(r3, LSL, kSmiTagSize));
-      __ b(&exit);
+      __ Ret();
       // slow case
       __ bind(&slow);
       __ push(r1);  // restore stack
@@ -4645,13 +4580,13 @@
         case Token::SHL: __ InvokeBuiltin(Builtins::SHL, JUMP_JS); break;
         default: UNREACHABLE();
       }
-      __ bind(&exit);
       break;
     }
 
     default: UNREACHABLE();
   }
-  __ Ret();
+  // This code should be unreachable.
+  __ stop("Unreachable");
 }
 
 
@@ -4721,7 +4656,11 @@
   __ mov(cp, Operand(0), LeaveCC, eq);
   // Restore cp otherwise.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
-  if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));
+#ifdef DEBUG
+  if (FLAG_debug_code) {
+    __ mov(lr, Operand(pc));
+  }
+#endif
   __ pop(pc);
 }
 
@@ -4784,7 +4723,11 @@
   __ mov(cp, Operand(0), LeaveCC, eq);
   // Restore cp otherwise.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
-  if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));
+#ifdef DEBUG
+  if (FLAG_debug_code) {
+    __ mov(lr, Operand(pc));
+  }
+#endif
   __ pop(pc);
 }
 
@@ -5043,9 +4986,11 @@
   }
   __ ldr(ip, MemOperand(ip));  // deref address
 
-  // Branch and link to JSEntryTrampoline
+  // Branch and link to JSEntryTrampoline.  We don't use the double underscore
+  // macro for the add instruction because we don't want the coverage tool
+  // inserting instructions here after we read the pc.
   __ mov(lr, Operand(pc));
-  __ add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
+  masm->add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
 
   // Unlink this frame from the handler chain. When reading the
   // address of the next handler, there is no need to use the address
@@ -5057,6 +5002,7 @@
   // No need to restore registers
   __ add(sp, sp, Operand(StackHandlerConstants::kSize));
 
+
   __ bind(&exit);  // r0 holds result
   // Restore the top frame descriptors from the stack.
   __ pop(r3);
@@ -5068,7 +5014,9 @@
 
   // Restore callee-saved registers and return.
 #ifdef DEBUG
-  if (FLAG_debug_code) __ mov(lr, Operand(pc));
+  if (FLAG_debug_code) {
+    __ mov(lr, Operand(pc));
+  }
 #endif
   __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
 }
diff --git a/src/codegen-arm.h b/src/codegen-arm.h
index b072f75..48b92ea 100644
--- a/src/codegen-arm.h
+++ b/src/codegen-arm.h
@@ -35,9 +35,6 @@
 class RegisterAllocator;
 class RegisterFile;
 
-// Mode to overwrite BinaryExpression values.
-enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
-
 enum InitState { CONST_INIT, NOT_CONST_INIT };
 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
 
@@ -292,10 +289,13 @@
 
   void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
 
-  void GenericBinaryOperation(Token::Value op);
+  void GenericBinaryOperation(Token::Value op, OverwriteMode overwrite_mode);
   void Comparison(Condition cc, bool strict = false);
 
-  void SmiOperation(Token::Value op, Handle<Object> value, bool reversed);
+  void SmiOperation(Token::Value op,
+                    Handle<Object> value,
+                    bool reversed,
+                    OverwriteMode mode);
 
   void CallWithArguments(ZoneList<Expression*>* arguments, int position);
 
diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc
index 663f235..fb2f8bf 100644
--- a/src/codegen-ia32.cc
+++ b/src/codegen-ia32.cc
@@ -37,7 +37,7 @@
 
 namespace v8 { namespace internal {
 
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
 
 // -------------------------------------------------------------------------
 // CodeGenState implementation.
@@ -1274,12 +1274,9 @@
                                                     smi_value,
                                                     overwrite_mode);
         __ Set(answer.reg(), Immediate(value));
-        if (operand->is_register()) {
-          __ sub(answer.reg(), Operand(operand->reg()));
-        } else {
-          ASSERT(operand->is_constant());
-          __ sub(Operand(answer.reg()), Immediate(operand->handle()));
-        }
+        // We are in the reversed case so they can't both be Smi constants.
+        ASSERT(operand->is_register());
+        __ sub(answer.reg(), Operand(operand->reg()));
       } else {
         operand->ToRegister();
         frame_->Spill(operand->reg());
@@ -1374,23 +1371,26 @@
         operand->ToRegister();
         __ test(operand->reg(), Immediate(kSmiTagMask));
         deferred->enter()->Branch(not_zero, operand, not_taken);
-        Result answer = allocator()->Allocate();
-        ASSERT(answer.is_valid());
-        __ mov(answer.reg(), operand->reg());
-        ASSERT(kSmiTag == 0);  // adjust code if not the case
-        // We do no shifts, only the Smi conversion, if shift_value is 1.
-        if (shift_value == 0) {
-          __ sar(answer.reg(), kSmiTagSize);
-        } else if (shift_value > 1) {
-          __ shl(answer.reg(), shift_value - 1);
+        if (shift_value != 0) {
+          Result answer = allocator()->Allocate();
+          ASSERT(answer.is_valid());
+          __ mov(answer.reg(), operand->reg());
+          ASSERT(kSmiTag == 0);  // adjust code if not the case
+          // We do no shifts, only the Smi conversion, if shift_value is 1.
+          if (shift_value > 1) {
+            __ shl(answer.reg(), shift_value - 1);
+          }
+          // Convert int result to Smi, checking that it is in int range.
+          ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+          __ add(answer.reg(), Operand(answer.reg()));
+          deferred->enter()->Branch(overflow, operand, not_taken);
+          operand->Unuse();
+          deferred->BindExit(&answer);
+          frame_->Push(&answer);
+        } else {
+          deferred->BindExit(operand);
+          frame_->Push(operand);
         }
-        // Convert int result to Smi, checking that it is in int range.
-        ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-        __ add(answer.reg(), Operand(answer.reg()));
-        deferred->enter()->Branch(overflow, operand, not_taken);
-        operand->Unuse();
-        deferred->BindExit(&answer);
-        frame_->Push(&answer);
       }
       break;
     }
@@ -1411,11 +1411,7 @@
       deferred->enter()->Branch(not_zero, operand, not_taken);
       frame_->Spill(operand->reg());
       if (op == Token::BIT_AND) {
-        if (int_value == 0) {
-          __ xor_(Operand(operand->reg()), operand->reg());
-        } else {
-          __ and_(Operand(operand->reg()), Immediate(value));
-        }
+        __ and_(Operand(operand->reg()), Immediate(value));
       } else if (op == Token::BIT_XOR) {
         if (int_value != 0) {
           __ xor_(Operand(operand->reg()), Immediate(value));
@@ -2009,18 +2005,18 @@
 
   // Add a label for checking the size of the code used for returning.
   Label check_exit_codesize;
-  __ bind(&check_exit_codesize);
+  masm_->bind(&check_exit_codesize);
 
   // Leave the frame and return popping the arguments and the
   // receiver.
   frame_->Exit();
-  __ ret((scope_->num_parameters() + 1) * kPointerSize);
+  masm_->ret((scope_->num_parameters() + 1) * kPointerSize);
   DeleteFrame();
 
   // Check that the size of the code used for returning matches what is
   // expected by the debugger.
   ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
-            __ SizeOfCodeGeneratedSince(&check_exit_codesize));
+            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
 }
 
 
@@ -2143,7 +2139,7 @@
                  times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
   smi_value.Unuse();
   // Calculate address to overwrite later with actual address of table.
-  int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
+  int32_t jump_table_ref = masm_->pc_offset() - sizeof(int32_t);
   __ Align(4);
   Label table_start;
   __ bind(&table_start);
@@ -3179,10 +3175,12 @@
   ASSERT(!in_spilled_code());
   Comment cmnt(masm_, "[ DebuggerStatement");
   CodeForStatementPosition(node);
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Spill everything, even constants, to the frame.
   frame_->SpillAll();
   frame_->CallRuntime(Runtime::kDebugBreak, 0);
   // Ignore the return value.
+#endif
 }
 
 
@@ -3384,7 +3382,9 @@
     // Loop up the context chain.  There is no frame effect so it is
     // safe to use raw labels here.
     Label next, fast;
-    if (!context.reg().is(tmp.reg())) __ mov(tmp.reg(), context.reg());
+    if (!context.reg().is(tmp.reg())) {
+      __ mov(tmp.reg(), context.reg());
+    }
     __ bind(&next);
     // Terminate at global context.
     __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
@@ -3933,6 +3933,9 @@
 
     } else {
       Literal* literal = node->value()->AsLiteral();
+      bool overwrite_value =
+          (node->value()->AsBinaryOperation() != NULL &&
+           node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
       Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
       // There are two cases where the target is not read in the right hand
       // side, that are easy to test for: the right hand side is a literal,
@@ -3945,7 +3948,9 @@
         target.GetValue(NOT_INSIDE_TYPEOF);
       }
       Load(node->value());
-      GenericBinaryOperation(node->binary_op(), node->type());
+      GenericBinaryOperation(node->binary_op(),
+                             node->type(),
+                             overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
     }
 
     if (var != NULL &&
@@ -5268,8 +5273,11 @@
   // instruction.
   ASSERT(value.is_register() && value.reg().is(eax));
   // The delta from the start of the map-compare instruction to the
-  // test eax instruction.
-  int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site());
+  // test eax instruction.  We use masm_ directly here instead of the
+  // double underscore macro because the macro sometimes uses macro
+  // expansion to turn into something that can't return a value.  This
+  // is encountered when doing generated code coverage tests.
+  int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
   __ test(value.reg(), Immediate(-delta_to_patch_site));
   __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
 
@@ -5284,7 +5292,7 @@
 
 
 #undef __
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 Handle<String> Reference::GetName() {
   ASSERT(type_ == NAMED);
@@ -5369,7 +5377,9 @@
         // Initially, use an invalid map. The map is patched in the IC
         // initialization code.
         __ bind(deferred->patch_site());
-        __ cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
+        // Use masm-> here instead of the double underscore macro since extra
+        // coverage code can interfere with the patching.
+        masm->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
                Immediate(Factory::null_value()));
         deferred->enter()->Branch(not_equal, &receiver, &key, not_taken);
 
@@ -5566,7 +5576,7 @@
 
 
 #undef __
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
 
 Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
                                                          Result* right) {
@@ -5900,7 +5910,7 @@
 
 
 #undef __
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
   // Perform fast-case smi code for the operation (eax <op> ebx) and
@@ -6225,7 +6235,9 @@
       }
 
       // SHR should return uint32 - go to runtime for non-smi/negative result.
-      if (op_ == Token::SHR) __ bind(&non_smi_result);
+      if (op_ == Token::SHR) {
+        __ bind(&non_smi_result);
+      }
       __ mov(eax, Operand(esp, 1 * kPointerSize));
       __ mov(edx, Operand(esp, 2 * kPointerSize));
       break;
diff --git a/src/codegen-ia32.h b/src/codegen-ia32.h
index 24a57a0..a39bc58 100644
--- a/src/codegen-ia32.h
+++ b/src/codegen-ia32.h
@@ -35,9 +35,6 @@
 class RegisterAllocator;
 class RegisterFile;
 
-// Mode to overwrite BinaryExpression values.
-enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
-
 enum InitState { CONST_INIT, NOT_CONST_INIT };
 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
 
@@ -435,7 +432,7 @@
   void GenericBinaryOperation(
       Token::Value op,
       SmiAnalysis* type,
-      const OverwriteMode overwrite_mode = NO_OVERWRITE);
+      OverwriteMode overwrite_mode);
 
   // If possible, combine two constant smi values using op to produce
   // a smi result, and push it on the virtual frame, all at compile time.
diff --git a/src/codegen.cc b/src/codegen.cc
index edc498d..ed7ee2f 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -304,8 +304,10 @@
                                  node->is_expression(), false, script_,
                                  node->inferred_name());
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Notify debugger that a new function has been added.
   Debugger::OnNewFunction(function);
+#endif
 
   // Set the expected number of properties for instances and return
   // the resulting function.
diff --git a/src/codegen.h b/src/codegen.h
index dd43cc0..54fe330 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -71,6 +71,11 @@
 //   CodeForStatementPosition
 //   CodeForSourcePosition
 
+
+// Mode to overwrite BinaryExpression values.
+enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
+
+
 #ifdef ARM
 #include "codegen-arm.h"
 #else
diff --git a/src/compiler.cc b/src/compiler.cc
index 63fed4a..62e838e 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -92,8 +92,10 @@
   StackGuard guard;
   PostponeInterruptsScope postpone;
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Notify debugger
   Debugger::OnBeforeCompile(script);
+#endif
 
   // Only allow non-global compiles for eval.
   ASSERT(is_eval || is_global);
@@ -160,8 +162,10 @@
   // the instances of the function.
   SetExpectedNofPropertiesFromEstimate(fun, lit->expected_property_count());
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Notify debugger
   Debugger::OnAfterCompile(script, fun);
+#endif
 
   return fun;
 }
diff --git a/src/constants-arm.h b/src/constants-arm.h
index f553963..919a892 100644
--- a/src/constants-arm.h
+++ b/src/constants-arm.h
@@ -106,7 +106,12 @@
   call_rt_r5 = 0x10,
   call_rt_r2 = 0x11,
   // break point
-  break_point = 0x20
+  break_point = 0x20,
+  // FP operations.  These simulate calling into C for a moment to do fp ops.
+  // They should trash all caller-save registers.
+  simulator_fp_add = 0x21,
+  simulator_fp_sub = 0x22,
+  simulator_fp_mul = 0x23
 };
 
 
diff --git a/src/d8.cc b/src/d8.cc
index 9648168..70143c3 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -163,6 +163,22 @@
 }
 
 
+Handle<Value> Shell::Read(const Arguments& args) {
+  if (args.Length() != 1) {
+    return ThrowException(String::New("Bad parameters"));
+  }
+  String::Utf8Value file(args[0]);
+  if (*file == NULL) {
+    return ThrowException(String::New("Error loading file"));
+  }
+  Handle<String> source = ReadFile(*file);
+  if (source.IsEmpty()) {
+    return ThrowException(String::New("Error loading file"));
+  }
+  return source;
+}
+
+
 Handle<Value> Shell::Load(const Arguments& args) {
   for (int i = 0; i < args.Length(); i++) {
     HandleScope handle_scope;
@@ -246,6 +262,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 Handle<Object> Shell::DebugMessageDetails(Handle<String> message) {
   Context::Scope context_scope(utility_context_);
   Handle<Object> global = utility_context_->Global();
@@ -266,6 +283,7 @@
   Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
   return val;
 }
+#endif
 
 
 int32_t* Counter::Bind(const char* name, bool is_histogram) {
@@ -381,6 +399,7 @@
   HandleScope scope;
   Handle<ObjectTemplate> global_template = ObjectTemplate::New();
   global_template->Set(String::New("print"), FunctionTemplate::New(Print));
+  global_template->Set(String::New("read"), FunctionTemplate::New(Read));
   global_template->Set(String::New("load"), FunctionTemplate::New(Load));
   global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
   global_template->Set(String::New("version"), FunctionTemplate::New(Version));
@@ -406,11 +425,13 @@
   global_template->Set(String::New("arguments"),
                        Utils::ToLocal(arguments_jsarray));
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Install the debugger object in the utility scope
   i::Debug::Load();
   i::JSObject* debug = i::Debug::debug_context()->global();
   utility_context_->Global()->Set(String::New("$debug"),
                                   Utils::ToLocal(&debug));
+#endif
 
   // Run the d8 shell utility script in the utility context
   int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
@@ -436,8 +457,10 @@
   evaluation_context_ = Context::New(NULL, global_template);
   evaluation_context_->SetSecurityToken(Undefined());
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Set the security token of the debug context to allow access.
   i::Debug::debug_context()->set_security_token(i::Heap::undefined_value());
+#endif
 }
 
 
@@ -555,6 +578,8 @@
   Handle<ObjectTemplate> global_template = ObjectTemplate::New();
   global_template->Set(String::New("print"),
                        FunctionTemplate::New(Shell::Print));
+  global_template->Set(String::New("read"),
+                       FunctionTemplate::New(Shell::Read));
   global_template->Set(String::New("load"),
                        FunctionTemplate::New(Shell::Load));
   global_template->Set(String::New("yield"),
@@ -690,6 +715,7 @@
       Locker::StartPreemption(preemption_interval);
     }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
     // Run the remote debugger if requested.
     if (i::FLAG_remote_debugger) {
       RunRemoteDebugger(i::FLAG_debugger_port);
@@ -705,6 +731,7 @@
     if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
       v8::Debug::SetDebugEventListener(HandleDebugEvent);
     }
+#endif
   }
   if (run_shell)
     RunShell();
diff --git a/src/d8.h b/src/d8.h
index 342a0d2..092e3a3 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -132,13 +132,16 @@
   static int Main(int argc, char* argv[]);
   static Handle<Array> GetCompletions(Handle<String> text,
                                       Handle<String> full);
+#ifdef ENABLE_DEBUGGER_SUPPORT
   static Handle<Object> DebugMessageDetails(Handle<String> message);
   static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
+#endif
 
   static Handle<Value> Print(const Arguments& args);
   static Handle<Value> Yield(const Arguments& args);
   static Handle<Value> Quit(const Arguments& args);
   static Handle<Value> Version(const Arguments& args);
+  static Handle<Value> Read(const Arguments& args);
   static Handle<Value> Load(const Arguments& args);
   // The OS object on the global object contains methods for performing
   // operating system calls:
diff --git a/src/d8.js b/src/d8.js
index e2766d0..ea2fb44 100644
--- a/src/d8.js
+++ b/src/d8.js
@@ -653,17 +653,47 @@
   // Process arguments if any.
   if (args && args.length > 0) {
     var target = args;
+    var type = 'function';
+    var line;
+    var column;
     var condition;
+    var pos;
 
-    var pos = args.indexOf(' ');
+    // Check for breakpoint condition.
+    pos = args.indexOf(' ');
     if (pos > 0) {
       target = args.substring(0, pos);
       condition = args.substring(pos + 1, args.length);
     }
 
+    // Check for script breakpoint (name:line[:column]). If no ':' in break
+    // specification it is considered a function break point.
+    pos = target.indexOf(':');
+    if (pos > 0) {
+      type = 'script';
+      var tmp = target.substring(pos + 1, target.length);
+      target = target.substring(0, pos);
+      
+      // Check for both line and column.
+      pos = tmp.indexOf(':');
+      if (pos > 0) {
+        column = parseInt(tmp.substring(pos + 1, tmp.length)) - 1;
+        line = parseInt(tmp.substring(0, pos)) - 1;
+      } else {
+        line = parseInt(tmp) - 1;
+      }
+    } else if (target[0] == '#' && target[target.length - 1] == '#') {
+      type = 'handle';
+      target = target.substring(1, target.length - 1);
+    } else {
+      type = 'function';
+    }
+  
     request.arguments = {};
-    request.arguments.type = 'function';
+    request.arguments.type = type;
     request.arguments.target = target;
+    request.arguments.line = line;
+    request.arguments.column = column;
     request.arguments.condition = condition;
   } else {
     throw new Error('Invalid break arguments.');
@@ -721,6 +751,9 @@
   }
 
   print('break location [condition]');
+  print('  break on named function: location is a function name');
+  print('  break on function: location is #<id>#');
+  print('  break on script position: location is name:line[:column]');
   print('clear <breakpoint #>');
   print('backtrace [from frame #] [to frame #]]');
   print('frame <frame #>');
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
index e865e0e..9838746 100644
--- a/src/debug-agent.cc
+++ b/src/debug-agent.cc
@@ -29,16 +29,18 @@
 #include "v8.h"
 #include "debug-agent.h"
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 namespace v8 { namespace internal {
 
-
 // Public V8 debugger API message handler function. This function just delegates
 // to the debugger agent through it's data parameter.
 void DebuggerAgentMessageHandler(const uint16_t* message, int length,
-                                 void *data) {
-  reinterpret_cast<DebuggerAgent*>(data)->DebuggerMessage(message, length);
+                                 v8::Debug::ClientData* client_data) {
+  DebuggerAgent::instance_->DebuggerMessage(message, length);
 }
 
+// static
+DebuggerAgent* DebuggerAgent::instance_ = NULL;
 
 // Debugger agent main thread.
 void DebuggerAgent::Run() {
@@ -410,5 +412,6 @@
   return total_received;
 }
 
-
 } }  // namespace v8::internal
+
+#endif  // ENABLE_DEBUGGER_SUPPORT
diff --git a/src/debug-agent.h b/src/debug-agent.h
index 177af0c..08f1372 100644
--- a/src/debug-agent.h
+++ b/src/debug-agent.h
@@ -28,12 +28,12 @@
 #ifndef V8_V8_DEBUG_AGENT_H_
 #define V8_V8_DEBUG_AGENT_H_
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 #include "../include/v8-debug.h"
 #include "platform.h"
 
 namespace v8 { namespace internal {
 
-
 // Forward decelrations.
 class DebuggerAgentSession;
 
@@ -46,8 +46,14 @@
       : name_(StrDup(name)), port_(port),
         server_(OS::CreateSocket()), terminate_(false),
         session_access_(OS::CreateMutex()), session_(NULL),
-        terminate_now_(OS::CreateSemaphore(0)) {}
-  ~DebuggerAgent() { delete server_; }
+        terminate_now_(OS::CreateSemaphore(0)) {
+    ASSERT(instance_ == NULL);
+    instance_ = this;
+  }
+  ~DebuggerAgent() {
+     instance_ = NULL;
+     delete server_;
+  }
 
   void Shutdown();
 
@@ -66,9 +72,11 @@
   DebuggerAgentSession* session_;  // Current active session if any.
   Semaphore* terminate_now_;  // Semaphore to signal termination.
 
+  static DebuggerAgent* instance_;
+
   friend class DebuggerAgentSession;
   friend void DebuggerAgentMessageHandler(const uint16_t* message, int length,
-                                          void *data);
+                                          v8::Debug::ClientData* client_data);
 
   DISALLOW_COPY_AND_ASSIGN(DebuggerAgent);
 };
@@ -111,7 +119,8 @@
   static int ReceiveAll(const Socket* conn, char* data, int len);
 };
 
-
 } }  // namespace v8::internal
 
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
 #endif  // V8_V8_DEBUG_AGENT_H_
diff --git a/src/debug-arm.cc b/src/debug-arm.cc
index 9fb77b7..f86f981 100644
--- a/src/debug-arm.cc
+++ b/src/debug-arm.cc
@@ -32,7 +32,7 @@
 
 namespace v8 { namespace internal {
 
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
 // Currently debug break is not supported in frame exit code on ARM.
 bool BreakLocationIterator::IsDebugBreakAtReturn() {
   return false;
@@ -58,7 +58,7 @@
 }
 
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
@@ -191,5 +191,6 @@
 
 #undef __
 
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 } }  // namespace v8::internal
diff --git a/src/debug-delay.js b/src/debug-delay.js
index 9944fb3..6cb5e7f 100644
--- a/src/debug-delay.js
+++ b/src/debug-delay.js
@@ -1021,6 +1021,9 @@
             columnOffset: script.columnOffset(),
             lineCount: script.lineCount(),
           };
+  if (!IS_UNDEFINED(script.data())) {
+    o.data = script.data();
+  }
   if (include_source) {
     o.source = script.source();
   }
@@ -1270,11 +1273,12 @@
   var ignoreCount = request.arguments.ignoreCount;
 
   // Check for legal arguments.
-  if (!type || !target) {
+  if (!type || IS_UNDEFINED(target)) {
     response.failed('Missing argument "type" or "target"');
     return;
   }
-  if (type != 'function' && type != 'script' && type != 'scriptId') {
+  if (type != 'function' && type != 'handle' &&
+      type != 'script' && type != 'scriptId') {
     response.failed('Illegal type "' + type + '"');
     return;
   }
@@ -1303,6 +1307,20 @@
 
     // Set function break point.
     break_point_number = Debug.setBreakPoint(f, line, column, condition);
+  } else if (type == 'handle') {
+    // Find the object pointed by the specified handle.
+    var handle = parseInt(target, 10);
+    var mirror = LookupMirror(handle);
+    if (!mirror) {
+      return response.failed('Object #' + handle + '# not found');
+    }
+    if (!mirror.isFunction()) {
+      return response.failed('Object #' + handle + '# is not a function');
+    }
+
+    // Set function break point.
+    break_point_number = Debug.setBreakPoint(mirror.value(),
+                                             line, column, condition);
   } else if (type == 'script') {
     // set script break point.
     break_point_number =
@@ -1547,20 +1565,24 @@
   }
 
   // Pull out arguments.
-  var handle = request.arguments.handle;
+  var handles = request.arguments.handles;
 
   // Check for legal arguments.
-  if (IS_UNDEFINED(handle)) {
-    return response.failed('Argument "handle" missing');
+  if (IS_UNDEFINED(handles)) {
+    return response.failed('Argument "handles" missing');
   }
 
-  // Lookup handle.
-  var mirror = LookupMirror(handle);
-  if (mirror) {
-    response.body = mirror;
-  } else {
-    return response.failed('Object #' + handle + '# not found');
+  // Lookup handles.
+  var mirrors = {};
+  for (var i = 0; i < handles.length; i++) {
+    var handle = handles[i];
+    var mirror = LookupMirror(handle);
+    if (!mirror) {
+      return response.failed('Object #' + handle + '# not found');
+    }
+    mirrors[handle] = mirror;
   }
+  response.body = mirrors;
 };
 
 
@@ -1675,6 +1697,9 @@
       script.lineOffset = scripts[i].line_offset;
       script.columnOffset = scripts[i].column_offset;
       script.lineCount = scripts[i].lineCount();
+      if (scripts[i].data) {
+        script.data = scripts[i].data;
+      }
       if (includeSource) {
         script.source = scripts[i].source;
       } else {
diff --git a/src/debug-ia32.cc b/src/debug-ia32.cc
index 6d59889..9503cfc 100644
--- a/src/debug-ia32.cc
+++ b/src/debug-ia32.cc
@@ -33,6 +33,7 @@
 
 namespace v8 { namespace internal {
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 
 // A debug break in the frame exit code is identified by a call instruction.
 bool BreakLocationIterator::IsDebugBreakAtReturn() {
@@ -67,7 +68,7 @@
 }
 
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
@@ -214,5 +215,6 @@
 
 #undef __
 
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 } }  // namespace v8::internal
diff --git a/src/debug.cc b/src/debug.cc
index a4bb04d..32a96a8 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -35,12 +35,15 @@
 #include "debug.h"
 #include "execution.h"
 #include "global-handles.h"
+#include "ic.h"
+#include "ic-inl.h"
 #include "natives.h"
 #include "stub-cache.h"
 #include "log.h"
 
 namespace v8 { namespace internal {
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 static void PrintLn(v8::Local<v8::Value> value) {
   v8::Local<v8::String> s = value->ToString();
   char* data = NewArray<char>(s->Length() + 1);
@@ -288,14 +291,8 @@
     // Patch the frame exit code with a break point.
     SetDebugBreakAtReturn();
   } else {
-    // Patch the original code with the current address as the current address
-    // might have changed by the inline caching since the code was copied.
-    original_rinfo()->set_target_address(rinfo()->target_address());
-
-    // Patch the code to invoke the builtin debug break function matching the
-    // calling convention used by the call site.
-    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo()));
-    rinfo()->set_target_address(dbgbrk_code->entry());
+    // Patch the IC call.
+    SetDebugBreakAtIC();
   }
   ASSERT(IsDebugBreak());
 }
@@ -306,8 +303,8 @@
     // Restore the frame exit code.
     ClearDebugBreakAtReturn();
   } else {
-    // Patch the code to the original invoke.
-    rinfo()->set_target_address(original_rinfo()->target_address());
+    // Patch the IC call.
+    ClearDebugBreakAtIC();
   }
   ASSERT(!IsDebugBreak());
 }
@@ -360,6 +357,39 @@
 }
 
 
+void BreakLocationIterator::SetDebugBreakAtIC() {
+  // Patch the original code with the current address as the current address
+  // might have changed by the inline caching since the code was copied.
+  original_rinfo()->set_target_address(rinfo()->target_address());
+
+  RelocInfo::Mode mode = rmode();
+  if (RelocInfo::IsCodeTarget(mode)) {
+    Address target = rinfo()->target_address();
+    Handle<Code> code(Code::GetCodeFromTargetAddress(target));
+
+    // Patch the code to invoke the builtin debug break function matching the
+    // calling convention used by the call site.
+    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(code, mode));
+    rinfo()->set_target_address(dbgbrk_code->entry());
+
+    // For stubs that refer back to an inlined version clear the cached map for
+    // the inlined case to always go through the IC. As long as the break point
+    // is set the patching performed by the runtime system will take place in
+    // the code copy and will therefore have no effect on the running code
+    // keeping it from using the inlined code.
+    if (code->is_keyed_load_stub() && KeyedLoadIC::HasInlinedVersion(pc())) {
+      KeyedLoadIC::ClearInlinedVersion(pc());
+    }
+  }
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtIC() {
+  // Patch the code to the original invoke.
+  rinfo()->set_target_address(original_rinfo()->target_address());
+}
+
+
 Object* BreakLocationIterator::BreakPointObjects() {
   return debug_info_->GetBreakPointObjects(code_position());
 }
@@ -1055,48 +1085,42 @@
 
 
 // Find the builtin to use for invoking the debug break
-Handle<Code> Debug::FindDebugBreak(RelocInfo* rinfo) {
+Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
   // Find the builtin debug break function matching the calling convention
   // used by the call site.
-  RelocInfo::Mode mode = rinfo->rmode();
-
-  if (RelocInfo::IsCodeTarget(mode)) {
-    Address target = rinfo->target_address();
-    Code* code = Code::GetCodeFromTargetAddress(target);
-    if (code->is_inline_cache_stub()) {
-      if (code->is_call_stub()) {
-        return ComputeCallDebugBreak(code->arguments_count());
-      }
-      if (code->is_load_stub()) {
-        return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
-      }
-      if (code->is_store_stub()) {
-        return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
-      }
-      if (code->is_keyed_load_stub()) {
-        Handle<Code> result =
-            Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
-        return result;
-      }
-      if (code->is_keyed_store_stub()) {
-        Handle<Code> result =
-            Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
-        return result;
-      }
+  if (code->is_inline_cache_stub()) {
+    if (code->is_call_stub()) {
+      return ComputeCallDebugBreak(code->arguments_count());
     }
-    if (RelocInfo::IsConstructCall(mode)) {
+    if (code->is_load_stub()) {
+      return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
+    }
+    if (code->is_store_stub()) {
+      return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
+    }
+    if (code->is_keyed_load_stub()) {
       Handle<Code> result =
-          Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
+          Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
       return result;
     }
-    if (code->kind() == Code::STUB) {
-      ASSERT(code->major_key() == CodeStub::CallFunction ||
-             code->major_key() == CodeStub::StackCheck);
+    if (code->is_keyed_store_stub()) {
       Handle<Code> result =
-          Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
+          Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
       return result;
     }
   }
+  if (RelocInfo::IsConstructCall(mode)) {
+    Handle<Code> result =
+        Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
+    return result;
+  }
+  if (code->kind() == Code::STUB) {
+    ASSERT(code->major_key() == CodeStub::CallFunction ||
+           code->major_key() == CodeStub::StackCheck);
+    Handle<Code> result =
+        Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
+    return result;
+  }
 
   UNREACHABLE();
   return Handle<Code>::null();
@@ -1397,11 +1421,10 @@
 bool Debugger::is_loading_debugger_ = false;
 bool Debugger::never_unload_debugger_ = false;
 DebugMessageThread* Debugger::message_thread_ = NULL;
-v8::DebugMessageHandler Debugger::message_handler_ = NULL;
+v8::Debug::MessageHandler Debugger::message_handler_ = NULL;
 bool Debugger::message_handler_cleared_ = false;
-void* Debugger::message_handler_data_ = NULL;
-v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
-void* Debugger::host_dispatch_handler_data_ = NULL;
+v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
+int Debugger::host_dispatch_micros_ = 100 * 1000;
 DebuggerAgent* Debugger::agent_ = NULL;
 LockingMessageQueue Debugger::command_queue_(kQueueInitialSize);
 LockingMessageQueue Debugger::message_queue_(kQueueInitialSize);
@@ -1703,8 +1726,8 @@
     if (event_listener_->IsProxy()) {
       // C debug event listener.
       Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
-      v8::DebugEventCallback callback =
-            FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy());
+      v8::Debug::EventCallback callback =
+            FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy());
       callback(event,
                v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
                v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)),
@@ -1805,32 +1828,31 @@
   // Process requests from the debugger.
   while (true) {
     // Wait for new command in the queue.
-    command_received_->Wait();
+    if (Debugger::host_dispatch_handler_) {
+      // In case there is a host dispatch - do periodic dispatches.
+      if (!command_received_->Wait(host_dispatch_micros_)) {
+        // Timout expired, do the dispatch.
+        Debugger::host_dispatch_handler_();
+        continue;
+      }
+    } else {
+      // In case there is no host dispatch - just wait.
+      command_received_->Wait();
+    }
 
     // The debug command interrupt flag might have been set when the command was
     // added.
     StackGuard::Continue(DEBUGCOMMAND);
 
     // Get the command from the queue.
-    Vector<uint16_t> command = command_queue_.Get();
+    Message command = command_queue_.Get();
     Logger::DebugTag("Got request from command queue, in interactive loop.");
     if (!Debugger::IsDebuggerActive()) {
+      // Delete command text and user data.
+      command.Dispose();
       return;
     }
 
-    // Check if the command is a host dispatch.
-    if (command[0] == 0) {
-      if (Debugger::host_dispatch_handler_) {
-        int32_t dispatch = (command[1] << 16) | command[2];
-        Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch),
-                                         Debugger::host_dispatch_handler_data_);
-      }
-      if (auto_continue && !HasCommands()) {
-        return;
-      }
-      continue;
-    }
-
     // Invoke JavaScript to process the debug request.
     v8::Local<v8::String> fun_name;
     v8::Local<v8::Function> fun;
@@ -1838,8 +1860,10 @@
     v8::TryCatch try_catch;
     fun_name = v8::String::New("processDebugRequest");
     fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
-    request = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
-                              command.length());
+
+    request = v8::String::New(command.text().start(),
+                              command.text().length());
+    command.text().Dispose();
     static const int kArgc = 1;
     v8::Handle<Value> argv[kArgc] = { request };
     v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
@@ -1875,13 +1899,8 @@
       response = try_catch.Exception()->ToString();
     }
 
-    // Convert text result to C string.
-    v8::String::Value val(response);
-    Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
-                        response->Length());
-
     // Return the result.
-    SendMessage(str);
+    SendMessage(Message::NewOutput(response, command.client_data()));
 
     // Return from debug event processing if either the VM is put into the
     // runnning state (through a continue command) or auto continue is active
@@ -1927,12 +1946,11 @@
 }
 
 
-void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
+void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler,
                                  bool message_handler_thread) {
   ScopedLock with(debugger_access_);
 
   message_handler_ = handler;
-  message_handler_data_ = data;
   if (handler != NULL) {
     if (!message_thread_ && message_handler_thread) {
       message_thread_ = new DebugMessageThread();
@@ -1951,10 +1969,10 @@
 }
 
 
-void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
-                                      void* data) {
+void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
+                                      int period) {
   host_dispatch_handler_ = handler;
-  host_dispatch_handler_data_ = data;
+  host_dispatch_micros_ = period * 1000;
 }
 
 
@@ -1962,26 +1980,28 @@
 // public API. Messages are kept internally as Vector<uint16_t> strings, which
 // are allocated in various places and deallocated by the calling function
 // sometime after this call.
-void Debugger::InvokeMessageHandler(Vector<uint16_t> message) {
+void Debugger::InvokeMessageHandler(Message message) {
   ScopedLock with(debugger_access_);
 
   if (message_handler_ != NULL) {
-    message_handler_(message.start(), message.length(), message_handler_data_);
+    message_handler_(message.text().start(),
+                     message.text().length(),
+                     message.client_data());
   }
+  message.Dispose();
 }
 
 
-void Debugger::SendMessage(Vector<uint16_t> message) {
+void Debugger::SendMessage(Message message) {
   if (message_thread_ == NULL) {
     // If there is no message thread just invoke the message handler from the
     // V8 thread.
     InvokeMessageHandler(message);
   } else {
-    // Put a copy of the message coming from V8 on the queue. The new copy of
-    // the event string is destroyed by the message thread.
-    Vector<uint16_t> message_copy = message.Clone();
+    // Put the message coming from V8 on the queue. The text and user data will
+    // be destroyed by the message thread.
     Logger::DebugTag("Put message on event message_queue.");
-    message_queue_.Put(message_copy);
+    message_queue_.Put(message);
     message_received_->Signal();
   }
 }
@@ -2004,12 +2024,11 @@
       if (FLAG_trace_debug_json) {
         PrintLn(json_event_string);
       }
-      v8::String::Value val(json_event_string);
-      Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
-                           json_event_string->Length());
-      SendMessage(str);
+      SendMessage(Message::NewOutput(
+          json_event_string,
+          NULL /* no user data since there was no request */));
     } else {
-      SendMessage(Vector<uint16_t>::empty());
+      SendMessage(Message::NewEmptyMessage());
     }
   } else {
     PrintLn(try_catch.Exception());
@@ -2025,13 +2044,15 @@
 // by the API client thread.  This is where the API client hands off
 // processing of the command to the DebugMessageThread thread.
 // The new copy of the command is destroyed in HandleCommand().
-void Debugger::ProcessCommand(Vector<const uint16_t> command) {
-  // Make a copy of the command. Need to cast away const for Clone to work.
-  Vector<uint16_t> command_copy =
+void Debugger::ProcessCommand(Vector<const uint16_t> command,
+                              v8::Debug::ClientData* client_data) {
+  // Need to cast away const.
+  Message message = Message::NewCommand(
       Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
-                       command.length()).Clone();
+                       command.length()),
+      client_data);
   Logger::DebugTag("Put command on command_queue.");
-  command_queue_.Put(command_copy);
+  command_queue_.Put(message);
   command_received_->Signal();
 
   // Set the debug command break flag to have the command processed.
@@ -2046,23 +2067,6 @@
 }
 
 
-void Debugger::ProcessHostDispatch(void* dispatch) {
-  // Puts a host dispatch comming from the public API on the queue.
-  uint16_t hack[3];
-  hack[0] = 0;
-  hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16;
-  hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF;
-  Logger::DebugTag("Put dispatch on command_queue.");
-  command_queue_.Put(Vector<uint16_t>(hack, 3).Clone());
-  command_received_->Signal();
-
-  // Set the debug command break flag to have the host dispatch processed.
-  if (!Debug::InDebugger()) {
-    StackGuard::DebugCommand();
-  }
-}
-
-
 bool Debugger::IsDebuggerActive() {
   ScopedLock with(debugger_access_);
 
@@ -2133,9 +2137,11 @@
     // Wait and Get are paired so that semaphore count equals queue length.
     Debugger::message_received_->Wait();
     Logger::DebugTag("Get message from event message_queue.");
-    Vector<uint16_t> message = Debugger::message_queue_.Get();
-    if (message.length() > 0) {
+    Message message = Debugger::message_queue_.Get();
+    if (message.text().length() > 0) {
       Debugger::InvokeMessageHandler(message);
+    } else {
+      message.Dispose();
     }
   }
 }
@@ -2143,22 +2149,72 @@
 
 void DebugMessageThread::Stop() {
   keep_running_ = false;
-  Debugger::SendMessage(Vector<uint16_t>(NULL, 0));
+  Debugger::SendMessage(Message::NewEmptyMessage());
   Join();
 }
 
 
+Message::Message() : text_(Vector<uint16_t>::empty()),
+                     client_data_(NULL) {
+}
+
+
+Message::Message(const Vector<uint16_t>& text,
+                 v8::Debug::ClientData* data)
+    : text_(text),
+      client_data_(data) {
+}
+
+
+Message::~Message() {
+}
+
+
+void Message::Dispose() {
+  text_.Dispose();
+  delete client_data_;
+  client_data_ = NULL;
+}
+
+
+Message Message::NewCommand(const Vector<uint16_t>& command,
+                            v8::Debug::ClientData* data) {
+  return Message(command.Clone(), data);
+}
+
+
+Message Message::NewOutput(v8::Handle<v8::String> output,
+                           v8::Debug::ClientData* data) {
+  Vector<uint16_t> text;
+  if (!output.IsEmpty()) {
+    // Do not include trailing '\0'.
+    text = Vector<uint16_t>::New(output->Length());
+    output->Write(text.start(), 0, output->Length());
+  }
+  return Message(text, data);
+}
+
+
+Message Message::NewEmptyMessage() {
+  return Message();
+}
+
+
 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) {
-  messages_ = NewArray<Vector<uint16_t> >(size);
+  messages_ = NewArray<Message>(size);
 }
 
 
 MessageQueue::~MessageQueue() {
+  while (!IsEmpty()) {
+    Message m = Get();
+    m.Dispose();
+  }
   DeleteArray(messages_);
 }
 
 
-Vector<uint16_t> MessageQueue::Get() {
+Message MessageQueue::Get() {
   ASSERT(!IsEmpty());
   int result = start_;
   start_ = (start_ + 1) % size_;
@@ -2166,7 +2222,7 @@
 }
 
 
-void MessageQueue::Put(const Vector<uint16_t>& message) {
+void MessageQueue::Put(const Message& message) {
   if ((end_ + 1) % size_ == start_) {
     Expand();
   }
@@ -2180,9 +2236,11 @@
   while (!IsEmpty()) {
     new_queue.Put(Get());
   }
-  Vector<uint16_t>* array_to_free = messages_;
+  Message* array_to_free = messages_;
   *this = new_queue;
   new_queue.messages_ = array_to_free;
+  // Make the new_queue empty so that it doesn't call Dispose on any messages.
+  new_queue.start_ = new_queue.end_;
   // Automatic destructor called on new_queue, freeing array_to_free.
 }
 
@@ -2203,18 +2261,18 @@
 }
 
 
-Vector<uint16_t> LockingMessageQueue::Get() {
+Message LockingMessageQueue::Get() {
   ScopedLock sl(lock_);
-  Vector<uint16_t> result = queue_.Get();
-  Logger::DebugEvent("Get", result);
+  Message result = queue_.Get();
+  Logger::DebugEvent("Get", result.text());
   return result;
 }
 
 
-void LockingMessageQueue::Put(const Vector<uint16_t>& message) {
+void LockingMessageQueue::Put(const Message& message) {
   ScopedLock sl(lock_);
   queue_.Put(message);
-  Logger::DebugEvent("Put", message);
+  Logger::DebugEvent("Put", message.text());
 }
 
 
@@ -2223,5 +2281,6 @@
   queue_.Clear();
 }
 
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 } }  // namespace v8::internal
diff --git a/src/debug.h b/src/debug.h
index 8822c50..ffd3da9 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -28,7 +28,6 @@
 #ifndef V8_V8_DEBUG_H_
 #define V8_V8_DEBUG_H_
 
-#include "../include/v8-debug.h"
 #include "assembler.h"
 #include "code-stubs.h"
 #include "debug-agent.h"
@@ -38,6 +37,8 @@
 #include "string-stream.h"
 #include "v8threads.h"
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
+#include "../include/v8-debug.h"
 
 namespace v8 { namespace internal {
 
@@ -131,6 +132,10 @@
  private:
   void SetDebugBreak();
   void ClearDebugBreak();
+
+  void SetDebugBreakAtIC();
+  void ClearDebugBreakAtIC();
+
   bool IsDebugBreakAtReturn();
   void SetDebugBreakAtReturn();
   void ClearDebugBreakAtReturn();
@@ -204,7 +209,7 @@
   static bool IsBreakStub(Code* code);
 
   // Find the builtin to use for invoking the debug break
-  static Handle<Code> FindDebugBreak(RelocInfo* rinfo);
+  static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
 
   static Handle<Object> GetSourceBreakLocations(
       Handle<SharedFunctionInfo> shared);
@@ -396,6 +401,32 @@
 };
 
 
+// Message send by user to v8 debugger or debugger output message.
+// In addition to command text it may contain a pointer to some user data
+// which are expected to be passed along with the command reponse to message
+// handler.
+class Message {
+ public:
+  static Message NewCommand(const Vector<uint16_t>& command,
+                            v8::Debug::ClientData* data);
+  static Message NewOutput(v8::Handle<v8::String> output,
+                           v8::Debug::ClientData* data);
+  static Message NewEmptyMessage();
+  Message();
+  ~Message();
+
+  // Deletes user data and disposes of the text.
+  void Dispose();
+  Vector<uint16_t> text() const { return text_; }
+  v8::Debug::ClientData* client_data() const { return client_data_; }
+ private:
+  Message(const Vector<uint16_t>& text,
+          v8::Debug::ClientData* data);
+
+  Vector<uint16_t> text_;
+  v8::Debug::ClientData* client_data_;
+};
+
 // A Queue of Vector<uint16_t> objects.  A thread-safe version is
 // LockingMessageQueue, based on this class.
 class MessageQueue BASE_EMBEDDED {
@@ -403,14 +434,14 @@
   explicit MessageQueue(int size);
   ~MessageQueue();
   bool IsEmpty() const { return start_ == end_; }
-  Vector<uint16_t> Get();
-  void Put(const Vector<uint16_t>& message);
+  Message Get();
+  void Put(const Message& message);
   void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
  private:
   // Doubles the size of the message queue, and copies the messages.
   void Expand();
 
-  Vector<uint16_t>* messages_;
+  Message* messages_;
   int start_;
   int end_;
   int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
@@ -426,8 +457,8 @@
   explicit LockingMessageQueue(int size);
   ~LockingMessageQueue();
   bool IsEmpty() const;
-  Vector<uint16_t> Get();
-  void Put(const Vector<uint16_t>& message);
+  Message Get();
+  void Put(const Message& message);
   void Clear();
  private:
   MessageQueue queue_;
@@ -472,29 +503,29 @@
                                    Handle<Object> event_data,
                                    bool auto_continue);
   static void SetEventListener(Handle<Object> callback, Handle<Object> data);
-  static void SetMessageHandler(v8::DebugMessageHandler handler, void* data,
+  static void SetMessageHandler(v8::Debug::MessageHandler handler,
                                 bool message_handler_thread);
   static void TearDown();
-  static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
-                                     void* data);
+  static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
+                                     int period);
 
   // Invoke the message handler function.
-  static void InvokeMessageHandler(Vector< uint16_t> message);
+  static void InvokeMessageHandler(Message message);
 
   // Send a message to the message handler eiher through the message thread or
   // directly.
-  static void SendMessage(Vector<uint16_t> message);
+  static void SendMessage(Message message);
 
   // Send the JSON message for a debug event.
   static bool SendEventMessage(Handle<Object> event_data);
 
   // Add a debugger command to the command queue.
-  static void ProcessCommand(Vector<const uint16_t> command);
+  static void ProcessCommand(Vector<const uint16_t> command,
+                             v8::Debug::ClientData* client_data = NULL);
 
   // Check whether there are commands in the command queue.
   static bool HasCommands();
 
-  static void ProcessHostDispatch(void* dispatch);
   static Handle<Object> Call(Handle<JSFunction> fun,
                              Handle<Object> data,
                              bool* pending_exception);
@@ -538,11 +569,10 @@
   static bool is_loading_debugger_;  // Are we loading the debugger?
   static bool never_unload_debugger_;  // Can we unload the debugger?
   static DebugMessageThread* message_thread_;
-  static v8::DebugMessageHandler message_handler_;
+  static v8::Debug::MessageHandler message_handler_;
   static bool message_handler_cleared_;  // Was message handler cleared?
-  static void* message_handler_data_;
-  static v8::DebugHostDispatchHandler host_dispatch_handler_;
-  static void* host_dispatch_handler_data_;
+  static v8::Debug::HostDispatchHandler host_dispatch_handler_;
+  static int host_dispatch_micros_;
 
   static DebuggerAgent* agent_;
 
@@ -719,4 +749,6 @@
 
 } }  // namespace v8::internal
 
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
 #endif  // V8_V8_DEBUG_H_
diff --git a/src/disasm-arm.cc b/src/disasm-arm.cc
index d19e042..3b7474d 100644
--- a/src/disasm-arm.cc
+++ b/src/disasm-arm.cc
@@ -261,6 +261,15 @@
     case break_point:
       Print("break_point");
       return;
+    case simulator_fp_add:
+      Print("simulator_fp_add");
+      return;
+    case simulator_fp_mul:
+      Print("simulator_fp_mul");
+      return;
+    case simulator_fp_sub:
+      Print("simulator_fp_sub");
+      return;
     default:
       out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
                                            "%d",
diff --git a/src/execution.cc b/src/execution.cc
index 03017d0..1d4d9ef 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -305,6 +305,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 bool StackGuard::IsDebugBreak() {
   ExecutionAccess access;
   return thread_local_.interrupt_flags_ & DEBUGBREAK;
@@ -331,7 +332,7 @@
     set_limits(kInterruptLimit, access);
   }
 }
-
+#endif
 
 void StackGuard::Continue(InterruptFlag after_what) {
   ExecutionAccess access;
@@ -539,6 +540,7 @@
 
   ContextSwitcher::PreemptionReceived();
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   if (Debug::InDebugger()) {
     // If currently in the debugger don't do any actual preemption but record
     // that preemption occoured while in the debugger.
@@ -548,11 +550,17 @@
     v8::Unlocker unlocker;
     Thread::YieldCPU();
   }
+#else
+  // Perform preemption.
+  v8::Unlocker unlocker;
+  Thread::YieldCPU();
+#endif
 
   return Heap::undefined_value();
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 Object* Execution::DebugBreakHelper() {
   // Just continue if breaks are disabled.
   if (Debug::disable_break()) {
@@ -598,12 +606,14 @@
   // Return to continue execution.
   return Heap::undefined_value();
 }
-
+#endif
 
 Object* Execution::HandleStackGuardInterrupt() {
+#ifdef ENABLE_DEBUGGER_SUPPORT
   if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
     DebugBreakHelper();
   }
+#endif
   if (StackGuard::IsPreempted()) RuntimePreempt();
   if (StackGuard::IsInterrupted()) {
     // interrupt
@@ -626,7 +636,7 @@
 
 v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
   // All allocation spaces other than NEW_SPACE have the same effect.
-  Heap::CollectGarbage(0, OLD_DATA_SPACE);
+  Heap::CollectAllGarbage();
   return v8::Undefined();
 }
 
diff --git a/src/execution.h b/src/execution.h
index 6531572..6f2f689 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -118,8 +118,9 @@
                                           Handle<JSFunction> fun,
                                           Handle<Object> pos,
                                           Handle<Object> is_global);
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
   static Object* DebugBreakHelper();
+#endif
 
   // If the stack guard is triggered, but it is not an actual
   // stack overflow, then handle the interruption accordingly.
@@ -158,11 +159,13 @@
   static void Preempt();
   static bool IsInterrupted();
   static void Interrupt();
-  static bool IsDebugBreak();
-  static void DebugBreak();
-  static bool IsDebugCommand();
-  static void DebugCommand();
   static void Continue(InterruptFlag after_what);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  static void DebugBreak();
+  static void DebugCommand();
+  static bool IsDebugBreak();
+  static bool IsDebugCommand();
+#endif
 
  private:
   // You should hold the ExecutionAccess lock when calling this method.
diff --git a/src/factory.cc b/src/factory.cc
index e29c84d..c849ab7 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -173,6 +173,7 @@
   script->set_id(Heap::last_script_id());
   script->set_line_offset(Smi::FromInt(0));
   script->set_column_offset(Smi::FromInt(0));
+  script->set_data(Heap::undefined_value());
   script->set_type(Smi::FromInt(SCRIPT_TYPE_NORMAL));
   script->set_wrapper(*Factory::NewProxy(0, TENURED));
   script->set_line_ends(Heap::undefined_value());
@@ -671,6 +672,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
   // Get the original code of the function.
   Handle<Code> code(shared->code());
@@ -700,6 +702,7 @@
 
   return debug_info;
 }
+#endif
 
 
 Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
diff --git a/src/factory.h b/src/factory.h
index 2564c3c..54f2089 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -310,8 +310,9 @@
                                                   uint32_t key,
                                                   Handle<Object> value);
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
-
+#endif
 
   // Return a map using the map cache in the global context.
   // The key the an ordered set of property names.
diff --git a/src/frames.cc b/src/frames.cc
index 88c723d..1eedbf6 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -647,10 +647,10 @@
   handler->Iterate(v);
   // Make sure that there's the entry frame does not contain more than
   // one stack handler.
-  if (kDebug) {
-    it.Advance();
-    ASSERT(it.done());
-  }
+#ifdef DEBUG
+  it.Advance();
+  ASSERT(it.done());
+#endif
 }
 
 
diff --git a/src/func-name-inferrer.cc b/src/func-name-inferrer.cc
index ef0c7db..75f7a99 100644
--- a/src/func-name-inferrer.cc
+++ b/src/func-name-inferrer.cc
@@ -63,11 +63,12 @@
 }
 
 
-void FuncNameInferrer::MaybeInferFunctionName() {
-  if (func_to_infer_ != NULL) {
-    func_to_infer_->set_inferred_name(MakeNameFromStack());
-    func_to_infer_ = NULL;
+void FuncNameInferrer::InferFunctionsNames() {
+  Handle<String> func_name = MakeNameFromStack();
+  for (int i = 0; i < funcs_to_infer_.length(); ++i) {
+    funcs_to_infer_[i]->set_inferred_name(func_name);
   }
+  funcs_to_infer_.Rewind(0);
 }
 
 
diff --git a/src/func-name-inferrer.h b/src/func-name-inferrer.h
index 9dcf7c5..d8270c3 100644
--- a/src/func-name-inferrer.h
+++ b/src/func-name-inferrer.h
@@ -45,7 +45,7 @@
   FuncNameInferrer() :
       entries_stack_(10),
       names_stack_(5),
-      func_to_infer_(NULL),
+      funcs_to_infer_(4),
       dot_(Factory::NewStringFromAscii(CStrVector("."))) {
   }
 
@@ -57,39 +57,34 @@
     entries_stack_.Add(names_stack_.length());
   }
 
-  void Leave() {
-    ASSERT(IsOpen());
-    names_stack_.Rewind(entries_stack_.RemoveLast());
-  }
-
   void PushName(Handle<String> name) {
     if (IsOpen()) {
       names_stack_.Add(name);
     }
   }
 
-  void SetFuncToInfer(FunctionLiteral* func_to_infer) {
+  void AddFunction(FunctionLiteral* func_to_infer) {
     if (IsOpen()) {
-      // If we encounter another function literal after already having
-      // encountered one, the second one replaces the first.
-      func_to_infer_ = func_to_infer;
+      funcs_to_infer_.Add(func_to_infer);
     }
   }
 
   void InferAndLeave() {
     ASSERT(IsOpen());
-    MaybeInferFunctionName();
-    Leave();
+    if (!funcs_to_infer_.is_empty()) {
+      InferFunctionsNames();
+    }
+    names_stack_.Rewind(entries_stack_.RemoveLast());
   }
 
  private:
   Handle<String> MakeNameFromStack();
   Handle<String> MakeNameFromStackHelper(int pos, Handle<String> prev);
-  void MaybeInferFunctionName();
+  void InferFunctionsNames();
 
   List<int> entries_stack_;
   List<Handle<String> > names_stack_;
-  FunctionLiteral* func_to_infer_;
+  List<FunctionLiteral*> funcs_to_infer_;
   Handle<String> dot_;
 
   DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
diff --git a/src/globals.h b/src/globals.h
index 1579c3d..fbbe7c9 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -80,12 +80,6 @@
 // -----------------------------------------------------------------------------
 // Constants
 
-#ifdef DEBUG
-const bool kDebug = true;
-#else
-const bool kDebug = false;
-#endif  // DEBUG
-
 const int KB = 1024;
 const int MB = KB * KB;
 const int GB = KB * KB * KB;
@@ -146,7 +140,6 @@
 class BreakableStatement;
 class Code;
 class CodeGenerator;
-class CodeRegion;
 class CodeStub;
 class Context;
 class Debug;
diff --git a/src/handles.cc b/src/handles.cc
index 60d8236..99161ce 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -212,10 +212,20 @@
 }
 
 
-Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
-                           Handle<String> key,
-                           Handle<Object> value,
-                           PropertyAttributes attributes) {
+Handle<Object> ForceSetProperty(Handle<JSObject> object,
+                                Handle<Object> key,
+                                Handle<Object> value,
+                                PropertyAttributes attributes) {
+  CALL_HEAP_FUNCTION(
+      Runtime::ForceSetObjectProperty(object, key, value, attributes), Object);
+}
+
+
+Handle<Object> IgnoreAttributesAndSetLocalProperty(
+    Handle<JSObject> object,
+    Handle<String> key,
+    Handle<Object> value,
+    PropertyAttributes attributes) {
   CALL_HEAP_FUNCTION(object->
       IgnoreAttributesAndSetLocalProperty(*key, *value, attributes), Object);
 }
@@ -491,17 +501,6 @@
         break;
       }
 
-      // Compute the property keys.
-      content = UnionOfKeys(content, GetEnumPropertyKeys(current));
-
-      // Add the property keys from the interceptor.
-      if (current->HasNamedInterceptor()) {
-        v8::Handle<v8::Array> result =
-            GetKeysForNamedInterceptor(object, current);
-        if (!result.IsEmpty())
-          content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
-      }
-
       // Compute the element keys.
       Handle<FixedArray> element_keys =
           Factory::NewFixedArray(current->NumberOfEnumElements());
@@ -515,6 +514,17 @@
         if (!result.IsEmpty())
           content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
       }
+
+      // Compute the property keys.
+      content = UnionOfKeys(content, GetEnumPropertyKeys(current));
+
+      // Add the property keys from the interceptor.
+      if (current->HasNamedInterceptor()) {
+        v8::Handle<v8::Array> result =
+            GetKeysForNamedInterceptor(object, current);
+        if (!result.IsEmpty())
+          content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
+      }
     }
   }
   return content;
@@ -549,7 +559,7 @@
         index++;
       }
     }
-    (*storage)->SortPairs(*sort_array);
+    (*storage)->SortPairs(*sort_array, sort_array->length());
     Handle<FixedArray> bridge_storage =
         Factory::NewFixedArray(DescriptorArray::kEnumCacheBridgeLength);
     DescriptorArray* desc = object->map()->instance_descriptors();
@@ -651,6 +661,7 @@
   // We shouldn't get here if compiling the script failed.
   ASSERT(!boilerplate.is_null());
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // When the debugger running in its own context touches lazy loaded
   // functions loading can be triggered. In that case ensure that the
   // execution of the boilerplate is in the correct context.
@@ -659,6 +670,7 @@
       Top::context() == *Debug::debug_context()) {
     Top::set_context(*compile_context);
   }
+#endif
 
   // Reset the lazy load data before running the script to make sure
   // not to get recursive lazy loading.
diff --git a/src/handles.h b/src/handles.h
index c8e534e..9cc1db4 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -196,6 +196,11 @@
                            Handle<Object> value,
                            PropertyAttributes attributes);
 
+Handle<Object> ForceSetProperty(Handle<JSObject> object,
+                                Handle<Object> key,
+                                Handle<Object> value,
+                                PropertyAttributes attributes);
+
 Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
                                                    Handle<String> key,
                                                    Handle<Object> value,
diff --git a/src/heap.cc b/src/heap.cc
index 7a8b728..a57884c 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2679,7 +2679,10 @@
   SYNCHRONIZE_TAG("bootstrapper");
   Top::Iterate(v);
   SYNCHRONIZE_TAG("top");
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
   Debug::Iterate(v);
+#endif
   SYNCHRONIZE_TAG("debug");
   CompilationCache::Iterate(v);
   SYNCHRONIZE_TAG("compilationcache");
diff --git a/src/ic-arm.cc b/src/ic-arm.cc
index 4db3980..ad6eb2c 100644
--- a/src/ic-arm.cc
+++ b/src/ic-arm.cc
@@ -39,7 +39,7 @@
 // Static IC stub generators.
 //
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 // Helper function used from LoadIC/CallIC GenerateNormal.
@@ -96,7 +96,9 @@
     // Compute the masked index: (hash + i + i * i) & mask.
     __ ldr(t1, FieldMemOperand(r2, String::kLengthOffset));
     __ mov(t1, Operand(t1, LSR, String::kHashShift));
-    if (i > 0) __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i)));
+    if (i > 0) {
+      __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i)));
+    }
     __ and_(t1, t1, Operand(r3));
 
     // Scale the index by multiplying by the element size.
@@ -505,6 +507,8 @@
 // TODO(181): Implement map patching once loop nesting is tracked on
 // the ARM platform so we can generate inlined fast-case code for
 // array indexing in loops.
+bool KeyedLoadIC::HasInlinedVersion(Address address) { return false; }
+void KeyedLoadIC::ClearInlinedVersion(Address address) { }
 void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) { }
 
 
diff --git a/src/ic-ia32.cc b/src/ic-ia32.cc
index 9060f2d..664303f 100644
--- a/src/ic-ia32.cc
+++ b/src/ic-ia32.cc
@@ -38,7 +38,7 @@
 // Static IC stub generators.
 //
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 // Helper function used to load a property from a dictionary backing storage.
@@ -91,7 +91,9 @@
     // Compute the masked index: (hash + i + i * i) & mask.
     __ mov(r1, FieldOperand(name, String::kLengthOffset));
     __ shr(r1, String::kHashShift);
-    if (i > 0) __ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
+    if (i > 0) {
+      __ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
+    }
     __ and_(r1, Operand(r2));
 
     // Scale the index by multiplying by the element size.
@@ -727,8 +729,24 @@
 }
 
 
+// One byte opcode for test eax,0xXXXXXXXX.
+static const byte kTestEaxByte = 0xA9;
+
+
+bool KeyedLoadIC::HasInlinedVersion(Address address) {
+  Address test_instruction_address = address + 4;  // 4 = stub address
+  return *test_instruction_address == kTestEaxByte;
+}
+
+
+void KeyedLoadIC::ClearInlinedVersion(Address address) {
+  // Insert null as the map to check for to make sure the map check fails
+  // sending control flow to the IC instead of the inlined version.
+  PatchInlinedMapCheck(address, Heap::null_value());
+}
+
+
 void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) {
-  static const byte kTestEaxByte = 0xA9;
   Address test_instruction_address = address + 4;  // 4 = stub address
   // The keyed load has a fast inlined case if the IC call instruction
   // is immediately followed by a test instruction.
@@ -742,7 +760,7 @@
     // bytes of the 7-byte operand-immediate compare instruction, so
     // we add 3 to the offset to get the map address.
     Address map_address = test_instruction_address + offset_value + 3;
-    // patch the map check.
+    // Patch the map check.
     (*(reinterpret_cast<Object**>(map_address))) = value;
   }
 }
diff --git a/src/ic-inl.h b/src/ic-inl.h
index f5ce0ad..bb56962 100644
--- a/src/ic-inl.h
+++ b/src/ic-inl.h
@@ -39,6 +39,7 @@
   // Get the address of the call.
   Address result = pc() - Assembler::kTargetAddrToReturnAddrDist;
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // First check if any break points are active if not just return the address
   // of the call.
   if (!Debug::has_break_points()) return result;
@@ -55,6 +56,9 @@
     // No break point here just return the address of the call.
     return result;
   }
+#else
+  return result;
+#endif
 }
 
 
diff --git a/src/ic.cc b/src/ic.cc
index d7bd764..51768d7 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -100,6 +100,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 Address IC::OriginalCodeAddress() {
   HandleScope scope;
   // Compute the JavaScript frame for the frame pointer of this IC
@@ -126,7 +127,7 @@
   int delta = original_code->instruction_start() - code->instruction_start();
   return addr + delta;
 }
-
+#endif
 
 IC::State IC::StateFrom(Code* target, Object* receiver) {
   IC::State state = target->ic_state();
@@ -236,7 +237,7 @@
   // Make sure to also clear the map used in inline fast cases.  If we
   // do not clear these maps, cached code can keep objects alive
   // through the embedded maps.
-  PatchInlinedMapCheck(address, Heap::null_value());
+  ClearInlinedVersion(address);
   SetTargetAtAddress(address, initialize_stub());
 }
 
@@ -356,6 +357,7 @@
       if (opt->IsJSFunction()) return opt;
     }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
     // Handle stepping into a function if step into is active.
     if (Debug::StepInActive()) {
       // Protect the result in a handle as the debugger can allocate and might
@@ -365,6 +367,7 @@
       Debug::HandleStepIn(function, fp(), false);
       return *function;
     }
+#endif
 
     return result;
   }
diff --git a/src/ic.h b/src/ic.h
index bbe1f6d..11d47ae 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -107,9 +107,11 @@
   Address fp() const { return fp_; }
   Address pc() const { return *pc_address_; }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Computes the address in the original code when the code running is
   // containing break points (calls to DebugBreakXXX builtins).
   Address OriginalCodeAddress();
+#endif
 
   // Set the call-site target.
   void set_target(Code* code) { SetTargetAtAddress(address(), code); }
@@ -252,6 +254,12 @@
   static void GeneratePreMonomorphic(MacroAssembler* masm);
   static void GenerateGeneric(MacroAssembler* masm);
 
+  // Check if this IC corresponds to an inlined version.
+  static bool HasInlinedVersion(Address address);
+
+  // Clear the use of the inlined version.
+  static void ClearInlinedVersion(Address address);
+
  private:
   static void Generate(MacroAssembler* masm, const ExternalReference& f);
 
diff --git a/src/jump-target-arm.cc b/src/jump-target-arm.cc
index 3ce5f30..6d375e5 100644
--- a/src/jump-target-arm.cc
+++ b/src/jump-target-arm.cc
@@ -35,7 +35,7 @@
 // -------------------------------------------------------------------------
 // JumpTarget implementation.
 
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
 
 void JumpTarget::DoJump() {
   ASSERT(cgen_ != NULL);
diff --git a/src/jump-target-ia32.cc b/src/jump-target-ia32.cc
index 8afb0a8..a1049b2 100644
--- a/src/jump-target-ia32.cc
+++ b/src/jump-target-ia32.cc
@@ -35,7 +35,7 @@
 // -------------------------------------------------------------------------
 // JumpTarget implementation.
 
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
 
 void JumpTarget::DoJump() {
   ASSERT(cgen_ != NULL);
diff --git a/src/log.cc b/src/log.cc
index d9e304d..f23b73b 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -814,35 +814,6 @@
 }
 
 
-void Logger::BeginCodeRegionEvent(CodeRegion* region,
-                                  Assembler* masm,
-                                  const char* name) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  if (logfile_ == NULL || !FLAG_log_code) return;
-  LogMessageBuilder msg;
-  msg.Append("begin-code-region,0x%x,0x%x,0x%x,%s\n",
-             reinterpret_cast<unsigned int>(region),
-             reinterpret_cast<unsigned int>(masm),
-             masm->pc_offset(),
-             name);
-  msg.WriteToLogFile();
-#endif
-}
-
-
-void Logger::EndCodeRegionEvent(CodeRegion* region, Assembler* masm) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  if (logfile_ == NULL || !FLAG_log_code) return;
-  LogMessageBuilder msg;
-  msg.Append("end-code-region,0x%x,0x%x,0x%x\n",
-             reinterpret_cast<unsigned int>(region),
-             reinterpret_cast<unsigned int>(masm),
-             masm->pc_offset());
-  msg.WriteToLogFile();
-#endif
-}
-
-
 void Logger::ResourceEvent(const char* name, const char* tag) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (logfile_ == NULL || !FLAG_log) return;
diff --git a/src/log.h b/src/log.h
index bbcfa42..44c1957 100644
--- a/src/log.h
+++ b/src/log.h
@@ -174,11 +174,6 @@
   static void CodeMoveEvent(Address from, Address to);
   // Emits a code delete event.
   static void CodeDeleteEvent(Address from);
-  // Emits region delimiters
-  static void BeginCodeRegionEvent(CodeRegion* region,
-                                   Assembler* masm,
-                                   const char* name);
-  static void EndCodeRegionEvent(CodeRegion* region, Assembler* masm);
 
   // ==== Events logged by --log-gc. ====
   // Heap sampling events: start, end, and individual types.
diff --git a/src/macro-assembler-arm.cc b/src/macro-assembler-arm.cc
index 88a300b..365c1ad 100644
--- a/src/macro-assembler-arm.cc
+++ b/src/macro-assembler-arm.cc
@@ -168,11 +168,11 @@
 }
 
 
-void MacroAssembler::Ret() {
+void MacroAssembler::Ret(Condition cond) {
 #if USE_BX
-  bx(lr);
+  bx(lr, cond);
 #else
-  mov(pc, Operand(lr));
+  mov(pc, Operand(lr), LeaveCC, cond);
 #endif
 }
 
@@ -320,16 +320,19 @@
   add(r6, fp, Operand(r4, LSL, kPointerSizeLog2));
   add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Save the state of all registers to the stack from the memory
   // location. This is needed to allow nested break points.
   if (type == StackFrame::EXIT_DEBUG) {
     // Use sp as base to push.
     CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
   }
+#endif
 }
 
 
 void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Restore the memory copy of the registers by digging them out from
   // the stack. This is needed to allow nested break points.
   if (type == StackFrame::EXIT_DEBUG) {
@@ -339,6 +342,7 @@
     add(r3, fp, Operand(kOffset));
     CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
   }
+#endif
 
   // Clear top frame.
   mov(r3, Operand(0));
@@ -348,9 +352,9 @@
   // Restore current context from top and clear it in debug mode.
   mov(ip, Operand(ExternalReference(Top::k_context_address)));
   ldr(cp, MemOperand(ip));
-  if (kDebug) {
-    str(r3, MemOperand(ip));
-  }
+#ifdef DEBUG
+  str(r3, MemOperand(ip));
+#endif
 
   // Pop the arguments, restore registers, and return.
   mov(sp, Operand(fp));  // respect ABI stack constraint
@@ -491,6 +495,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 void MacroAssembler::SaveRegistersToMemory(RegList regs) {
   ASSERT((regs & ~kJSCallerSaved) == 0);
   // Copy the content of registers to memory location.
@@ -548,7 +553,7 @@
     }
   }
 }
-
+#endif
 
 void MacroAssembler::PushTryHandler(CodeLocation try_location,
                                     HandlerType type) {
@@ -674,10 +679,10 @@
   // Load current lexical context from the stack frame.
   ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
   // In debug mode, make sure the lexical context is set.
-  if (kDebug) {
-    cmp(scratch, Operand(0));
-    Check(ne, "we should not have an empty lexical context");
-  }
+#ifdef DEBUG
+  cmp(scratch, Operand(0));
+  Check(ne, "we should not have an empty lexical context");
+#endif
 
   // Load the global context of the current context.
   int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
diff --git a/src/macro-assembler-arm.h b/src/macro-assembler-arm.h
index 4b999fd..d3835be 100644
--- a/src/macro-assembler-arm.h
+++ b/src/macro-assembler-arm.h
@@ -86,7 +86,7 @@
   void Call(Register target, Condition cond = al);
   void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
   void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
-  void Ret();
+  void Ret(Condition cond = al);
   // Jumps to the label at the index given by the Smi in "index".
   void SmiJumpTable(Register index, Vector<Label*> targets);
 
@@ -138,6 +138,7 @@
                       InvokeFlag flag);
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // ---------------------------------------------------------------------------
   // Debugger Support
 
@@ -147,7 +148,7 @@
   void CopyRegistersFromStackToMemory(Register base,
                                       Register scratch,
                                       RegList regs);
-
+#endif
 
   // ---------------------------------------------------------------------------
   // Exception handling
@@ -297,6 +298,15 @@
 }
 
 
+#ifdef GENERATED_CODE_COVERAGE
+#define CODE_COVERAGE_STRINGIFY(x) #x
+#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
+#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
+#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
+#else
+#define ACCESS_MASM(masm) masm->
+#endif
+
 
 } }  // namespace v8::internal
 
diff --git a/src/macro-assembler-ia32.cc b/src/macro-assembler-ia32.cc
index 4fad3be..d6d5800 100644
--- a/src/macro-assembler-ia32.cc
+++ b/src/macro-assembler-ia32.cc
@@ -216,6 +216,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 void MacroAssembler::SaveRegistersToMemory(RegList regs) {
   ASSERT((regs & ~kJSCallerSaved) == 0);
   // Copy the content of registers to memory location.
@@ -290,7 +291,7 @@
     }
   }
 }
-
+#endif
 
 void MacroAssembler::Set(Register dst, const Immediate& x) {
   if (x.is_zero()) {
@@ -378,6 +379,7 @@
   mov(edi, Operand(eax));
   lea(esi, Operand(ebp, eax, times_4, offset));
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Save the state of all registers to the stack from the memory
   // location. This is needed to allow nested break points.
   if (type == StackFrame::EXIT_DEBUG) {
@@ -389,6 +391,7 @@
     // associated with this issue).
     PushRegistersFromMemory(kJSCallerSaved);
   }
+#endif
 
   // Reserve space for two arguments: argc and argv.
   sub(Operand(esp), Immediate(2 * kPointerSize));
@@ -406,6 +409,7 @@
 
 
 void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Restore the memory copy of the registers by digging them out from
   // the stack. This is needed to allow nested break points.
   if (type == StackFrame::EXIT_DEBUG) {
@@ -416,6 +420,7 @@
     lea(ebx, Operand(ebp, kOffset));
     CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
   }
+#endif
 
   // Get the return address from the stack and restore the frame pointer.
   mov(ecx, Operand(ebp, 1 * kPointerSize));
@@ -427,9 +432,9 @@
   // Restore current context from top and clear it in debug mode.
   ExternalReference context_address(Top::k_context_address);
   mov(esi, Operand::StaticVariable(context_address));
-  if (kDebug) {
-    mov(Operand::StaticVariable(context_address), Immediate(0));
-  }
+#ifdef DEBUG
+  mov(Operand::StaticVariable(context_address), Immediate(0));
+#endif
 
   // Push the return address to get ready to return.
   push(ecx);
diff --git a/src/macro-assembler-ia32.h b/src/macro-assembler-ia32.h
index 40aa84a..ae3a853 100644
--- a/src/macro-assembler-ia32.h
+++ b/src/macro-assembler-ia32.h
@@ -73,7 +73,7 @@
                    Register value,
                    Register scratch);
 
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // ---------------------------------------------------------------------------
   // Debugger Support
 
@@ -84,7 +84,7 @@
   void CopyRegistersFromStackToMemory(Register base,
                                       Register scratch,
                                       RegList regs);
-
+#endif
 
   // ---------------------------------------------------------------------------
   // Activation frames
@@ -343,6 +343,29 @@
   return Operand(object, index, scale, offset - kHeapObjectTag);
 }
 
+
+#ifdef GENERATED_CODE_COVERAGE
+extern void LogGeneratedCodeCoverage(const char* file_line);
+#define CODE_COVERAGE_STRINGIFY(x) #x
+#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
+#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
+#define ACCESS_MASM(masm) {                                               \
+    byte* ia32_coverage_function =                                        \
+        reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
+    masm->pushfd();                                                       \
+    masm->pushad();                                                       \
+    masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));         \
+    masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY);         \
+    masm->pop(eax);                                                       \
+    masm->popad();                                                        \
+    masm->popfd();                                                        \
+  }                                                                       \
+  masm->
+#else
+#define ACCESS_MASM(masm) masm->
+#endif
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_MACRO_ASSEMBLER_IA32_H_
diff --git a/src/messages.js b/src/messages.js
index cd9a1e8..fa6fb1f 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -98,6 +98,7 @@
   instanceof_function_expected: "Expecting a function in instanceof check, but got %0",
   instanceof_nonobject_proto:   "Function has non-object prototype '%0' in instanceof check",
   null_to_object:               "Cannot convert null to object",
+  reduce_no_initial:            "Reduce of empty array with no initial value",
   // RangeError
   invalid_array_length:         "Invalid array length",
   invalid_array_apply_length:   "Function.prototype.apply supports only up to 1024 arguments",
diff --git a/src/mirror-delay.js b/src/mirror-delay.js
index 9c9d713..dc4d7eb 100644
--- a/src/mirror-delay.js
+++ b/src/mirror-delay.js
@@ -1582,6 +1582,11 @@
 };
 
 
+ScriptMirror.prototype.data = function() {
+  return this.script_.data;
+};
+
+
 ScriptMirror.prototype.scriptType = function() {
   return this.script_.type;
 };
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index f40fd3e..635ef0f 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -924,7 +924,11 @@
   VerifyPointer(name());
   line_offset()->SmiVerify();
   column_offset()->SmiVerify();
+  VerifyPointer(data());
+  VerifyPointer(wrapper());
   type()->SmiVerify();
+  VerifyPointer(line_ends());
+  VerifyPointer(id());
 }
 
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index c2143ea..73b9c84 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2053,10 +2053,12 @@
 ACCESSORS(Script, id, Object, kIdOffset)
 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
+ACCESSORS(Script, data, Object, kDataOffset)
 ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
 ACCESSORS(Script, type, Smi, kTypeOffset)
 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
@@ -2066,6 +2068,7 @@
 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
+#endif
 
 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
diff --git a/src/objects.cc b/src/objects.cc
index 9c640f4..31c5bab 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -43,22 +43,6 @@
 
 namespace v8 { namespace internal {
 
-#define FIELD_ADDR(p, offset) \
-  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
-
-
-#define WRITE_FIELD(p, offset, value) \
-  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
-
-
-#define WRITE_INT_FIELD(p, offset, value) \
-  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
-
-
-#define WRITE_BARRIER(object, offset) \
-  Heap::RecordWrite(object->address(), offset);
-
-
 // Getters and setters are stored in a fixed array property.  These are
 // constants for their indices.
 const int kGetterIndex = 0;
@@ -1800,6 +1784,17 @@
     && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
     return SetPropertyWithFailedAccessCheck(result, name, value);
   }
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return value;
+    ASSERT(proto->IsJSGlobalObject());
+    return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty(
+        name,
+        value,
+        attributes);
+  }
+
   // Check for accessor in prototype chain removed here in clone.
   if (result->IsNotFound()) {
     return AddProperty(name, value, attributes);
@@ -1820,20 +1815,16 @@
         return AddFastPropertyUsingMap(result->GetTransitionMap(),
                                        name,
                                        value);
-      } else {
-        return ConvertDescriptorToField(name, value, attributes);
       }
+      return ConvertDescriptorToField(name, value, attributes);
     case CONSTANT_FUNCTION:
       if (value == result->GetConstantFunction()) return value;
       // Only replace the function if necessary.
       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
     case CALLBACKS:
-      return SetPropertyWithCallback(result->GetCallbackObject(),
-                                     name,
-                                     value,
-                                     result->holder());
     case INTERCEPTOR:
-      return SetPropertyWithInterceptor(name, value, attributes);
+      // Override callback in clone
+      return ConvertDescriptorToField(name, value, attributes);
     case CONSTANT_TRANSITION:
       // Replace with a MAP_TRANSITION to a new map with a FIELD, even
       // if the value is a function.
@@ -4678,6 +4669,7 @@
     it.rinfo()->set_target_object(code);
   }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   if (Debug::has_break_points()) {
     for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN));
          !it.done();
@@ -4691,6 +4683,7 @@
       }
     }
   }
+#endif
   set_ic_flag(IC_TARGET_IS_OBJECT);
 }
 
@@ -4712,10 +4705,12 @@
       v->VisitCodeTarget(it.rinfo());
     } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
       v->VisitExternalReference(it.rinfo()->target_reference_address());
+#ifdef ENABLE_DEBUGGER_SUPPORT
     } else if (Debug::has_break_points() &&
                RelocInfo::IsJSReturn(rmode) &&
                it.rinfo()->IsCallInstruction()) {
       v->VisitDebugTarget(it.rinfo());
+#endif
     } else if (rmode == RelocInfo::RUNTIME_ENTRY) {
       v->VisitRuntimeEntry(it.rinfo());
     }
@@ -4740,6 +4735,7 @@
     it.rinfo()->set_target_address(code->instruction_start());
   }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   if (Debug::has_break_points()) {
     for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN));
          !it.done();
@@ -4751,6 +4747,7 @@
       }
     }
   }
+#endif
   set_ic_flag(IC_TARGET_IS_ADDRESS);
 }
 
@@ -5138,7 +5135,7 @@
       VMState state(EXTERNAL);
       result = getter(index, info);
     }
-    if (!result.IsEmpty()) return !result->IsUndefined();
+    if (!result.IsEmpty()) return true;
   }
   return holder_handle->HasElementPostInterceptor(*receiver_handle, index);
 }
@@ -5861,43 +5858,46 @@
 }
 
 
-void FixedArray::Swap(int i, int j) {
+void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
   Object* temp = get(i);
   set(i, get(j));
   set(j, temp);
+  if (this != numbers) {
+    temp = numbers->get(i);
+    numbers->set(i, numbers->get(j));
+    numbers->set(j, temp);
+  }
 }
 
 
-static void InsertionSortPairs(FixedArray* content, FixedArray* smis) {
-  int len = smis->length();
+static void InsertionSortPairs(FixedArray* content,
+                               FixedArray* numbers,
+                               int len) {
   for (int i = 1; i < len; i++) {
     int j = i;
     while (j > 0 &&
-           Smi::cast(smis->get(j-1))->value() >
-               Smi::cast(smis->get(j))->value()) {
-      smis->Swap(j-1, j);
-      content->Swap(j-1, j);
+           (NumberToUint32(numbers->get(j - 1)) >
+            NumberToUint32(numbers->get(j)))) {
+      content->SwapPairs(numbers, j - 1, j);
       j--;
     }
   }
 }
 
 
-void HeapSortPairs(FixedArray* content, FixedArray* smis) {
+void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
   // In-place heap sort.
-  ASSERT(content->length() == smis->length());
-  int len = smis->length();
+  ASSERT(content->length() == numbers->length());
 
   // Bottom-up max-heap construction.
   for (int i = 1; i < len; ++i) {
     int child_index = i;
     while (child_index > 0) {
       int parent_index = ((child_index + 1) >> 1) - 1;
-      int parent_value = Smi::cast(smis->get(parent_index))->value();
-      int child_value = Smi::cast(smis->get(child_index))->value();
+      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
+      uint32_t child_value = NumberToUint32(numbers->get(child_index));
       if (parent_value < child_value) {
-        content->Swap(parent_index, child_index);
-        smis->Swap(parent_index, child_index);
+        content->SwapPairs(numbers, parent_index, child_index);
       } else {
         break;
       }
@@ -5908,25 +5908,22 @@
   // Extract elements and create sorted array.
   for (int i = len - 1; i > 0; --i) {
     // Put max element at the back of the array.
-    content->Swap(0, i);
-    smis->Swap(0, i);
+    content->SwapPairs(numbers, 0, i);
     // Sift down the new top element.
     int parent_index = 0;
     while (true) {
       int child_index = ((parent_index + 1) << 1) - 1;
       if (child_index >= i) break;
-      uint32_t child1_value = Smi::cast(smis->get(child_index))->value();
-      uint32_t child2_value = Smi::cast(smis->get(child_index + 1))->value();
-      uint32_t parent_value = Smi::cast(smis->get(parent_index))->value();
+      uint32_t child1_value = NumberToUint32(numbers->get(child_index));
+      uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
+      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
       if (child_index + 1 >= i || child1_value > child2_value) {
         if (parent_value > child1_value) break;
-        content->Swap(parent_index, child_index);
-        smis->Swap(parent_index, child_index);
+        content->SwapPairs(numbers, parent_index, child_index);
         parent_index = child_index;
       } else {
         if (parent_value > child2_value) break;
-        content->Swap(parent_index, child_index + 1);
-        smis->Swap(parent_index, child_index + 1);
+        content->SwapPairs(numbers, parent_index, child_index + 1);
         parent_index = child_index + 1;
       }
     }
@@ -5934,43 +5931,41 @@
 }
 
 
-// Sort this array and the smis as pairs wrt. the (distinct) smis.
-void FixedArray::SortPairs(FixedArray* smis) {
-  ASSERT(this->length() == smis->length());
-  int len = smis->length();
+// Sort this array and the numbers as pairs wrt. the (distinct) numbers.
+void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
+  ASSERT(this->length() == numbers->length());
   // For small arrays, simply use insertion sort.
   if (len <= 10) {
-    InsertionSortPairs(this, smis);
+    InsertionSortPairs(this, numbers, len);
     return;
   }
   // Check the range of indices.
-  int min_index = Smi::cast(smis->get(0))->value();
-  int max_index = min_index;
-  int i;
+  uint32_t min_index = NumberToUint32(numbers->get(0));
+  uint32_t max_index = min_index;
+  uint32_t i;
   for (i = 1; i < len; i++) {
-    if (Smi::cast(smis->get(i))->value() < min_index) {
-      min_index = Smi::cast(smis->get(i))->value();
-    } else if (Smi::cast(smis->get(i))->value() > max_index) {
-      max_index = Smi::cast(smis->get(i))->value();
+    if (NumberToUint32(numbers->get(i)) < min_index) {
+      min_index = NumberToUint32(numbers->get(i));
+    } else if (NumberToUint32(numbers->get(i)) > max_index) {
+      max_index = NumberToUint32(numbers->get(i));
     }
   }
   if (max_index - min_index + 1 == len) {
     // Indices form a contiguous range, unless there are duplicates.
-    // Do an in-place linear time sort assuming distinct smis, but
+    // Do an in-place linear time sort assuming distinct numbers, but
     // avoid hanging in case they are not.
     for (i = 0; i < len; i++) {
-      int p;
-      int j = 0;
+      uint32_t p;
+      uint32_t j = 0;
       // While the current element at i is not at its correct position p,
       // swap the elements at these two positions.
-      while ((p = Smi::cast(smis->get(i))->value() - min_index) != i &&
+      while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
              j++ < len) {
-        this->Swap(i, p);
-        smis->Swap(i, p);
+        SwapPairs(numbers, i, p);
       }
     }
   } else {
-    HeapSortPairs(this, smis);
+    HeapSortPairs(this, numbers, len);
     return;
   }
 }
@@ -6758,7 +6753,7 @@
   }
 
   // Sort the arrays wrt. enumeration order.
-  iteration_order->SortPairs(enumeration_order);
+  iteration_order->SortPairs(enumeration_order, enumeration_order->length());
 
   // Overwrite the enumeration_order with the enumeration indices.
   for (int i = 0; i < length; i++) {
@@ -7010,6 +7005,7 @@
        if ((attr & filter) == 0) storage->set(index++, k);
      }
   }
+  storage->SortPairs(storage, index);
   ASSERT(storage->length() >= index);
 }
 
@@ -7031,7 +7027,7 @@
        }
      }
   }
-  storage->SortPairs(sort_array);
+  storage->SortPairs(sort_array, sort_array->length());
   ASSERT(storage->length() >= index);
 }
 
@@ -7176,6 +7172,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 // Check if there is a break point at this code position.
 bool DebugInfo::HasBreakPoint(int code_position) {
   // Get the break point info object for this code position.
@@ -7419,6 +7416,6 @@
   // Multiple break points.
   return FixedArray::cast(break_point_objects())->length();
 }
-
+#endif
 
 } }  // namespace v8::internal
diff --git a/src/objects.h b/src/objects.h
index ade282b..db3c449 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -389,7 +389,7 @@
 // Note that for subtle reasons related to the ordering or numerical values of
 // type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
 // manually.
-#define STRUCT_LIST(V)                                                    \
+#define STRUCT_LIST_ALL(V)                                                \
   V(ACCESSOR_INFO, AccessorInfo, accessor_info)                           \
   V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info)                \
   V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info)                  \
@@ -398,10 +398,19 @@
   V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info)       \
   V(SIGNATURE_INFO, SignatureInfo, signature_info)                        \
   V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info)                   \
-  V(DEBUG_INFO, DebugInfo, debug_info)                                    \
-  V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)                   \
   V(SCRIPT, Script, script)
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
+#define STRUCT_LIST_DEBUGGER(V)                                           \
+  V(DEBUG_INFO, DebugInfo, debug_info)                                    \
+  V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
+#else
+#define STRUCT_LIST_DEBUGGER(V)
+#endif
+
+#define STRUCT_LIST(V)                                                    \
+  STRUCT_LIST_ALL(V)                                                      \
+  STRUCT_LIST_DEBUGGER(V)
 
 // We use the full 8 bits of the instance_type field to encode heap object
 // instance types.  The high-order bit (bit 7) is set if the object is not a
@@ -1585,11 +1594,15 @@
   bool IsEqualTo(FixedArray* other);
 #endif
 
-  // Swap two elements.
-  void Swap(int i, int j);
+  // Swap two elements in a pair of arrays.  If this array and the
+  // numbers array are the same object, the elements are only swapped
+  // once.
+  void SwapPairs(FixedArray* numbers, int i, int j);
 
-  // Sort this array and the smis as pairs wrt. the smis.
-  void SortPairs(FixedArray* smis);
+  // Sort prefix of this array and the numbers array as pairs wrt. the
+  // numbers.  If the numbers array and the this array are the same
+  // object, the prefix of this array is sorted.
+  void SortPairs(FixedArray* numbers, uint32_t len);
 
  protected:
   // Set operation on FixedArray without using write barriers.
@@ -2590,6 +2603,9 @@
   // extracted.
   DECL_ACCESSORS(column_offset, Smi)
 
+  // [data]: additional data associated with this script.
+  DECL_ACCESSORS(data, Object)
+
   // [wrapper]: the wrapper cache.
   DECL_ACCESSORS(wrapper, Proxy)
 
@@ -2610,7 +2626,8 @@
   static const int kNameOffset = kSourceOffset + kPointerSize;
   static const int kLineOffsetOffset = kNameOffset + kPointerSize;
   static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
-  static const int kWrapperOffset = kColumnOffsetOffset + kPointerSize;
+  static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
+  static const int kWrapperOffset = kDataOffset + kPointerSize;
   static const int kTypeOffset = kWrapperOffset + kPointerSize;
   static const int kLineEndsOffset = kTypeOffset + kPointerSize;
   static const int kIdOffset = kLineEndsOffset + kPointerSize;
@@ -4147,6 +4164,7 @@
 };
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 // The DebugInfo class holds additional information for a function being
 // debugged.
 class DebugInfo: public Struct {
@@ -4252,6 +4270,7 @@
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
 };
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 
 #undef DECL_BOOLEAN_ACCESSORS
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 9209990..1e71704 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -262,7 +262,8 @@
 }
 
 
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
+  int frames_size = frames.length();
   void** addresses = NewArray<void*>(frames_size);
 
   int frames_count = backtrace(addresses, frames_size);
@@ -502,27 +503,24 @@
 
 bool FreeBSDSemaphore::Wait(int timeout) {
   const long kOneSecondMicros = 1000000;  // NOLINT
-  const long kOneSecondNanos = 1000000000;  // NOLINT
 
   // Split timeout into second and nanosecond parts.
-  long nanos = (timeout % kOneSecondMicros) * 1000;  // NOLINT
-  time_t secs = timeout / kOneSecondMicros;
+  struct timeval delta;
+  delta.tv_usec = timeout % kOneSecondMicros;
+  delta.tv_sec = timeout / kOneSecondMicros;
 
-  // Get the current real time clock.
-  struct timespec ts;
-  if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+  struct timeval current_time;
+  // Get the current time.
+  if (gettimeofday(&current_time, NULL) == -1) {
     return false;
   }
 
-  // Calculate realtime for end of timeout.
-  ts.tv_nsec += nanos;
-  if (ts.tv_nsec >= kOneSecondNanos) {
-    ts.tv_nsec -= kOneSecondNanos;
-    ts.tv_nsec++;
-  }
-  ts.tv_sec += secs;
+  // Calculate time for end of timeout.
+  struct timeval end_time;
+  timeradd(&current_time, &delta, &end_time);
 
-  // Wait for semaphore signalled or timeout.
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC(&end_time, &ts);
   while (true) {
     int result = sem_timedwait(&sem_, &ts);
     if (result == 0) return true;  // Successfully got semaphore.
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index f9a5dea..9f5b9ac 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -262,9 +262,10 @@
 }
 
 
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
   // backtrace is a glibc extension.
 #ifdef __GLIBC__
+  int frames_size = frames.length();
   void** addresses = NewArray<void*>(frames_size);
 
   int frames_count = backtrace(addresses, frames_size);
@@ -506,28 +507,34 @@
 }
 
 
+#ifndef TIMEVAL_TO_TIMESPEC
+#define TIMEVAL_TO_TIMESPEC(tv, ts) do {                            \
+    (ts)->tv_sec = (tv)->tv_sec;                                    \
+    (ts)->tv_nsec = (tv)->tv_usec * 1000;                           \
+} while (false)
+#endif
+
+
 bool LinuxSemaphore::Wait(int timeout) {
   const long kOneSecondMicros = 1000000;  // NOLINT
-  const long kOneSecondNanos = 1000000000;  // NOLINT
 
   // Split timeout into second and nanosecond parts.
-  long nanos = (timeout % kOneSecondMicros) * 1000;  // NOLINT
-  time_t secs = timeout / kOneSecondMicros;
+  struct timeval delta;
+  delta.tv_usec = timeout % kOneSecondMicros;
+  delta.tv_sec = timeout / kOneSecondMicros;
 
-  // Get the current realtime clock.
-  struct timespec ts;
-  if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+  struct timeval current_time;
+  // Get the current time.
+  if (gettimeofday(&current_time, NULL) == -1) {
     return false;
   }
 
-  // Calculate real time for end of timeout.
-  ts.tv_nsec += nanos;
-  if (ts.tv_nsec >= kOneSecondNanos) {
-    ts.tv_nsec -= kOneSecondNanos;
-    ts.tv_nsec++;
-  }
-  ts.tv_sec += secs;
+  // Calculate time for end of timeout.
+  struct timeval end_time;
+  timeradd(&current_time, &delta, &end_time);
 
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC(&end_time, &ts);
   // Wait for semaphore signalled or timeout.
   while (true) {
     int result = sem_timedwait(&sem_, &ts);
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index b13122f..7951543 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -212,10 +212,11 @@
 }
 
 
-int OS::StackWalk(StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<StackFrame> frames) {
 #ifndef MAC_OS_X_VERSION_10_5
   return 0;
 #else
+  int frames_size = frames.length();
   void** addresses = NewArray<void*>(frames_size);
   int frames_count = backtrace(addresses, frames_size);
 
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
index 3a50b9d..42583f1 100644
--- a/src/platform-nullos.cc
+++ b/src/platform-nullos.cc
@@ -215,7 +215,7 @@
 }
 
 
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
   UNIMPLEMENTED();
   return 0;
 }
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 7177870..597a217 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1161,7 +1161,7 @@
 // it is triggered by the use of inline assembler.
 #pragma warning(push)
 #pragma warning(disable : 4748)
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
   BOOL ok;
 
   // Load the required functions from DLL's.
@@ -1201,6 +1201,7 @@
   int frames_count = 0;
 
   // Collect stack frames.
+  int frames_size = frames.length();
   while (frames_count < frames_size) {
     ok = _StackWalk64(
         IMAGE_FILE_MACHINE_I386,    // MachineType
@@ -1284,7 +1285,7 @@
 
 #else  // __MINGW32__
 void OS::LogSharedLibraryAddresses() { }
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) { return 0; }
+int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; }
 #endif  // __MINGW32__
 
 
diff --git a/src/platform.h b/src/platform.h
index db4f2fd..b70095b 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -207,7 +207,7 @@
     char text[kStackWalkMaxTextLen];
   };
 
-  static int StackWalk(StackFrame* frames, int frames_size);
+  static int StackWalk(Vector<StackFrame> frames);
 
   // Factory method for creating platform dependent Mutex.
   // Please use delete to reclaim the storage for the returned Mutex.
diff --git a/src/regexp-macro-assembler-ia32.cc b/src/regexp-macro-assembler-ia32.cc
index c2f76b4..8c92091 100644
--- a/src/regexp-macro-assembler-ia32.cc
+++ b/src/regexp-macro-assembler-ia32.cc
@@ -86,7 +86,7 @@
  *              byte* stack_area_top)
  */
 
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
 
 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
     Mode mode,
diff --git a/src/rewriter.cc b/src/rewriter.cc
index 6641f26..4e3676b 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -194,7 +194,7 @@
 
   if (node->name()->length() == 0) {
     // Anonymous function.
-    func_name_inferrer_.SetFuncToInfer(node);
+    func_name_inferrer_.AddFunction(node);
   }
 }
 
@@ -282,10 +282,7 @@
     case Token::ASSIGN:
       // No type can be infered from the general assignment.
 
-      if (node->value()->AsFunctionLiteral() != NULL ||
-          node->value()->AsObjectLiteral() != NULL) {
-        scoped_fni.Enter();
-      }
+      scoped_fni.Enter();
       break;
     case Token::ASSIGN_BIT_OR:
     case Token::ASSIGN_BIT_XOR:
diff --git a/src/runtime.cc b/src/runtime.cc
index ab25c9e..2b350a5 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2688,6 +2688,59 @@
 }
 
 
+Object* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object,
+                                        Handle<Object> key,
+                                        Handle<Object> value,
+                                        PropertyAttributes attr) {
+  HandleScope scope;
+
+  // Check if the given key is an array index.
+  uint32_t index;
+  if (Array::IndexFromObject(*key, &index)) {
+    ASSERT(attr == NONE);
+
+    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
+    // of a string using [] notation.  We need to support this too in
+    // JavaScript.
+    // In the case of a String object we just need to redirect the assignment to
+    // the underlying string if the index is in range.  Since the underlying
+    // string does nothing with the assignment then we can ignore such
+    // assignments.
+    if (js_object->IsStringObjectWithCharacterAt(index)) {
+      return *value;
+    }
+
+    return js_object->SetElement(index, *value);
+  }
+
+  if (key->IsString()) {
+    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
+      ASSERT(attr == NONE);
+      return js_object->SetElement(index, *value);
+    } else {
+      Handle<String> key_string = Handle<String>::cast(key);
+      key_string->TryFlattenIfNotFlat();
+      return js_object->IgnoreAttributesAndSetLocalProperty(*key_string,
+                                                            *value,
+                                                            attr);
+    }
+  }
+
+  // Call-back into JavaScript to convert the key to a string.
+  bool has_pending_exception = false;
+  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
+  Handle<String> name = Handle<String>::cast(converted);
+
+  if (name->AsArrayIndex(&index)) {
+    ASSERT(attr == NONE);
+    return js_object->SetElement(index, *value);
+  } else {
+    return js_object->IgnoreAttributesAndSetLocalProperty(*name, *value, attr);
+  }
+}
+
+
 static Object* Runtime_SetProperty(Arguments args) {
   NoHandleAllocation ha;
   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
@@ -3482,6 +3535,7 @@
   return Heap::nan_value();
 }
 
+
 static Object* Runtime_NumberAdd(Arguments args) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
@@ -4158,10 +4212,12 @@
     JSFunction* function = JSFunction::cast(constructor);
 
     // Handle stepping into constructors if step into is active.
+#ifdef ENABLE_DEBUGGER_SUPPORT
     if (Debug::StepInActive()) {
       HandleScope scope;
       Debug::HandleStepIn(Handle<JSFunction>(function), 0, true);
     }
+#endif
 
     if (function->has_initial_map() &&
         function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
@@ -4525,12 +4581,6 @@
 }
 
 
-static Object* Runtime_DebugBreak(Arguments args) {
-  ASSERT(args.length() == 0);
-  return Execution::DebugBreakHelper();
-}
-
-
 static Object* Runtime_StackGuard(Arguments args) {
   ASSERT(args.length() == 1);
 
@@ -4892,26 +4942,6 @@
 }
 
 
-static Object* Runtime_CompileScript(Arguments args) {
-  HandleScope scope;
-  ASSERT(args.length() == 4);
-
-  CONVERT_ARG_CHECKED(String, source, 0);
-  CONVERT_ARG_CHECKED(String, script, 1);
-  CONVERT_CHECKED(Smi, line_attrs, args[2]);
-  int line = line_attrs->value();
-  CONVERT_CHECKED(Smi, col_attrs, args[3]);
-  int col = col_attrs->value();
-  Handle<JSFunction> boilerplate =
-      Compiler::Compile(source, script, line, col, NULL, NULL);
-  if (boilerplate.is_null()) return Failure::Exception();
-  Handle<JSFunction> fun =
-      Factory::NewFunctionFromBoilerplate(boilerplate,
-                                          Handle<Context>(Top::context()));
-  return *fun;
-}
-
-
 static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
   // This utility adjusts the property attributes for newly created Function
   // object ("new Function(...)") by changing the map.
@@ -5316,6 +5346,13 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
+static Object* Runtime_DebugBreak(Arguments args) {
+  ASSERT(args.length() == 0);
+  return Execution::DebugBreakHelper();
+}
+
+
 // Helper functions for wrapping and unwrapping stack frame ids.
 static Smi* WrapFrameId(StackFrame::Id id) {
   ASSERT(IsAligned(OffsetFrom(id), 4));
@@ -5928,8 +5965,8 @@
   if (result->IsFailure()) return result;
 
   static const int kMaxCFramesSize = 200;
-  OS::StackFrame frames[kMaxCFramesSize];
-  int frames_count = OS::StackWalk(frames, kMaxCFramesSize);
+  ScopedVector<OS::StackFrame> frames(kMaxCFramesSize);
+  int frames_count = OS::StackWalk(frames);
   if (frames_count == OS::kStackWalkError) {
     return Heap::undefined_value();
   }
@@ -6796,6 +6833,22 @@
 }
 
 
+static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
+#ifdef DEBUG
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  // Get the function and make sure it is compiled.
+  CONVERT_ARG_CHECKED(JSFunction, func, 0);
+  if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
+    return Failure::Exception();
+  }
+  func->code()->PrintLn();
+#endif  // DEBUG
+  return Heap::undefined_value();
+}
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
+
 // Finds the script object from the script data. NOTE: This operation uses
 // heap traversal to find the function generated for the source position
 // for the requested break point. For lazily compiled functions several heap
@@ -6845,21 +6898,6 @@
 }
 
 
-static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
-#ifdef DEBUG
-  HandleScope scope;
-  ASSERT(args.length() == 1);
-  // Get the function and make sure it is compiled.
-  CONVERT_ARG_CHECKED(JSFunction, func, 0);
-  if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
-    return Failure::Exception();
-  }
-  func->code()->PrintLn();
-#endif  // DEBUG
-  return Heap::undefined_value();
-}
-
-
 static Object* Runtime_Abort(Arguments args) {
   ASSERT(args.length() == 2);
   OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
diff --git a/src/runtime.h b/src/runtime.h
index 657e5c5..6bd19f6 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -195,7 +195,6 @@
   \
   /* Globals */ \
   F(CompileString, 2) \
-  F(CompileScript, 4) \
   F(GlobalPrint, 1) \
   \
   /* Eval */ \
@@ -215,42 +214,6 @@
   F(DefineAccessor, -1 /* 4 or 5 */) \
   F(LookupAccessor, 3) \
   \
-  /* Debugging */ \
-  F(SetDebugEventListener, 2) \
-  F(Break, 0) \
-  F(DebugGetPropertyDetails, 2) \
-  F(DebugGetProperty, 2) \
-  F(DebugLocalPropertyNames, 1) \
-  F(DebugLocalElementNames, 1) \
-  F(DebugPropertyTypeFromDetails, 1) \
-  F(DebugPropertyAttributesFromDetails, 1) \
-  F(DebugPropertyIndexFromDetails, 1) \
-  F(DebugInterceptorInfo, 1) \
-  F(DebugNamedInterceptorPropertyNames, 1) \
-  F(DebugIndexedInterceptorElementNames, 1) \
-  F(DebugNamedInterceptorPropertyValue, 2) \
-  F(DebugIndexedInterceptorElementValue, 2) \
-  F(CheckExecutionState, 1) \
-  F(GetFrameCount, 1) \
-  F(GetFrameDetails, 2) \
-  F(GetCFrames, 1) \
-  F(GetThreadCount, 1) \
-  F(GetThreadDetails, 2) \
-  F(GetBreakLocations, 1) \
-  F(SetFunctionBreakPoint, 3) \
-  F(SetScriptBreakPoint, 3) \
-  F(ClearBreakPoint, 1) \
-  F(ChangeBreakOnException, 2) \
-  F(PrepareStep, 3) \
-  F(ClearStepping, 0) \
-  F(DebugEvaluate, 4) \
-  F(DebugEvaluateGlobal, 3) \
-  F(DebugGetLoadedScripts, 0) \
-  F(DebugReferencedBy, 3) \
-  F(DebugConstructedBy, 2) \
-  F(DebugGetPrototype, 1) \
-  F(SystemBreak, 0) \
-  \
   /* Literals */ \
   F(MaterializeRegExpLiteral, 4)\
   F(CreateArrayLiteralBoilerplate, 3) \
@@ -290,8 +253,6 @@
   F(DebugTrace, 0) \
   F(TraceEnter, 0) \
   F(TraceExit, 1) \
-  F(DebugBreak, 0) \
-  F(FunctionGetAssemblerCode, 1) \
   F(Abort, 2) \
   /* Logging */ \
   F(Log, 2) \
@@ -299,6 +260,48 @@
   /* Pseudo functions - handled as macros by parser */ \
   F(IS_VAR, 1)
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
+#define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F) \
+  /* Debugger support*/ \
+  F(DebugBreak, 0) \
+  F(SetDebugEventListener, 2) \
+  F(Break, 0) \
+  F(DebugGetPropertyDetails, 2) \
+  F(DebugGetProperty, 2) \
+  F(DebugLocalPropertyNames, 1) \
+  F(DebugLocalElementNames, 1) \
+  F(DebugPropertyTypeFromDetails, 1) \
+  F(DebugPropertyAttributesFromDetails, 1) \
+  F(DebugPropertyIndexFromDetails, 1) \
+  F(DebugInterceptorInfo, 1) \
+  F(DebugNamedInterceptorPropertyNames, 1) \
+  F(DebugIndexedInterceptorElementNames, 1) \
+  F(DebugNamedInterceptorPropertyValue, 2) \
+  F(DebugIndexedInterceptorElementValue, 2) \
+  F(CheckExecutionState, 1) \
+  F(GetFrameCount, 1) \
+  F(GetFrameDetails, 2) \
+  F(GetCFrames, 1) \
+  F(GetThreadCount, 1) \
+  F(GetThreadDetails, 2) \
+  F(GetBreakLocations, 1) \
+  F(SetFunctionBreakPoint, 3) \
+  F(SetScriptBreakPoint, 3) \
+  F(ClearBreakPoint, 1) \
+  F(ChangeBreakOnException, 2) \
+  F(PrepareStep, 3) \
+  F(ClearStepping, 0) \
+  F(DebugEvaluate, 4) \
+  F(DebugEvaluateGlobal, 3) \
+  F(DebugGetLoadedScripts, 0) \
+  F(DebugReferencedBy, 3) \
+  F(DebugConstructedBy, 2) \
+  F(DebugGetPrototype, 1) \
+  F(SystemBreak, 0) \
+  F(FunctionGetAssemblerCode, 1)
+#else
+#define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
+#endif
 
 #ifdef DEBUG
 #define RUNTIME_FUNCTION_LIST_DEBUG(F) \
@@ -316,7 +319,8 @@
 
 #define RUNTIME_FUNCTION_LIST(F) \
   RUNTIME_FUNCTION_LIST_ALWAYS(F) \
-  RUNTIME_FUNCTION_LIST_DEBUG(F)
+  RUNTIME_FUNCTION_LIST_DEBUG(F) \
+  RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
 
 // ----------------------------------------------------------------------------
 // Runtime provides access to all C++ runtime functions.
@@ -369,6 +373,11 @@
                                    Handle<Object> value,
                                    PropertyAttributes attr);
 
+  static Object* ForceSetObjectProperty(Handle<JSObject> object,
+                                        Handle<Object> key,
+                                        Handle<Object> value,
+                                        PropertyAttributes attr);
+
   static Object* GetObjectProperty(Handle<Object> object, Handle<Object> key);
 
   // This function is used in FunctionNameUsing* tests.
diff --git a/src/serialize.cc b/src/serialize.cc
index 9a2be23..e15c003 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -548,6 +548,7 @@
     AddFromId(ref_table[i].type, ref_table[i].id, ref_table[i].name);
   }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Debug addresses
   Add(Debug_Address(Debug::k_after_break_target_address).address(),
       DEBUG_ADDRESS,
@@ -567,6 +568,7 @@
         Debug::k_register_address << kDebugIdShift | i,
         name.start());
   }
+#endif
 
   // Stat counters
   struct StatsRefTableEntry {
@@ -659,10 +661,6 @@
       UNCLASSIFIED,
       4,
       "RegExpStack::limit_address()");
-  Add(ExternalReference::debug_break().address(),
-      UNCLASSIFIED,
-      5,
-      "Debug::Break()");
   Add(ExternalReference::new_space_start().address(),
       UNCLASSIFIED,
       6,
@@ -679,10 +677,28 @@
       UNCLASSIFIED,
       9,
       "Heap::NewSpaceAllocationTopAddress()");
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  Add(ExternalReference::debug_break().address(),
+      UNCLASSIFIED,
+      5,
+      "Debug::Break()");
   Add(ExternalReference::debug_step_in_fp_address().address(),
       UNCLASSIFIED,
       10,
       "Debug::step_in_fp_addr()");
+  Add(ExternalReference::double_fp_operation(Token::ADD).address(),
+      UNCLASSIFIED,
+      11,
+      "add_two_doubles");
+  Add(ExternalReference::double_fp_operation(Token::SUB).address(),
+      UNCLASSIFIED,
+      12,
+      "sub_two_doubles");
+  Add(ExternalReference::double_fp_operation(Token::MUL).address(),
+      UNCLASSIFIED,
+      13,
+      "mul_two_doubles");
+#endif
 }
 
 
diff --git a/src/simulator-arm.cc b/src/simulator-arm.cc
index 5a61107..7d96b3a 100644
--- a/src/simulator-arm.cc
+++ b/src/simulator-arm.cc
@@ -90,12 +90,44 @@
 }
 
 
+
+#ifdef GENERATED_CODE_COVERAGE
+static FILE* coverage_log = NULL;
+
+
+static void InitializeCoverage() {
+  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
+  if (file_name != NULL) {
+    coverage_log = fopen(file_name, "aw+");
+  }
+}
+
+
+void Debugger::Stop(Instr* instr) {
+  char* str = reinterpret_cast<char*>(instr->InstructionBits() & 0x0fffffff);
+  if (strlen(str) > 0) {
+    if (coverage_log != NULL) {
+      fprintf(coverage_log, "%s\n", str);
+      fflush(coverage_log);
+    }
+    instr->SetInstructionBits(0xe1a00000);  // Overwrite with nop.
+  }
+  sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
+}
+
+#else  // ndef GENERATED_CODE_COVERAGE
+
+static void InitializeCoverage() {
+}
+
+
 void Debugger::Stop(Instr* instr) {
   const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);
   PrintF("Simulator hit %s\n", str);
   sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
   Debug();
 }
+#endif
 
 
 static const char* reg_names[] = {  "r0",  "r1",  "r2",  "r3",
@@ -375,6 +407,7 @@
   // access violation if the simulator ever tries to execute it.
   registers_[pc] = bad_lr;
   registers_[lr] = bad_lr;
+  InitializeCoverage();
 }
 
 
@@ -427,6 +460,37 @@
 }
 
 
+// For use in calls that take two double values, constructed from r0, r1, r2
+// and r3.
+void Simulator::GetFpArgs(double* x, double* y) {
+  // We use a char buffer to get around the strict-aliasing rules which
+  // otherwise allow the compiler to optimize away the copy.
+  char buffer[2 * sizeof(registers_[0])];
+  // Registers 0 and 1 -> x.
+  memcpy(buffer, registers_, sizeof(buffer));
+  memcpy(x, buffer, sizeof(buffer));
+  // Registers 2 and 3 -> y.
+  memcpy(buffer, registers_ + 2, sizeof(buffer));
+  memcpy(y, buffer, sizeof(buffer));
+}
+
+
+void Simulator::SetFpResult(const double& result) {
+  char buffer[2 * sizeof(registers_[0])];
+  memcpy(buffer, &result, sizeof(buffer));
+  // result -> registers 0 and 1.
+  memcpy(registers_, buffer, sizeof(buffer));
+}
+
+
+void Simulator::TrashCallerSaveRegisters() {
+  // We don't trash the registers with the return value.
+  registers_[2] = 0x50Bad4U;
+  registers_[3] = 0x50Bad4U;
+  registers_[12] = 0x50Bad4U;
+}
+
+
 // The ARM cannot do unaligned reads and writes.  On some ARM platforms an
 // interrupt is caused.  On others it does a funky rotation thing.  For now we
 // simply disallow unaligned reads, but at some point we may want to move to
@@ -862,7 +926,8 @@
 // Software interrupt instructions are used by the simulator to call into the
 // C-based V8 runtime.
 void Simulator::SoftwareInterrupt(Instr* instr) {
-  switch (instr->SwiField()) {
+  int swi = instr->SwiField();
+  switch (swi) {
     case call_rt_r5: {
       SimulatorRuntimeCall target =
           reinterpret_cast<SimulatorRuntimeCall>(get_register(r5));
@@ -894,6 +959,30 @@
       dbg.Debug();
       break;
     }
+    {
+      double x, y, z;
+    case simulator_fp_add:
+      GetFpArgs(&x, &y);
+      z = x + y;
+      SetFpResult(z);
+      TrashCallerSaveRegisters();
+      set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+      break;
+    case simulator_fp_sub:
+      GetFpArgs(&x, &y);
+      z = x - y;
+      SetFpResult(z);
+      TrashCallerSaveRegisters();
+      set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+      break;
+    case simulator_fp_mul:
+      GetFpArgs(&x, &y);
+      z = x * y;
+      SetFpResult(z);
+      TrashCallerSaveRegisters();
+      set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+      break;
+    }
     default: {
       UNREACHABLE();
       break;
diff --git a/src/simulator-arm.h b/src/simulator-arm.h
index 4f3c53d..5553ab2 100644
--- a/src/simulator-arm.h
+++ b/src/simulator-arm.h
@@ -174,6 +174,12 @@
   // Executes one instruction.
   void InstructionDecode(Instr* instr);
 
+  // For use in calls that take two double values, constructed from r0, r1, r2
+  // and r3.
+  void GetFpArgs(double* x, double* y);
+  void SetFpResult(const double& result);
+  void TrashCallerSaveRegisters();
+
   // architecture state
   int32_t registers_[16];
   bool n_flag_;
diff --git a/src/string-stream.cc b/src/string-stream.cc
index f311e20..2e0912f 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -57,19 +57,26 @@
 
 
 bool StringStream::Put(char c) {
-  if (space() == 0) return false;
-  if (length_ >= capacity_ - 1) {
+  if (full()) return false;
+  ASSERT(length_ < capacity_);
+  // Since the trailing '\0' is not accounted for in length_ fullness is
+  // indicated by a difference of 1 between length_ and capacity_. Thus when
+  // reaching a difference of 2 we need to grow the buffer.
+  if (length_ == capacity_ - 2) {
     unsigned new_capacity = capacity_;
     char* new_buffer = allocator_->grow(&new_capacity);
     if (new_capacity > capacity_) {
       capacity_ = new_capacity;
       buffer_ = new_buffer;
     } else {
-      // Indicate truncation with dots.
-      memset(cursor(), '.', space());
-      length_ = capacity_;
-      buffer_[length_ - 2] = '\n';
-      buffer_[length_ - 1] = '\0';
+      // Reached the end of the available buffer.
+      ASSERT(capacity_ >= 5);
+      length_ = capacity_ - 1;  // Indicate fullness of the stream.
+      buffer_[length_ - 4] = '.';
+      buffer_[length_ - 3] = '.';
+      buffer_[length_ - 2] = '.';
+      buffer_[length_ - 1] = '\n';
+      buffer_[length_] = '\0';
       return false;
     }
   }
@@ -95,8 +102,7 @@
 
 void StringStream::Add(Vector<const char> format, Vector<FmtElm> elms) {
   // If we already ran out of space then return immediately.
-  if (space() == 0)
-    return;
+  if (full()) return;
   int offset = 0;
   int elm = 0;
   while (offset < format.length()) {
@@ -564,12 +570,10 @@
 }
 
 
+// Only grow once to the maximum allowable size.
 char* NoAllocationStringAllocator::grow(unsigned* bytes) {
-  unsigned new_bytes = *bytes * 2;
-  if (new_bytes > size_) {
-    new_bytes = size_;
-  }
-  *bytes = new_bytes;
+  ASSERT(size_ >= *bytes);
+  *bytes = size_;
   return space_;
 }
 
diff --git a/src/string-stream.h b/src/string-stream.h
index 37ae93e..901f376 100644
--- a/src/string-stream.h
+++ b/src/string-stream.h
@@ -162,8 +162,8 @@
   unsigned length_;  // does not include terminating 0-character
   char* buffer_;
 
+  bool full() const { return (capacity_ - length_) == 1; }
   int space() const { return capacity_ - length_; }
-  char* cursor() const { return buffer_ + length_; }
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
 };
diff --git a/src/stub-cache-arm.cc b/src/stub-cache-arm.cc
index 211b643..56afa02 100644
--- a/src/stub-cache-arm.cc
+++ b/src/stub-cache-arm.cc
@@ -33,7 +33,7 @@
 
 namespace v8 { namespace internal {
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 static void ProbeTable(MacroAssembler* masm,
@@ -183,7 +183,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
   GenerateFastPropertyLoad(masm, r0, reg, holder, index);
   __ Ret();
 }
@@ -203,7 +203,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
 
   // Return the constant value.
   __ mov(r0, Operand(Handle<Object>(value)));
@@ -226,7 +226,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
 
   // Push the arguments on the JS stack of the caller.
   __ push(receiver);  // receiver
@@ -256,7 +256,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
 
   // Push the arguments on the JS stack of the caller.
   __ push(receiver);  // receiver
@@ -456,8 +456,7 @@
 
 
 #undef __
-
-#define __ masm()->
+#define __ ACCESS_MASM(masm())
 
 
 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
@@ -511,7 +510,7 @@
 
   // Do the right check and compute the holder register.
   Register reg =
-      __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
+      masm()->CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
   GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
 
   // Check that the function really is a function.
diff --git a/src/stub-cache-ia32.cc b/src/stub-cache-ia32.cc
index 19777e6..bdfc3d6 100644
--- a/src/stub-cache-ia32.cc
+++ b/src/stub-cache-ia32.cc
@@ -33,7 +33,7 @@
 
 namespace v8 { namespace internal {
 
-#define __ masm->
+#define __ ACCESS_MASM(masm)
 
 
 static void ProbeTable(MacroAssembler* masm,
@@ -256,7 +256,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
 
   // Get the value from the properties.
   GenerateFastPropertyLoad(masm, eax, reg, holder, index);
@@ -279,7 +279,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
 
   // Push the arguments on the JS stack of the caller.
   __ pop(scratch2);  // remove return address
@@ -310,7 +310,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
 
   // Return the constant value.
   __ mov(eax, Handle<Object>(value));
@@ -332,7 +332,7 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+      masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
 
   // Push the arguments on the JS stack of the caller.
   __ pop(scratch2);  // remove return address
@@ -440,7 +440,7 @@
 
 #undef __
 
-#define __ masm()->
+#define __ ACCESS_MASM(masm())
 
 
 // TODO(1241006): Avoid having lazy compile stubs specialized by the
@@ -485,7 +485,7 @@
 
   // Do the right check and compute the holder register.
   Register reg =
-      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+      masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
 
   GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
 
@@ -656,7 +656,7 @@
 
   // Check that maps have not changed and compute the holder register.
   Register reg =
-      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+      masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
 
   // Enter an internal frame.
   __ EnterInternalFrame();
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 35e3d42..6811fd2 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -594,6 +594,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 Object* StubCache::ComputeCallDebugBreak(int argc) {
   Code::Flags flags =
       Code::ComputeFlags(Code::CALL_IC, DEBUG_BREAK, NORMAL, argc);
@@ -612,6 +613,7 @@
   StubCompiler compiler;
   return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
 }
+#endif
 
 
 Object* StubCache::ComputeLazyCompile(int argc) {
@@ -836,6 +838,7 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
   HandleScope scope;
   Debug::GenerateCallICDebugBreak(masm());
@@ -864,6 +867,7 @@
   }
   return result;
 }
+#endif
 
 
 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) {
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 05845e5..824f4ff 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -157,8 +157,10 @@
   // Finds the Code object stored in the Heap::non_monomorphic_cache().
   static Code* FindCallInitialize(int argc);
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   static Object* ComputeCallDebugBreak(int argc);
   static Object* ComputeCallDebugPrepareStepIn(int argc);
+#endif
 
   static Object* ComputeLazyCompile(int argc);
 
@@ -288,8 +290,10 @@
   Object* CompileCallNormal(Code::Flags flags);
   Object* CompileCallMegamorphic(Code::Flags flags);
   Object* CompileCallMiss(Code::Flags flags);
+#ifdef ENABLE_DEBUGGER_SUPPORT
   Object* CompileCallDebugBreak(Code::Flags flags);
   Object* CompileCallDebugPrepareStepIn(Code::Flags flags);
+#endif
   Object* CompileLazyCompile(Code::Flags flags);
 
   // Static functions for generating parts of stubs.
diff --git a/src/top.cc b/src/top.cc
index a99e9ff..96f98a5 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -116,15 +116,15 @@
   // When the thread starts running it will allocate a fixed number of bytes
   // on the stack and publish the location of this memory for others to use.
   void Run() {
-    EmbeddedVector<char, 32 * 1024> local_buffer;
+    EmbeddedVector<char, 15 * 1024> local_buffer;
 
     // Initialize the buffer with a known good value.
     OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
                 local_buffer.length());
 
     // Publish the local buffer and signal its availability.
-    data_ = &local_buffer[0];
-    length_ = sizeof(local_buffer);
+    data_ = local_buffer.start();
+    length_ = local_buffer.length();
     data_ready_semaphore_->Signal();
 
     while (keep_running_) {
@@ -728,8 +728,10 @@
   bool should_return_exception = ShouldReportException(&is_caught_externally);
   bool report_exception = !is_out_of_memory && should_return_exception;
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Notify debugger of exception.
   Debugger::OnException(exception_handle, report_exception);
+#endif
 
   // Generate the message.
   Handle<Object> message_obj;
diff --git a/src/utils.h b/src/utils.h
index f62b47a..e008c85 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -406,6 +406,16 @@
 };
 
 
+template <typename T>
+class ScopedVector : public Vector<T> {
+ public:
+  explicit ScopedVector(int length) : Vector<T>(NewArray<T>(length), length) { }
+  ~ScopedVector() {
+    DeleteArray(this->start());
+  }
+};
+
+
 inline Vector<const char> CStrVector(const char* data) {
   return Vector<const char>(data, strlen(data));
 }
diff --git a/src/v8.cc b/src/v8.cc
index 9158b52..fbe3d5d 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -72,7 +72,9 @@
     v8::Locker::StartPreemption(100);
   }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   Debug::Setup(create_heap_objects);
+#endif
   StubCache::Initialize(create_heap_objects);
 
   // If we are deserializing, read the state into the now-empty heap.
@@ -111,7 +113,9 @@
   Heap::TearDown();
   Logger::TearDown();
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   Debugger::TearDown();
+#endif
 
   has_been_setup_ = false;
   has_been_disposed_ = true;
diff --git a/src/v8.h b/src/v8.h
index 4cf0b70..4ced0d2 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -51,6 +51,11 @@
 #error both DEBUG and NDEBUG are set
 #endif
 
+// Enable debugger support by default, unless it is in ANDROID
+#if !defined(ENABLE_DEBUGGER_SUPPORT) && !defined(ANDROID)
+#define ENABLE_DEBUGGER_SUPPORT
+#endif
+
 // Basic includes
 #include "../include/v8.h"
 #include "globals.h"
diff --git a/src/v8threads.cc b/src/v8threads.cc
index e8f6f9b..2439476 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -144,7 +144,9 @@
   char* from = state->data();
   from = HandleScopeImplementer::RestoreThread(from);
   from = Top::RestoreThread(from);
+#ifdef ENABLE_DEBUGGER_SUPPORT
   from = Debug::RestoreDebug(from);
+#endif
   from = StackGuard::RestoreStackGuard(from);
   from = RegExpStack::RestoreStack(from);
   from = Bootstrapper::RestoreState(from);
@@ -172,7 +174,9 @@
 static int ArchiveSpacePerThread() {
   return HandleScopeImplementer::ArchiveSpacePerThread() +
                             Top::ArchiveSpacePerThread() +
+#ifdef ENABLE_DEBUGGER_SUPPORT
                           Debug::ArchiveSpacePerThread() +
+#endif
                      StackGuard::ArchiveSpacePerThread() +
                     RegExpStack::ArchiveSpacePerThread() +
                    Bootstrapper::ArchiveSpacePerThread();
@@ -259,7 +263,9 @@
   char* to = state->data();
   to = HandleScopeImplementer::ArchiveThread(to);
   to = Top::ArchiveThread(to);
+#ifdef ENABLE_DEBUGGER_SUPPORT
   to = Debug::ArchiveDebug(to);
+#endif
   to = StackGuard::ArchiveStackGuard(to);
   to = RegExpStack::ArchiveStack(to);
   to = Bootstrapper::ArchiveState(to);
diff --git a/src/virtual-frame-arm.cc b/src/virtual-frame-arm.cc
index baf0814..b794d8b 100644
--- a/src/virtual-frame-arm.cc
+++ b/src/virtual-frame-arm.cc
@@ -36,7 +36,8 @@
 // -------------------------------------------------------------------------
 // VirtualFrame implementation.
 
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
+
 
 // On entry to a function, the virtual frame already contains the
 // receiver and the parameters.  All initial frame elements are in
diff --git a/src/virtual-frame-ia32.cc b/src/virtual-frame-ia32.cc
index eb3befc..3647ca5 100644
--- a/src/virtual-frame-ia32.cc
+++ b/src/virtual-frame-ia32.cc
@@ -33,7 +33,7 @@
 
 namespace v8 { namespace internal {
 
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
 
 // -------------------------------------------------------------------------
 // VirtualFrame implementation.
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 9a3f819..e56452f 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -27,9 +27,6 @@
 
 prefix cctest
 
-# BUG(96): Fix this flaky test.
-test-debug/ThreadedDebugging: PASS || FAIL
-
 # BUG(281): This test fails on some Linuxes.
 test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
 
@@ -37,14 +34,19 @@
 
 test-debug: SKIP
 
+# Bug http://code.google.com/p/v8/issues/detail?id=323
+test-api/ApplyInterruption: SKIP
+
 # BUG(113): Test seems flaky on ARM.
 test-spaces/LargeObjectSpace: PASS || FAIL
 
 # BUG(240): Test seems flaky on ARM.
 test-api/RegExpInterruption: SKIP
 
+[ $simulator == arm ]
+
 # BUG(271): During exception propagation, we compare pointers into the
 # stack.  These tests fail on the ARM simulator because the C++ and
 # the JavaScript stacks are separate.
-test-api/ExceptionOrder: PASS || FAIL
-test-api/TryCatchInTryFinally: PASS || FAIL
+test-api/ExceptionOrder: FAIL
+test-api/TryCatchInTryFinally: FAIL
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 23e57d5..b7a5cb6 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1394,6 +1394,7 @@
                           v8::Handle<Value> data) {
   CHECK_EQ(5.76, data->NumberValue());
   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
   message_received = true;
 }
 
@@ -1406,7 +1407,10 @@
   LocalContext context;
   v8::ScriptOrigin origin =
       v8::ScriptOrigin(v8_str("6.75"));
-  Script::Compile(v8_str("throw 'error'"), &origin)->Run();
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->SetData(v8_str("7.56"));
+  script->Run();
   CHECK(message_received);
   // clear out the message listener
   v8::V8::RemoveMessageListeners(check_message);
@@ -2925,7 +2929,19 @@
 
 static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
   ApiTestFuzzer::Fuzz();
-  return v8::Undefined();
+  if (name->Equals(v8_str("foo")) ||
+      name->Equals(v8_str("bar")) ||
+      name->Equals(v8_str("baz"))) {
+    return v8::Undefined();
+  }
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> IndexedGetK(uint32_t index, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  if (index == 0 || index == 1) return v8::Undefined();
+  return v8::Handle<Value>();
 }
 
 
@@ -2942,8 +2958,8 @@
 static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
   ApiTestFuzzer::Fuzz();
   v8::Handle<v8::Array> result = v8::Array::New(2);
-  result->Set(v8::Integer::New(0), v8_str("hat"));
-  result->Set(v8::Integer::New(1), v8_str("gyt"));
+  result->Set(v8::Integer::New(0), v8_str("0"));
+  result->Set(v8::Integer::New(1), v8_str("1"));
   return result;
 }
 
@@ -2952,21 +2968,56 @@
   v8::HandleScope scope;
   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
-  obj->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL, IndexedEnum);
+  obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
   LocalContext context;
   context->Global()->Set(v8_str("k"), obj->NewInstance());
   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
+    "k[10] = 0;"
+    "k.a = 0;"
+    "k[5] = 0;"
+    "k.b = 0;"
+    "k[4294967295] = 0;"
+    "k.c = 0;"
+    "k[4294967296] = 0;"
+    "k.d = 0;"
+    "k[140000] = 0;"
+    "k.e = 0;"
+    "k[30000000000] = 0;"
+    "k.f = 0;"
     "var result = [];"
     "for (var prop in k) {"
     "  result.push(prop);"
     "}"
     "result"));
-  CHECK_EQ(5, result->Length());
-  CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(0)));
-  CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(1)));
-  CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(2)));
-  CHECK_EQ(v8_str("hat"), result->Get(v8::Integer::New(3)));
-  CHECK_EQ(v8_str("gyt"), result->Get(v8::Integer::New(4)));
+  // Check that we get all the property names returned including the
+  // ones from the enumerators in the right order: indexed properties
+  // in numerical order, indexed interceptor properties, named
+  // properties in insertion order, named interceptor properties.
+  // This order is not mandated by the spec, so this test is just
+  // documenting our behavior.
+  CHECK_EQ(17, result->Length());
+  // Indexed properties in numerical order.
+  CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
+  CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
+  CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
+  CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
+  // Indexed interceptor properties in the order they are returned
+  // from the enumerator interceptor.
+  CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
+  CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
+  // Named properties in insertion order.
+  CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
+  CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
+  CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
+  CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
+  CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
+  CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
+  CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
+  CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
+  // Named interceptor properties.
+  CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
+  CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
+  CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
 }
 
 
@@ -5963,6 +6014,112 @@
 }
 
 
+class ApplyInterruptTest {
+ public:
+  ApplyInterruptTest() : block_(NULL) {}
+  ~ApplyInterruptTest() { delete block_; }
+  void RunTest() {
+    block_ = i::OS::CreateSemaphore(0);
+    gc_count_ = 0;
+    gc_during_apply_ = 0;
+    apply_success_ = false;
+    gc_success_ = false;
+    GCThread gc_thread(this);
+    gc_thread.Start();
+    v8::Locker::StartPreemption(1);
+
+    LongRunningApply();
+    {
+      v8::Unlocker unlock;
+      gc_thread.Join();
+    }
+    v8::Locker::StopPreemption();
+    CHECK(apply_success_);
+    CHECK(gc_success_);
+  }
+ private:
+  // Number of garbage collections required.
+  static const int kRequiredGCs = 2;
+
+  class GCThread : public i::Thread {
+   public:
+    explicit GCThread(ApplyInterruptTest* test)
+        : test_(test) {}
+    virtual void Run() {
+      test_->CollectGarbage();
+    }
+   private:
+     ApplyInterruptTest* test_;
+  };
+
+  void CollectGarbage() {
+    block_->Wait();
+    while (gc_during_apply_ < kRequiredGCs) {
+      {
+        v8::Locker lock;
+        i::Heap::CollectAllGarbage();
+        gc_count_++;
+      }
+      i::OS::Sleep(1);
+    }
+    gc_success_ = true;
+  }
+
+  void LongRunningApply() {
+    block_->Signal();
+    int rounds = 0;
+    while (gc_during_apply_ < kRequiredGCs) {
+      int gc_before = gc_count_;
+      {
+        const char* c_source =
+            "function do_very_little(bar) {"
+            "  this.foo = bar;"
+            "}"
+            "for (var i = 0; i < 100000; i++) {"
+            "  do_very_little.apply(this, ['bar']);"
+            "}";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+      }
+      int gc_after = gc_count_;
+      gc_during_apply_ += gc_after - gc_before;
+      rounds++;
+    }
+    apply_success_ = true;
+  }
+
+  i::Semaphore* block_;
+  int gc_count_;
+  int gc_during_apply_;
+  bool apply_success_;
+  bool gc_success_;
+};
+
+
+// Test that nothing bad happens if we get a preemption just when we were
+// about to do an apply().
+TEST(ApplyInterruption) {
+  v8::Locker lock;
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  // Should complete without problems.
+  ApplyInterruptTest().RunTest();
+
+  local_env->Exit();
+}
+
+
 // Verify that we can clone an object
 TEST(ObjectClone) {
   v8::HandleScope scope;
@@ -6187,3 +6344,118 @@
   res = CompileRun("function f() { with (this) { y = 42 }; return y; }; f()");
   CHECK_EQ(v8::Integer::New(42), res);
 }
+
+static int force_set_set_count = 0;
+static int force_set_get_count = 0;
+bool pass_on_get = false;
+
+static v8::Handle<v8::Value> ForceSetGetter(v8::Local<v8::String> name,
+                                            const v8::AccessorInfo& info) {
+  force_set_get_count++;
+  if (pass_on_get) {
+    return v8::Handle<v8::Value>();
+  } else {
+    return v8::Int32::New(3);
+  }
+}
+
+static void ForceSetSetter(v8::Local<v8::String> name,
+                           v8::Local<v8::Value> value,
+                           const v8::AccessorInfo& info) {
+  force_set_set_count++;
+}
+
+static v8::Handle<v8::Value> ForceSetInterceptSetter(
+    v8::Local<v8::String> name,
+    v8::Local<v8::Value> value,
+    const v8::AccessorInfo& info) {
+  force_set_set_count++;
+  return v8::Undefined();
+}
+
+TEST(ForceSet) {
+  force_set_get_count = 0;
+  force_set_set_count = 0;
+  pass_on_get = false;
+
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  v8::Handle<v8::String> access_property = v8::String::New("a");
+  templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
+
+  // Ordinary properties
+  v8::Handle<v8::String> simple_property = v8::String::New("p");
+  global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
+  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+  // This should fail because the property is read-only
+  global->Set(simple_property, v8::Int32::New(5));
+  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+  // This should succeed even though the property is read-only
+  global->ForceSet(simple_property, v8::Int32::New(6));
+  CHECK_EQ(6, global->Get(simple_property)->Int32Value());
+
+  // Accessors
+  CHECK_EQ(0, force_set_set_count);
+  CHECK_EQ(0, force_set_get_count);
+  CHECK_EQ(3, global->Get(access_property)->Int32Value());
+  // CHECK_EQ the property shouldn't override it, just call the setter
+  // which in this case does nothing.
+  global->Set(access_property, v8::Int32::New(7));
+  CHECK_EQ(3, global->Get(access_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+  // Forcing the property to be set should override the accessor without
+  // calling it
+  global->ForceSet(access_property, v8::Int32::New(8));
+  CHECK_EQ(8, global->Get(access_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+}
+
+TEST(ForceSetWithInterceptor) {
+  force_set_get_count = 0;
+  force_set_set_count = 0;
+  pass_on_get = false;
+
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
+
+  v8::Handle<v8::String> some_property = v8::String::New("a");
+  CHECK_EQ(0, force_set_set_count);
+  CHECK_EQ(0, force_set_get_count);
+  CHECK_EQ(3, global->Get(some_property)->Int32Value());
+  // Setting the property shouldn't override it, just call the setter
+  // which in this case does nothing.
+  global->Set(some_property, v8::Int32::New(7));
+  CHECK_EQ(3, global->Get(some_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+  // Getting the property when the interceptor returns an empty handle
+  // should yield undefined, since the property isn't present on the
+  // object itself yet.
+  pass_on_get = true;
+  CHECK(global->Get(some_property)->IsUndefined());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(3, force_set_get_count);
+  // Forcing the property to be set should cause the value to be
+  // set locally without calling the interceptor.
+  global->ForceSet(some_property, v8::Int32::New(8));
+  CHECK_EQ(8, global->Get(some_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(4, force_set_get_count);
+  // Reenabling the interceptor should cause it to take precedence over
+  // the property
+  pass_on_get = false;
+  CHECK_EQ(3, global->Get(some_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(5, force_set_get_count);
+  // The interceptor should also work for other properties
+  CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(6, force_set_get_count);
+}
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index e482c7f..fea07c5 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -45,10 +45,13 @@
 using ::v8::internal::Code;
 using ::v8::internal::Debug;
 using ::v8::internal::Debugger;
+using ::v8::internal::Message;
+using ::v8::internal::MessageQueue;
 using ::v8::internal::StepAction;
 using ::v8::internal::StepIn;  // From StepAction enum
 using ::v8::internal::StepNext;  // From StepAction enum
 using ::v8::internal::StepOut;  // From StepAction enum
+using ::v8::internal::Vector;
 
 
 // Size of temp buffer for formatting small strings.
@@ -525,6 +528,24 @@
 v8::Local<v8::Function> frame_source_column;
 
 
+// Source for The JavaScript function which picks out the script name for the
+// top frame.
+const char* frame_script_name_source =
+    "function frame_script_name(exec_state) {"
+    "  return exec_state.frame(0).func().script().name();"
+    "}";
+v8::Local<v8::Function> frame_script_name;
+
+
+// Source for The JavaScript function which picks out the script data for the
+// top frame.
+const char* frame_script_data_source =
+    "function frame_script_data(exec_state) {"
+    "  return exec_state.frame(0).func().script().data();"
+    "}";
+v8::Local<v8::Function> frame_script_data;
+
+
 // Source for The JavaScript function which returns the number of frames.
 static const char* frame_count_source =
     "function frame_count(exec_state) {"
@@ -536,6 +557,11 @@
 // Global variable to store the last function hit - used by some tests.
 char last_function_hit[80];
 
+// Global variable to store the name and data for last script hit - used by some
+// tests.
+char last_script_name_hit[80];
+char last_script_data_hit[80];
+
 // Global variables to store the last source position - used by some tests.
 int last_source_line = -1;
 int last_source_column = -1;
@@ -586,6 +612,37 @@
       CHECK(result->IsNumber());
       last_source_column = result->Int32Value();
     }
+
+    if (!frame_script_name.IsEmpty()) {
+      // Get the script name of the function script.
+      const int argc = 1;
+      v8::Handle<v8::Value> argv[argc] = { exec_state };
+      v8::Handle<v8::Value> result = frame_script_name->Call(exec_state,
+                                                             argc, argv);
+      if (result->IsUndefined()) {
+        last_script_name_hit[0] = '\0';
+      } else {
+        CHECK(result->IsString());
+        v8::Handle<v8::String> script_name(result->ToString());
+        script_name->WriteAscii(last_script_name_hit);
+      }
+    }
+
+    if (!frame_script_data.IsEmpty()) {
+      // Get the script data of the function script.
+      const int argc = 1;
+      v8::Handle<v8::Value> argv[argc] = { exec_state };
+      v8::Handle<v8::Value> result = frame_script_data->Call(exec_state,
+                                                             argc, argv);
+      if (result->IsUndefined()) {
+        last_script_data_hit[0] = '\0';
+      } else {
+        result = result->ToString();
+        CHECK(result->IsString());
+        v8::Handle<v8::String> script_data(result->ToString());
+        script_data->WriteAscii(last_script_data_hit);
+      }
+    }
   }
 }
 
@@ -2120,6 +2177,53 @@
 }
 
 
+// Test of the stepping mechanism for keyed load in a loop.
+TEST(DebugStepKeyedLoadLoop) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // 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(
+      &env,
+      "function foo(a) {\n"
+      "  var x;\n"
+      "  var len = a.length;\n"
+      "  for (var i = 0; i < len; i++) {\n"
+      "    y = 1;\n"
+      "    x = a[i];\n"
+      "  }\n"
+      "}\n",
+      "foo");
+
+  // Create array [0,1,2,3,4,5,6,7,8,9]
+  v8::Local<v8::Array> a = v8::Array::New(10);
+  for (int i = 0; i < 10; i++) {
+    a->Set(v8::Number::New(i), v8::Number::New(i));
+  }
+
+  // Call function without any break points to ensure inlining is in place.
+  const int kArgc = 1;
+  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;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), kArgc, args);
+
+  // With stepping all break locations are hit.
+  CHECK_EQ(22, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
 // Test the stepping mechanism with different ICs.
 TEST(DebugStepLinearMixedICs) {
   v8::HandleScope scope;
@@ -3321,7 +3425,8 @@
   void Run();
 };
 
-static void MessageHandler(const uint16_t* message, int length, void *data) {
+static void MessageHandler(const uint16_t* message, int length,
+                           v8::Debug::ClientData* client_data) {
   static char print_buffer[1000];
   Utf16ToAscii(message, length, print_buffer);
   if (IsBreakEventMessage(print_buffer)) {
@@ -3336,7 +3441,6 @@
   fflush(stdout);
 }
 
-
 void MessageQueueDebuggerThread::Run() {
   const int kBufferSize = 1000;
   uint16_t buffer_1[kBufferSize];
@@ -3427,6 +3531,118 @@
   fflush(stdout);
 }
 
+
+class TestClientData : public v8::Debug::ClientData {
+ public:
+  TestClientData() {
+    constructor_call_counter++;
+  }
+  virtual ~TestClientData() {
+    destructor_call_counter++;
+  }
+
+  static void ResetCounters() {
+    constructor_call_counter = 0;
+    destructor_call_counter = 0;
+  }
+
+  static int constructor_call_counter;
+  static int destructor_call_counter;
+};
+
+int TestClientData::constructor_call_counter = 0;
+int TestClientData::destructor_call_counter = 0;
+
+
+// Tests that MessageQueue doesn't destroy client data when expands and
+// does destroy when it dies.
+TEST(MessageQueueExpandAndDestroy) {
+  TestClientData::ResetCounters();
+  { // Create a scope for the queue.
+    MessageQueue queue(1);
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    ASSERT_EQ(0, TestClientData::destructor_call_counter);
+    queue.Get().Dispose();
+    ASSERT_EQ(1, TestClientData::destructor_call_counter);
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    queue.Put(Message::NewOutput(v8::Handle<v8::String>(),
+                                 new TestClientData()));
+    queue.Put(Message::NewEmptyMessage());
+    ASSERT_EQ(1, TestClientData::destructor_call_counter);
+    queue.Get().Dispose();
+    ASSERT_EQ(2, TestClientData::destructor_call_counter);
+  }
+  // All the client data should be destroyed when the queue is destroyed.
+  ASSERT_EQ(TestClientData::destructor_call_counter,
+            TestClientData::destructor_call_counter);
+}
+
+
+static int handled_client_data_instances_count = 0;
+static void MessageHandlerCountingClientData(
+    const uint16_t* message,
+    int length,
+    v8::Debug::ClientData* client_data) {
+  if (client_data) {
+    handled_client_data_instances_count++;
+  }
+}
+
+
+// Tests that all client data passed to the debugger are sent to the handler.
+TEST(SendClientDataToHandler) {
+  // Create a V8 environment
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  TestClientData::ResetCounters();
+  handled_client_data_instances_count = 0;
+  v8::Debug::SetMessageHandler(MessageHandlerCountingClientData,
+                               false /* message_handler_thread */);
+  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5; debugger;";
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+  const char* command_1 =
+      "{\"seq\":117,"
+       "\"type\":\"request\","
+       "\"command\":\"evaluate\","
+       "\"arguments\":{\"expression\":\"1+2\"}}";
+  const char* command_2 =
+    "{\"seq\":118,"
+     "\"type\":\"request\","
+     "\"command\":\"evaluate\","
+     "\"arguments\":{\"expression\":\"1+a\"}}";
+  const char* command_continue =
+    "{\"seq\":106,"
+     "\"type\":\"request\","
+     "\"command\":\"continue\"}";
+
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer),
+                         new TestClientData());
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer), NULL);
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer),
+                         new TestClientData());
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer),
+                         new TestClientData());
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+  CompileRun(source_1);
+  ASSERT_EQ(3, TestClientData::constructor_call_counter);
+  ASSERT_EQ(TestClientData::constructor_call_counter,
+            handled_client_data_instances_count);
+  ASSERT_EQ(TestClientData::constructor_call_counter,
+            TestClientData::destructor_call_counter);
+}
+
+
 /* Test ThreadedDebugging */
 /* This test interrupts a running infinite loop that is
  * occupying the v8 thread by a break command from the
@@ -3454,7 +3670,7 @@
 
 
 static void ThreadedMessageHandler(const uint16_t* message, int length,
-                                   void *data) {
+                                   v8::Debug::ClientData* client_data) {
   static char print_buffer[1000];
   Utf16ToAscii(message, length, print_buffer);
   if (IsBreakEventMessage(print_buffer)) {
@@ -3552,7 +3768,7 @@
 
 static void BreakpointsMessageHandler(const uint16_t* message,
                                       int length,
-                                      void *data) {
+                                      v8::Debug::ClientData* client_data) {
   static char print_buffer[1000];
   Utf16ToAscii(message, length, print_buffer);
   printf("%s\n", print_buffer);
@@ -3698,7 +3914,8 @@
 
 
 static void DummyMessageHandler(const uint16_t* message,
-                                int length, void *data) {
+                                int length,
+                                v8::Debug::ClientData* client_data) {
 }
 
 
@@ -3924,7 +4141,8 @@
 // Debugger message handler which counts the number of times it is called.
 static int message_handler_hit_count = 0;
 static void MessageHandlerHitCount(const uint16_t* message,
-                                   int length, void* data) {
+                                   int length,
+                                   v8::Debug::ClientData* client_data) {
   message_handler_hit_count++;
 
   const int kBufferSize = 1000;
@@ -3972,9 +4190,10 @@
 
 
 // Debugger message handler which clears the message handler while active.
-static void MessageHandlerClearingMessageHandler(const uint16_t* message,
-                                                 int length,
-                                                 void* data) {
+static void MessageHandlerClearingMessageHandler(
+    const uint16_t* message,
+    int length,
+    v8::Debug::ClientData* client_data) {
   message_handler_hit_count++;
 
   // Clear debug message handler.
@@ -4004,54 +4223,107 @@
 }
 
 
-int host_dispatch_hit_count = 0;
-static void HostDispatchHandlerHitCount(void* dispatch, void *data) {
-  host_dispatch_hit_count++;
+/* Test DebuggerHostDispatch */
+/* In this test, the debugger waits for a command on a breakpoint
+ * and is dispatching host commands while in the infinite loop.
+ */
+
+class HostDispatchV8Thread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+class HostDispatchDebuggerThread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+Barriers* host_dispatch_barriers;
+
+static void HostDispatchMessageHandler(const uint16_t* message,
+                                       int length,
+                                       v8::Debug::ClientData* client_data) {
+  static char print_buffer[1000];
+  Utf16ToAscii(message, length, print_buffer);
+  printf("%s\n", print_buffer);
+  fflush(stdout);
 }
 
 
-// Test that clearing the debug event listener actually clears all break points
-// and related information.
-TEST(DebuggerHostDispatch) {
-  i::FLAG_debugger_auto_break = true;
+static void HostDispatchDispatchHandler() {
+  host_dispatch_barriers->semaphore_1->Signal();
+}
+
+
+void HostDispatchV8Thread::Run() {
+  const char* source_1 = "var y_global = 3;\n"
+    "function cat( new_value ) {\n"
+    "  var x = new_value;\n"
+    "  y_global = 4;\n"
+    "  x = 3 * x + 1;\n"
+    "  y_global = 5;\n"
+    "  return x;\n"
+    "}\n"
+    "\n";
+  const char* source_2 = "cat(17);\n";
 
   v8::HandleScope scope;
   DebugLocalContext env;
 
-  const int kBufferSize = 1000;
-  uint16_t buffer[kBufferSize];
-  const char* command_continue =
-    "{\"seq\":0,"
-     "\"type\":\"request\","
-     "\"command\":\"continue\"}";
-
-  // Create an empty function to call for processing debug commands
-  v8::Local<v8::Function> empty =
-      CompileFunction(&env, "function empty(){}", "empty");
-
   // Setup message and host dispatch handlers.
-  v8::Debug::SetMessageHandler(DummyMessageHandler);
-  v8::Debug::SetHostDispatchHandler(HostDispatchHandlerHitCount,
-                                    NULL);
+  v8::Debug::SetMessageHandler(HostDispatchMessageHandler);
+  v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms */);
 
-  // Send a host dispatch by itself.
-  v8::Debug::SendHostDispatch(NULL);
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
-  CHECK_EQ(1, host_dispatch_hit_count);
+  CompileRun(source_1);
+  host_dispatch_barriers->barrier_1.Wait();
+  host_dispatch_barriers->barrier_2.Wait();
+  CompileRun(source_2);
+}
 
-  // Fill a host dispatch and a continue command on the command queue.
-  v8::Debug::SendHostDispatch(NULL);
-  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
 
-  // Fill a continue command and a host dispatch on the command queue.
-  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
-  v8::Debug::SendHostDispatch(NULL);
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
+void HostDispatchDebuggerThread::Run() {
+  const int kBufSize = 1000;
+  uint16_t buffer[kBufSize];
 
-  // All the host dispatch callback should be called.
-  CHECK_EQ(3, host_dispatch_hit_count);
+  const char* command_1 = "{\"seq\":101,"
+      "\"type\":\"request\","
+      "\"command\":\"setbreakpoint\","
+      "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
+  const char* command_2 = "{\"seq\":102,"
+      "\"type\":\"request\","
+      "\"command\":\"continue\"}";
+
+  // v8 thread initializes, runs source_1
+  host_dispatch_barriers->barrier_1.Wait();
+  // 1: Set breakpoint in cat().
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
+
+  host_dispatch_barriers->barrier_2.Wait();
+  // v8 thread starts compiling source_2.
+  // Break happens, to run queued commands and host dispatches.
+  // Wait for host dispatch to be processed.
+  host_dispatch_barriers->semaphore_1->Wait();
+  // 2: Continue evaluation
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
+}
+
+HostDispatchDebuggerThread host_dispatch_debugger_thread;
+HostDispatchV8Thread host_dispatch_v8_thread;
+
+
+TEST(DebuggerHostDispatch) {
+  i::FLAG_debugger_auto_break = true;
+
+  // Create a V8 environment
+  Barriers stack_allocated_host_dispatch_barriers;
+  stack_allocated_host_dispatch_barriers.Initialize();
+  host_dispatch_barriers = &stack_allocated_host_dispatch_barriers;
+
+  host_dispatch_v8_thread.Start();
+  host_dispatch_debugger_thread.Start();
+
+  host_dispatch_v8_thread.Join();
+  host_dispatch_debugger_thread.Join();
 }
 
 
@@ -4249,3 +4521,58 @@
   // Must not crash while accessing line_ends.
   i::FLAG_allow_natives_syntax = allow_natives_syntax;
 }
+
+
+// Test script break points set on lines.
+TEST(ScriptNameAndData) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  // Create functions for retrieving script name and data for the function on
+  // the top frame when hitting a break point.
+  frame_script_name = CompileFunction(&env,
+                                      frame_script_name_source,
+                                      "frame_script_name");
+  frame_script_data = CompileFunction(&env,
+                                      frame_script_data_source,
+                                      "frame_script_data");
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  // Test function source.
+  v8::Local<v8::String> script = v8::String::New(
+    "function f() {\n"
+    "  debugger;\n"
+    "}\n");
+
+  v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8::String::New("name"));
+  v8::Handle<v8::Script> script1 = v8::Script::Compile(script, &origin1);
+  script1->SetData(v8::String::New("data"));
+  script1->Run();
+  v8::Script::Compile(script, &origin1)->Run();
+  v8::Local<v8::Function> f;
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  CHECK_EQ("name", last_script_name_hit);
+  CHECK_EQ("data", last_script_data_hit);
+
+  v8::Local<v8::String> data_obj_source = v8::String::New(
+    "({ a: 'abc',\n"
+    "  b: 123,\n"
+    "  toString: function() { return this.a + ' ' + this.b; }\n"
+    "})\n");
+  v8::Local<v8::Value> data_obj = v8::Script::Compile(data_obj_source)->Run();
+  v8::ScriptOrigin origin2 = v8::ScriptOrigin(v8::String::New("new name"));
+  v8::Handle<v8::Script> script2 = v8::Script::Compile(script, &origin2);
+  script2->Run();
+  script2->SetData(data_obj);
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+  CHECK_EQ("new name", last_script_name_hit);
+  CHECK_EQ("abc 123", last_script_data_hit);
+}
diff --git a/test/cctest/test-func-name-inference.cc b/test/cctest/test-func-name-inference.cc
index 5058629..d91f75f 100644
--- a/test/cctest/test-func-name-inference.cc
+++ b/test/cctest/test-func-name-inference.cc
@@ -221,3 +221,30 @@
   CheckFunctionName(script, "return 2", "");
   CheckFunctionName(script, "return 3", "");
 }
+
+
+TEST(MultipleFuncsConditional) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "fun1 = 0 ?\n"
+      "    function() { return 1; } :\n"
+      "    function() { return 2; }");
+  CheckFunctionName(script, "return 1", "fun1");
+  CheckFunctionName(script, "return 2", "fun1");
+}
+
+
+TEST(MultipleFuncsInLiteral) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function MyClass() {}\n"
+      "MyClass.prototype = {\n"
+      "  method1: 0 ? function() { return 1; } :\n"
+      "               function() { return 2; } }");
+  CheckFunctionName(script, "return 1", "MyClass.method1");
+  CheckFunctionName(script, "return 2", "MyClass.method1");
+}
diff --git a/test/mjsunit/array-reduce.js b/test/mjsunit/array-reduce.js
new file mode 100644
index 0000000..e476e1c
--- /dev/null
+++ b/test/mjsunit/array-reduce.js
@@ -0,0 +1,514 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test reduce and reduceRight
+ */
+
+function clone(v) {
+  // Shallow-copies arrays, returns everything else verbatim.
+  if (v instanceof Array) {
+    // Shallow-copy an array.
+    var newArray = new Array(v.length);
+    for (var i in v) {
+      newArray[i] = v[i];
+    }
+    return newArray;
+  }
+  return v;
+}
+
+
+// Creates a callback function for reduce/reduceRight that tests the number
+// of arguments and otherwise behaves as "func", but which also
+// records all calls in an array on the function (as arrays of arguments
+// followed by result).
+function makeRecorder(func, testName) {
+  var record = [];
+  var f = function recorder(a, b, i, s) {
+    assertEquals(4, arguments.length,
+                 testName + "(number of arguments: " + arguments.length + ")");
+    assertEquals("number", typeof(i), testName + "(index must be number)");
+    assertEquals(s[i], b, testName + "(current argument is at index)");
+    if (record.length > 0) {
+      var prevRecord = record[record.length - 1];
+      var prevResult = prevRecord[prevRecord.length - 1];
+      assertEquals(prevResult, a,
+                   testName + "(prev result -> current input)");
+    }
+    var args = [clone(a), clone(b), i, clone(s)];
+    var result = func.apply(this, arguments);
+    args.push(clone(result));
+    record.push(args);
+    return result;
+  };
+  f.record = record;
+  return f;
+}
+
+
+function testReduce(type,
+                    testName,
+                    expectedResult,
+                    expectedCalls,
+                    array,
+                    combine,
+                    init) {
+  var rec = makeRecorder(combine);
+  var result;
+  var performsCall;
+  if (arguments.length > 6) {
+    result = array[type](rec, init);
+  } else {
+    result = array[type](rec);
+  }
+  var calls = rec.record;
+  assertEquals(expectedCalls.length, calls.length,
+               testName + " (number of calls)");
+  for (var i = 0; i < expectedCalls.length; i++) {
+    assertEquals(expectedCalls[i], calls[i],
+                 testName + " (call " + (i + 1) + ")");
+  }
+  assertEquals(expectedResult, result, testName + " (result)");
+}
+
+
+function sum(a, b) { return a + b; }
+function prod(a, b) { return a * b; }
+function dec(a, b, i, arr) { return a + b * Math.pow(10, arr.length - i - 1); }
+function accumulate(acc, elem, i) { acc[i] = elem; return acc; }
+
+// ---- Test Reduce[Left]
+
+var simpleArray = [2,4,6]
+
+testReduce("reduce", "SimpleReduceSum", 12,
+           [[0, 2, 0, simpleArray, 2],
+            [2, 4, 1, simpleArray, 6],
+            [6, 6, 2, simpleArray, 12]],
+           simpleArray, sum, 0);
+
+testReduce("reduce", "SimpleReduceProd", 48,
+           [[1, 2, 0, simpleArray, 2],
+            [2, 4, 1, simpleArray, 8],
+            [8, 6, 2, simpleArray, 48]],
+           simpleArray, prod, 1);
+
+testReduce("reduce", "SimpleReduceDec", 246,
+           [[0, 2, 0, simpleArray, 200],
+            [200, 4, 1, simpleArray, 240],
+            [240, 6, 2, simpleArray, 246]],
+           simpleArray, dec, 0);
+
+testReduce("reduce", "SimpleReduceAccumulate", simpleArray,
+           [[[], 2, 0, simpleArray, [2]],
+            [[2], 4, 1, simpleArray, [2, 4]],
+            [[2,4], 6, 2, simpleArray, simpleArray]],
+           simpleArray, accumulate, []);
+
+
+testReduce("reduce", "EmptyReduceSum", 0, [], [], sum, 0);
+testReduce("reduce", "EmptyReduceProd", 1, [], [], prod, 1);
+testReduce("reduce", "EmptyReduceDec", 0, [], [], dec, 0);
+testReduce("reduce", "EmptyReduceAccumulate", [], [], [], accumulate, []);
+
+testReduce("reduce", "EmptyReduceSumNoInit", 0, [], [0], sum);
+testReduce("reduce", "EmptyReduceProdNoInit", 1, [], [1], prod);
+testReduce("reduce", "EmptyReduceDecNoInit", 0, [], [0], dec);
+testReduce("reduce", "EmptyReduceAccumulateNoInit", [], [], [[]], accumulate);
+
+
+var simpleSparseArray = [,,,2,,4,,6,,];
+testReduce("reduce", "SimpleSparseReduceSum", 12,
+           [[0, 2, 3, simpleSparseArray, 2],
+            [2, 4, 5, simpleSparseArray, 6],
+            [6, 6, 7, simpleSparseArray, 12]],
+           simpleSparseArray, sum, 0);
+
+testReduce("reduce", "SimpleSparseReduceProd", 48,
+           [[1, 2, 3, simpleSparseArray, 2],
+            [2, 4, 5, simpleSparseArray, 8],
+            [8, 6, 7, simpleSparseArray, 48]],
+           simpleSparseArray, prod, 1);
+
+testReduce("reduce", "SimpleSparseReduceDec", 204060,
+           [[0, 2, 3, simpleSparseArray, 200000],
+            [200000, 4, 5, simpleSparseArray, 204000],
+            [204000, 6, 7, simpleSparseArray, 204060]],
+           simpleSparseArray, dec, 0);
+
+testReduce("reduce", "SimpleSparseReduceAccumulate", [,,,2,,4,,6],
+           [[[], 2, 3, simpleSparseArray, [,,,2]],
+            [[,,,2], 4, 5, simpleSparseArray, [,,,2,,4]],
+            [[,,,2,,4], 6, 7, simpleSparseArray, [,,,2,,4,,6]]],
+           simpleSparseArray, accumulate, []);
+
+
+testReduce("reduce", "EmptySparseReduceSumNoInit", 0, [], [,,0,,], sum);
+testReduce("reduce", "EmptySparseReduceProdNoInit", 1, [], [,,1,,], prod);
+testReduce("reduce", "EmptySparseReduceDecNoInit", 0, [], [,,0,,], dec);
+testReduce("reduce", "EmptySparseReduceAccumulateNoInit",
+           [], [], [,,[],,], accumulate);
+
+
+var verySparseArray = [];
+verySparseArray.length = 10000;
+verySparseArray[2000] = 2;
+verySparseArray[5000] = 4;
+verySparseArray[9000] = 6;
+var verySparseSlice2 = verySparseArray.slice(0, 2001);
+var verySparseSlice4 = verySparseArray.slice(0, 5001);
+var verySparseSlice6 = verySparseArray.slice(0, 9001);
+
+testReduce("reduce", "VerySparseReduceSum", 12,
+           [[0, 2, 2000, verySparseArray, 2],
+            [2, 4, 5000, verySparseArray, 6],
+            [6, 6, 9000, verySparseArray, 12]],
+           verySparseArray, sum, 0);
+
+testReduce("reduce", "VerySparseReduceProd", 48,
+           [[1, 2, 2000, verySparseArray, 2],
+            [2, 4, 5000, verySparseArray, 8],
+            [8, 6, 9000, verySparseArray, 48]],
+           verySparseArray, prod, 1);
+
+testReduce("reduce", "VerySparseReduceDec", Infinity,
+           [[0, 2, 2000, verySparseArray, Infinity],
+            [Infinity, 4, 5000, verySparseArray, Infinity],
+            [Infinity, 6, 9000, verySparseArray, Infinity]],
+           verySparseArray, dec, 0);
+
+testReduce("reduce", "VerySparseReduceAccumulate",
+           verySparseSlice6,
+           [[[], 2, 2000, verySparseArray, verySparseSlice2],
+            [verySparseSlice2, 4, 5000, verySparseArray, verySparseSlice4],
+            [verySparseSlice4, 6, 9000, verySparseArray, verySparseSlice6]],
+           verySparseArray, accumulate, []);
+
+
+testReduce("reduce", "VerySparseReduceSumNoInit", 12,
+           [[2, 4, 5000, verySparseArray, 6],
+            [6, 6, 9000, verySparseArray, 12]],
+           verySparseArray, sum);
+
+testReduce("reduce", "VerySparseReduceProdNoInit", 48,
+           [[2, 4, 5000, verySparseArray, 8],
+            [8, 6, 9000, verySparseArray, 48]],
+           verySparseArray, prod);
+
+testReduce("reduce", "VerySparseReduceDecNoInit", Infinity,
+           [[2, 4, 5000, verySparseArray, Infinity],
+            [Infinity, 6, 9000, verySparseArray, Infinity]],
+           verySparseArray, dec);
+
+testReduce("reduce", "SimpleSparseReduceAccumulateNoInit",
+           2,
+           [[2, 4, 5000, verySparseArray, 2],
+            [2, 6, 9000, verySparseArray, 2]],
+           verySparseArray, accumulate);
+
+
+// ---- Test ReduceRight
+
+testReduce("reduceRight", "SimpleReduceRightSum", 12,
+           [[0, 6, 2, simpleArray, 6],
+            [6, 4, 1, simpleArray, 10],
+            [10, 2, 0, simpleArray, 12]],
+           simpleArray, sum, 0);
+
+testReduce("reduceRight", "SimpleReduceRightProd", 48,
+           [[1, 6, 2, simpleArray, 6],
+            [6, 4, 1, simpleArray, 24],
+            [24, 2, 0, simpleArray, 48]],
+           simpleArray, prod, 1);
+
+testReduce("reduceRight", "SimpleReduceRightDec", 246,
+           [[0, 6, 2, simpleArray, 6],
+            [6, 4, 1, simpleArray, 46],
+            [46, 2, 0, simpleArray, 246]],
+           simpleArray, dec, 0);
+
+testReduce("reduceRight", "SimpleReduceRightAccumulate", simpleArray,
+           [[[], 6, 2, simpleArray, [,,6]],
+            [[,,6], 4, 1, simpleArray, [,4,6]],
+            [[,4,6], 2, 0, simpleArray, simpleArray]],
+           simpleArray, accumulate, []);
+
+
+testReduce("reduceRight", "EmptyReduceRightSum", 0, [], [], sum, 0);
+testReduce("reduceRight", "EmptyReduceRightProd", 1, [], [], prod, 1);
+testReduce("reduceRight", "EmptyReduceRightDec", 0, [], [], dec, 0);
+testReduce("reduceRight", "EmptyReduceRightAccumulate", [],
+           [], [], accumulate, []);
+
+testReduce("reduceRight", "EmptyReduceRightSumNoInit", 0, [], [0], sum);
+testReduce("reduceRight", "EmptyReduceRightProdNoInit", 1, [], [1], prod);
+testReduce("reduceRight", "EmptyReduceRightDecNoInit", 0, [], [0], dec);
+testReduce("reduceRight", "EmptyReduceRightAccumulateNoInit",
+           [], [], [[]], accumulate);
+
+
+testReduce("reduceRight", "SimpleSparseReduceRightSum", 12,
+           [[0, 6, 7, simpleSparseArray, 6],
+            [6, 4, 5, simpleSparseArray, 10],
+            [10, 2, 3, simpleSparseArray, 12]],
+           simpleSparseArray, sum, 0);
+
+testReduce("reduceRight", "SimpleSparseReduceRightProd", 48,
+           [[1, 6, 7, simpleSparseArray, 6],
+            [6, 4, 5, simpleSparseArray, 24],
+            [24, 2, 3, simpleSparseArray, 48]],
+           simpleSparseArray, prod, 1);
+
+testReduce("reduceRight", "SimpleSparseReduceRightDec", 204060,
+           [[0, 6, 7, simpleSparseArray, 60],
+            [60, 4, 5, simpleSparseArray, 4060],
+            [4060, 2, 3, simpleSparseArray, 204060]],
+           simpleSparseArray, dec, 0);
+
+testReduce("reduceRight", "SimpleSparseReduceRightAccumulate", [,,,2,,4,,6],
+           [[[], 6, 7, simpleSparseArray, [,,,,,,,6]],
+            [[,,,,,,,6], 4, 5, simpleSparseArray, [,,,,,4,,6]],
+            [[,,,,,4,,6], 2, 3, simpleSparseArray, [,,,2,,4,,6]]],
+           simpleSparseArray, accumulate, []);
+
+
+testReduce("reduceRight", "EmptySparseReduceRightSumNoInit",
+           0, [], [,,0,,], sum);
+testReduce("reduceRight", "EmptySparseReduceRightProdNoInit",
+           1, [], [,,1,,], prod);
+testReduce("reduceRight", "EmptySparseReduceRightDecNoInit",
+           0, [], [,,0,,], dec);
+testReduce("reduceRight", "EmptySparseReduceRightAccumulateNoInit",
+           [], [], [,,[],,], accumulate);
+
+
+var verySparseSuffix6 = [];
+verySparseSuffix6[9000] = 6;
+var verySparseSuffix4 = [];
+verySparseSuffix4[5000] = 4;
+verySparseSuffix4[9000] = 6;
+var verySparseSuffix2 = verySparseSlice6;
+
+
+testReduce("reduceRight", "VerySparseReduceRightSum", 12,
+           [[0, 6, 9000, verySparseArray, 6],
+            [6, 4, 5000, verySparseArray, 10],
+            [10, 2, 2000, verySparseArray, 12]],
+           verySparseArray, sum, 0);
+
+testReduce("reduceRight", "VerySparseReduceRightProd", 48,
+           [[1, 6, 9000, verySparseArray, 6],
+            [6, 4, 5000, verySparseArray, 24],
+            [24, 2, 2000, verySparseArray, 48]],
+           verySparseArray, prod, 1);
+
+testReduce("reduceRight", "VerySparseReduceRightDec", Infinity,
+           [[0, 6, 9000, verySparseArray, Infinity],
+            [Infinity, 4, 5000, verySparseArray, Infinity],
+            [Infinity, 2, 2000, verySparseArray, Infinity]],
+           verySparseArray, dec, 0);
+
+testReduce("reduceRight", "VerySparseReduceRightAccumulate",
+           verySparseSuffix2,
+           [[[], 6, 9000, verySparseArray, verySparseSuffix6],
+            [verySparseSuffix6, 4, 5000, verySparseArray, verySparseSuffix4],
+            [verySparseSuffix4, 2, 2000, verySparseArray, verySparseSuffix2]],
+           verySparseArray, accumulate, []);
+
+
+testReduce("reduceRight", "VerySparseReduceRightSumNoInit", 12,
+           [[6, 4, 5000, verySparseArray, 10],
+            [10, 2, 2000, verySparseArray, 12]],
+           verySparseArray, sum);
+
+testReduce("reduceRight", "VerySparseReduceRightProdNoInit", 48,
+           [[6, 4, 5000, verySparseArray, 24],
+            [24, 2, 2000, verySparseArray, 48]],
+           verySparseArray, prod);
+
+testReduce("reduceRight", "VerySparseReduceRightDecNoInit", Infinity,
+           [[6, 4, 5000, verySparseArray, Infinity],
+            [Infinity, 2, 2000, verySparseArray, Infinity]],
+           verySparseArray, dec);
+
+testReduce("reduceRight", "SimpleSparseReduceRightAccumulateNoInit",
+           6,
+           [[6, 4, 5000, verySparseArray, 6],
+            [6, 2, 2000, verySparseArray, 6]],
+           verySparseArray, accumulate);
+
+
+// undefined is an element
+var undefArray = [,,undefined,,undefined,,];
+
+testReduce("reduce", "SparseUndefinedReduceAdd", NaN,
+           [[0, undefined, 2, undefArray, NaN],
+            [NaN, undefined, 4, undefArray, NaN],
+           ],
+           undefArray, sum, 0);
+
+testReduce("reduceRight", "SparseUndefinedReduceRightAdd", NaN,
+           [[0, undefined, 4, undefArray, NaN],
+            [NaN, undefined, 2, undefArray, NaN],
+           ], undefArray, sum, 0);
+
+testReduce("reduce", "SparseUndefinedReduceAddNoInit", NaN,
+           [[undefined, undefined, 4, undefArray, NaN],
+           ], undefArray, sum);
+
+testReduce("reduceRight", "SparseUndefinedReduceRightAddNoInit", NaN,
+           [[undefined, undefined, 2, undefArray, NaN],
+           ], undefArray, sum);
+
+
+// Ignore non-array properties:
+
+var arrayPlus = [1,2,,3];
+arrayPlus[-1] = NaN;
+arrayPlus[Math.pow(2,32)] = NaN;
+arrayPlus[NaN] = NaN;
+arrayPlus["00"] = NaN;
+arrayPlus["02"] = NaN;
+arrayPlus["-0"] = NaN;
+
+testReduce("reduce", "ArrayWithNonElementPropertiesReduce", 6,
+           [[0, 1, 0, arrayPlus, 1],
+            [1, 2, 1, arrayPlus, 3],
+            [3, 3, 3, arrayPlus, 6],
+           ], arrayPlus, sum, 0);
+
+testReduce("reduceRight", "ArrayWithNonElementPropertiesReduceRight", 6,
+           [[0, 3, 3, arrayPlus, 3],
+            [3, 2, 1, arrayPlus, 5],
+            [5, 1, 0, arrayPlus, 6],
+           ], arrayPlus, sum, 0);
+
+
+// Test error conditions:
+
+try {
+  [1].reduce("not a function");
+  fail("Reduce callback not a function not throwing");
+} catch (e) {
+  assertTrue(e instanceof TypeError,
+             "reduce callback not a function not throwing TypeError");
+  assertEquals("called_non_callable", e.type,
+               "reduce non function TypeError type");
+}
+
+try {
+  [1].reduceRight("not a function");
+  fail("ReduceRight callback not a function not throwing");
+} catch (e) {
+  assertTrue(e instanceof TypeError,
+             "reduceRight callback not a function not throwing TypeError");
+  assertEquals("called_non_callable", e.type,
+               "reduceRight non function TypeError type");
+}
+
+
+try {
+  [].reduce(sum);
+  fail("Reduce no initial value not throwing");
+} catch (e) {
+  assertTrue(e instanceof TypeError,
+             "reduce no initial value not throwing TypeError");
+  assertEquals("reduce_no_initial", e.type,
+               "reduce no initial TypeError type");
+}
+
+try {
+  [].reduceRight(sum);
+  fail("ReduceRight no initial value not throwing");
+} catch (e) {
+  assertTrue(e instanceof TypeError,
+             "reduceRight no initial value not throwing TypeError");
+  assertEquals("reduce_no_initial", e.type,
+               "reduceRight no initial TypeError type");
+}
+
+
+try {
+  [,,,].reduce(sum);
+  fail("Reduce sparse no initial value not throwing");
+} catch (e) {
+  assertTrue(e instanceof TypeError,
+             "reduce sparse no initial value not throwing TypeError");
+  assertEquals("reduce_no_initial", e.type,
+               "reduce no initial TypeError type");
+}
+
+try {
+  [,,,].reduceRight(sum);
+  fail("ReduceRight sparse no initial value not throwing");
+} catch (e) {
+  assertTrue(e instanceof TypeError,
+             "reduceRight sparse no initial value not throwing TypeError");
+  assertEquals("reduce_no_initial", e.type,
+               "reduceRight no initial TypeError type");
+}
+
+
+// Array changing length
+
+function manipulator(a, b, i, s) {
+  if (s.length % 2) {
+    s[s.length * 3] = i;
+  } else {
+    s.length = s.length >> 1;
+  }
+  return a + b;
+}
+
+var arr = [1, 2, 3, 4];
+testReduce("reduce", "ArrayManipulationShort", 3,
+           [[0, 1, 0, [1, 2, 3, 4], 1],
+            [1, 2, 1, [1, 2], 3],
+           ], arr, manipulator, 0);
+
+var arr = [1, 2, 3, 4, 5];
+testReduce("reduce", "ArrayManipulationLonger", 10,
+           [[0, 1, 0, [1, 2, 3, 4, 5], 1],
+            [1, 2, 1, [1, 2, 3, 4, 5,,,,,,,,,,, 0], 3],
+            [3, 3, 2, [1, 2, 3, 4, 5,,,,], 6],
+            [6, 4, 3, [1, 2, 3, 4], 10],
+           ], arr, manipulator, 0);
+
+function extender(a, b, i, s) {
+  s[s.length] = s.length;
+  return a + b;
+}
+
+var arr = [1, 2, 3, 4];
+testReduce("reduce", "ArrayManipulationExtender", 10,
+           [[0, 1, 0, [1, 2, 3, 4], 1],
+            [1, 2, 1, [1, 2, 3, 4, 4], 3],
+            [3, 3, 2, [1, 2, 3, 4, 4, 5], 6],
+            [6, 4, 3, [1, 2, 3, 4, 4, 5, 6], 10],
+           ], arr, extender, 0);
+
diff --git a/test/mjsunit/constant-folding.js b/test/mjsunit/constant-folding.js
index 41b632f..4deb43c 100644
--- a/test/mjsunit/constant-folding.js
+++ b/test/mjsunit/constant-folding.js
@@ -168,4 +168,65 @@
   assertEquals(17, j, "switch with constant value");
 }
 
+
+function TrueToString() {
+  return true.toString();
+}
+
+
+function FalseToString() {
+  return false.toString();
+}
+
+
+function BoolTest() {
+  assertEquals("true", TrueToString());
+  assertEquals("true", TrueToString());
+  assertEquals("true", TrueToString());
+  assertEquals("false", FalseToString());
+  assertEquals("false", FalseToString());
+  assertEquals("false", FalseToString());
+  Boolean.prototype.toString = function() { return "foo"; }
+  assertEquals("foo", TrueToString());
+  assertEquals("foo", FalseToString());
+}
+
+
+// Some tests of shifts that get into the corners in terms of coverage.
+// We generate different code for the case where the operand is a constant.
+function ShiftTest() {
+  var x = 123;
+  assertEquals(x, x >> 0);
+  assertEquals(x, x << 0);
+  assertEquals(x, x >>> 0);
+  assertEquals(61, x >> 1);
+  assertEquals(246, x << 1);
+  assertEquals(61, x >>> 1);
+  x = -123;
+  assertEquals(x, x >> 0);
+  assertEquals(x, x << 0);
+  assertEquals(0x10000 * 0x10000 + x, x >>> 0);
+  assertEquals(-62, x >> 1);
+  assertEquals(-246, x << 1);
+  assertEquals(0x10000 * 0x8000 - 62, x >>> 1);
+  // Answer is non-Smi so the subtraction is not folded in the code
+  // generator.
+  assertEquals(-0x40000001, -0x3fffffff - 2);
+
+  x = 123;
+  assertEquals(0, x & 0);
+
+  // Answer is non-smi and lhs of << is a temporary heap number that we can
+  // overwrite.
+  x = 123.0001;
+  assertEquals(1073741824, (x * x) << 30);
+  x = 123;
+  // Answer is non-smi and lhs of << is a temporary heap number that we think
+  // we can overwrite (but we can't because it's a Smi).
+  assertEquals(1073741824, (x * x) << 30);
+}
+
+
 test();
+BoolTest();
+ShiftTest();
diff --git a/test/mjsunit/debug-handle.js b/test/mjsunit/debug-handle.js
index 64a68a8..c7ab76a 100644
--- a/test/mjsunit/debug-handle.js
+++ b/test/mjsunit/debug-handle.js
@@ -95,8 +95,8 @@
 
     // Test some illegal lookup requests.
     lookupRequest(dcp, void 0, false);
-    lookupRequest(dcp, '{"handle":"a"}', false);
-    lookupRequest(dcp, '{"handle":-1}', false);
+    lookupRequest(dcp, '{"handles":["a"]}', false);
+    lookupRequest(dcp, '{"handles":[-1]}', false);
 
     // Evaluate and get some handles.
     var handle_o = evaluateRequest(dcp, '{"expression":"o"}');
@@ -109,24 +109,28 @@
 
     var response;
     var count;
-    response = lookupRequest(dcp, '{"handle":' + handle_o + '}', true);
-    assertEquals(handle_o, response.body.handle);
+    response = lookupRequest(dcp, '{"handles":[' + handle_o + ']}', true);
+    var obj = response.body[handle_o];
+    assertTrue(!!obj, 'Object not found: ' + handle_o);
+    assertEquals(handle_o, obj.handle);
     count = 0;
-    for (i in response.body.properties) {
-      switch (response.body.properties[i].name) {
+    for (i in obj.properties) {
+      switch (obj.properties[i].name) {
         case 'o':
-          response.body.properties[i].ref = handle_o;
+          obj.properties[i].ref = handle_o;
           count++;
           break;
         case 'p':
-          response.body.properties[i].ref = handle_p;
+          obj.properties[i].ref = handle_p;
           count++;
           break;
       }
     }
     assertEquals(2, count, 'Either "o" or "p" not found');
-    response = lookupRequest(dcp, '{"handle":' + handle_p + '}', true);
-    assertEquals(handle_p, response.body.handle);
+    response = lookupRequest(dcp, '{"handles":[' + handle_p + ']}', true);
+    obj = response.body[handle_p];
+    assertTrue(!!obj, 'Object not found: ' + handle_p);
+    assertEquals(handle_p, obj.handle);
 
     // Check handles for functions on the stack.
     var handle_f = evaluateRequest(dcp, '{"expression":"f"}');
@@ -136,28 +140,31 @@
     assertFalse(handle_f == handle_g, "f and g have he same handle");
     assertEquals(handle_g, handle_caller, "caller for f should be g");
 
-    response = lookupRequest(dcp, '{"handle":' + handle_f + '}', true);
-    assertEquals(handle_f, response.body.handle);
+    response = lookupRequest(dcp, '{"handles":[' + handle_f + ']}', true);
+    obj = response.body[handle_f];
+    assertEquals(handle_f, obj.handle);
+
     count = 0;
-    for (i in response.body.properties) {
-      var arguments = '{"handle":' + response.body.properties[i].ref + '}'
-      switch (response.body.properties[i].name) {
+    for (i in obj.properties) {
+      var ref = obj.properties[i].ref;
+      var arguments = '{"handles":[' + ref + ']}';
+      switch (obj.properties[i].name) {
         case 'name':
           var response_name;
           response_name = lookupRequest(dcp, arguments, true);
-          assertEquals('string', response_name.body.type);
-          assertEquals("f", response_name.body.value);
+          assertEquals('string', response_name.body[ref].type);
+          assertEquals("f", response_name.body[ref].value);
           count++;
           break;
         case 'length':
           var response_length;
           response_length = lookupRequest(dcp, arguments, true);
-          assertEquals('number', response_length.body.type);
-          assertEquals(1, response_length.body.value);
+          assertEquals('number', response_length.body[ref].type);
+          assertEquals(1, response_length.body[ref].value);
           count++;
           break;
         case 'caller':
-          assertEquals(handle_g, response.body.properties[i].ref);
+          assertEquals(handle_g, obj.properties[i].ref);
           count++;
           break;
       }
@@ -165,6 +172,49 @@
     assertEquals(3, count, 'Either "name", "length" or "caller" not found');
 
 
+    // Resolve all at once.
+    var refs = [];
+    for (i in obj.properties) {
+      refs.push(obj.properties[i].ref);
+    }
+
+    var arguments = '{"handles":[' + refs.join(',') + ']}';
+    response = lookupRequest(dcp, arguments, true);
+    count = 0;
+    for (i in obj.properties) {
+      var ref = obj.properties[i].ref;
+      var val = response.body[ref];
+      assertTrue(!!val, 'Failed to lookup "' + obj.properties[i].name + '"');
+      switch (obj.properties[i].name) {
+        case 'name':
+          assertEquals('string', val.type);
+          assertEquals("f", val.value);
+          count++;
+          break;
+        case 'length':
+          assertEquals('number', val.type);
+          assertEquals(1, val.value);
+          count++;
+          break;
+        case 'caller':
+          assertEquals('function', val.type);
+          assertEquals(handle_g, ref);
+          count++;
+          break;
+      }
+    }
+    assertEquals(3, count, 'Either "name", "length" or "caller" not found');
+
+    count = 0;
+    for (var handle in response.body) {
+      assertTrue(refs.indexOf(parseInt(handle)) != -1,
+                 'Handle not in the request: ' + handle);
+      count++;
+    }
+    assertEquals(count, obj.properties.length, 
+                 'Unexpected number of resolved objects');
+
+
     // Indicate that all was processed.
     listenerComplete = true;
   }
@@ -195,5 +245,5 @@
 g(o);
 
 // Make sure that the debug event listener vas invoked.
-assertTrue(listenerComplete, "listener did not run to completion");
+assertTrue(listenerComplete, "listener did not run to completion: " + exception);
 assertFalse(exception, "exception in listener")
diff --git a/test/mjsunit/debug-setbreakpoint.js b/test/mjsunit/debug-setbreakpoint.js
index 904ec18..f8d9b15 100644
--- a/test/mjsunit/debug-setbreakpoint.js
+++ b/test/mjsunit/debug-setbreakpoint.js
@@ -54,14 +54,14 @@
   var json_response = dcp.processDebugJSONRequest(request);
   var response = safeEval(json_response);
   if (success) {
-    assertTrue(response.success, json_response);
+    assertTrue(response.success, request + ' -> ' + json_response);
     if (is_script) {
-      assertEquals('scriptName', response.body.type, json_response);
+      assertEquals('scriptName', response.body.type, request + ' -> ' + json_response);
     } else {
-      assertEquals('scriptId', response.body.type, json_response);
+      assertEquals('scriptId', response.body.type, request + ' -> ' + json_response);
     }
   } else {
-    assertFalse(response.success, json_response);
+    assertFalse(response.success, request + ' -> ' + json_response);
   }
 }
 
@@ -75,6 +75,8 @@
     var request = '{' + base_request + '}'
     var response = safeEval(dcp.processDebugJSONRequest(request));
     assertFalse(response.success);
+    
+    var mirror;
 
     testArguments(dcp, '{}', false);
     testArguments(dcp, '{"type":"xx"}', false);
@@ -86,6 +88,9 @@
     testArguments(dcp, '{"type":"function","target":"f","line":-1}', false);
     testArguments(dcp, '{"type":"function","target":"f","column":-1}', false);
     testArguments(dcp, '{"type":"function","target":"f","ignoreCount":-1}', false);
+    testArguments(dcp, '{"type":"handle","target":"-1"}', false);
+    mirror = debug.MakeMirror(o);
+    testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', false);
 
     // Test some legal setbreakpoint requests.
     testArguments(dcp, '{"type":"function","target":"f"}', true, false);
@@ -106,6 +111,11 @@
     testArguments(dcp, '{"type":"scriptId","target":' + g_script_id + ',"line":' + g_line + '}', true, false);
     testArguments(dcp, '{"type":"scriptId","target":' + h_script_id + ',"line":' + h_line + '}', true, false);
 
+    mirror = debug.MakeMirror(f);
+    testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', true, false);
+    mirror = debug.MakeMirror(o.a);
+    testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', true, false);
+
     // Indicate that all was processed.
     listenerComplete = true;
   }
@@ -127,6 +137,8 @@
 
 eval('function h(){}');
 
+o = {a:function(){},b:function(){}}
+
 // Check the script ids for the test functions.
 f_script_id = Debug.findScript(f).id;
 g_script_id = Debug.findScript(g).id;
diff --git a/test/mjsunit/enumeration-order.js b/test/mjsunit/enumeration-order.js
index 699a636..a328121 100644
--- a/test/mjsunit/enumeration-order.js
+++ b/test/mjsunit/enumeration-order.js
@@ -26,17 +26,17 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 function check_enumeration_order(obj)  {
-  var value = 0; 
+  var value = 0;
   for (var name in obj) assertTrue(value < obj[name]);
   value = obj[name];
 }
 
 function make_object(size)  {
   var a = new Object();
-  
+
   for (var i = 0; i < size; i++) a["a_" + i] = i + 1;
   check_enumeration_order(a);
-  
+
   for (var i = 0; i < size; i +=3) delete a["a_" + i];
   check_enumeration_order(a);
 }
@@ -51,9 +51,59 @@
   code += "a_" + (size - 1) + " : " + size;
   code += " }";
   eval("var a = " + code);
-  check_enumeration_order(a);  
+  check_enumeration_order(a);
 }
 
-// Validate the enumeration order for object literals up to 100 named properties.
+// Validate the enumeration order for object literals up to 100 named
+// properties.
 for (var j = 1; j< 100; j++) make_literal_object(j);
 
+// We enumerate indexed properties in numerical order followed by
+// named properties in insertion order, followed by indexed properties
+// of the prototype object in numerical order, followed by named
+// properties of the prototype object in insertion order, and so on.
+//
+// This enumeration order is not required by the specification, so
+// this just documents our choice.
+var proto2 = {};
+proto2[140000] = 0;
+proto2.a = 0;
+proto2[2] = 0;
+proto2[3] = 0;  // also on the 'proto1' object
+proto2.b = 0;
+proto2[4294967295] = 0;
+proto2.c = 0;
+proto2[4294967296] = 0;
+
+var proto1 = {};
+proto1[5] = 0;
+proto1.d = 0;
+proto1[3] = 0;
+proto1.e = 0;
+proto1.f = 0;  // also on the 'o' object
+
+var o = {};
+o[-23] = 0;
+o[300000000000] = 0;
+o[23] = 0;
+o.f = 0;
+o.g = 0;
+o[-4] = 0;
+o[42] = 0;
+
+o.__proto__ = proto1;
+proto1.__proto__ = proto2;
+
+var expected = ['23', '42',  // indexed from 'o'
+                '-23', '300000000000', 'f', 'g', '-4',  // named from 'o'
+                '3', '5',  // indexed from 'proto1'
+                'd', 'e',  // named from 'proto1'
+                '2', '140000', '4294967295',  // indexed from 'proto2'
+                'a', 'b', 'c', '4294967296'];  // named from 'proto2'
+var actual = [];
+for (var p in o) actual.push(p);
+assertArrayEquals(expected, actual);
+
+
+
+
diff --git a/test/mjsunit/eval-enclosing-function-name.js b/test/mjsunit/eval-enclosing-function-name.js
new file mode 100644
index 0000000..422f03f
--- /dev/null
+++ b/test/mjsunit/eval-enclosing-function-name.js
@@ -0,0 +1,76 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// From within 'eval', the name of the enclosing function should be
+// visible.
+
+var f = function y() { return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { return eval('typeof y'); };
+assertEquals("function", f());
+
+
+f = function y() { y = 3; return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { y += 3; return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { y &= y; return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { y = 3; return eval('typeof y'); }
+assertEquals("function", f());
+
+
+f = function y() { var y = 3; return typeof y; }
+assertEquals("number", f());
+
+
+f = function y() { var y = 3; return eval('typeof y'); }
+assertEquals("number", f());
+
+
+f = function y() { eval('y = 3'); return typeof y; }
+assertEquals("function", f());
+
+
+f = function y() { eval('y = 3'); return eval('typeof y'); }
+assertEquals("function", f());
+
+
+f = function y() { eval('var y = 3'); return typeof y; }
+assertEquals("number", f());
+
+
+f = function y() { eval('var y = 3'); return eval('typeof y'); }
+assertEquals("number", f());
diff --git a/test/mjsunit/keyed-ic.js b/test/mjsunit/keyed-ic.js
index d37bd03..a6726ed 100644
--- a/test/mjsunit/keyed-ic.js
+++ b/test/mjsunit/keyed-ic.js
@@ -145,6 +145,35 @@
 
 
 // ----------------------------------------------------------------------
+// Indexed access.
+// ----------------------------------------------------------------------
+runTest = function() {
+  var o = [ 42, 43 ];
+
+  var initial_X = 0;
+  var X = initial_X;
+  var Y = 1;
+
+  function fieldTest(change_index) {
+    for (var i = 0; i < 10; i++) {
+      var property = o[X];
+      if (i <= change_index) {
+        assertEquals(42, property);
+      } else {
+        assertEquals(43, property);
+      }
+      if (i == change_index) X = Y;
+    }
+    X = initial_X;
+  };
+
+  for (var i = 0; i < 10; i++) fieldTest(i);
+}
+
+runTest();
+
+
+// ----------------------------------------------------------------------
 // Constant function access.
 // ----------------------------------------------------------------------
 runTest = function() {
diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js
index 3570d68..320e8d1 100644
--- a/test/mjsunit/mjsunit.js
+++ b/test/mjsunit/mjsunit.js
@@ -53,6 +53,9 @@
 
 function deepEquals(a, b) {
   if (a == b) return true;
+  if (typeof a == "number" && typeof b == "number" && isNaN(a) && isNaN(b)) {
+    return true;
+  }
   if ((typeof a) !== 'object' || (typeof b) !== 'object' ||
       (a === null) || (b === null))
     return false;
@@ -113,6 +116,20 @@
 }
 
 
+function assertNull(value, name_opt) {
+  if (value !== null) {
+    fail("null", value, name_opt);
+  }
+}
+
+
+function assertNotNull(value, name_opt) {
+  if (value === null) {
+    fail("not null", value, name_opt);
+  }
+}
+
+
 function assertThrows(code) {
   var threwException = true;
   try {
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 5a76078..4bb7c16 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -48,19 +48,19 @@
 # Bug number 1020483: Debug tests fail on ARM.
 debug-constructor: CRASH, FAIL
 debug-continue: SKIP
-debug-evaluate-recursive: CRASH, FAIL if $mode == debug
-debug-changebreakpoint: CRASH, FAIL if $mode == debug
-debug-clearbreakpoint: CRASH, FAIL if $mode == debug
-debug-conditional-breakpoints: CRASH, FAIL if $mode == debug
-debug-evaluate: CRASH, FAIL if $mode == debug
-debug-ignore-breakpoints: CRASH, FAIL if $mode == debug
-debug-multiple-breakpoints: CRASH, FAIL if $mode == debug
-debug-setbreakpoint: CRASH, FAIL if $mode == debug
+debug-evaluate-recursive: CRASH || FAIL
+debug-changebreakpoint: CRASH || FAIL
+debug-clearbreakpoint: CRASH || FAIL
+debug-conditional-breakpoints: FAIL
+debug-evaluate: CRASH || FAIL
+debug-ignore-breakpoints: CRASH || FAIL
+debug-multiple-breakpoints: CRASH || FAIL
+debug-setbreakpoint: CRASH || FAIL || PASS
 debug-step-stub-callfunction: SKIP
 debug-stepin-constructor: CRASH, FAIL
 debug-step: SKIP
 debug-breakpoints: PASS || FAIL
-debug-handle: CRASH, FAIL if $mode == debug
+debug-handle: CRASH || FAIL || PASS
 regress/regress-269: SKIP
 
 # Bug number 130 http://code.google.com/p/v8/issues/detail?id=130
diff --git a/test/mjsunit/negate.js b/test/mjsunit/negate.js
index 3bf4111..70daf24 100644
--- a/test/mjsunit/negate.js
+++ b/test/mjsunit/negate.js
@@ -30,9 +30,9 @@
 
 function testmulneg(a, b) {
   var base = a * b;
-  assertEquals(-base, a * -b);
-  assertEquals(-base, -a * b);
-  assertEquals(base, -a * -b);
+  assertEquals(-base, a * -b, "a * -b where a = " + a + ", b = " + b);
+  assertEquals(-base, -a * b, "-a * b where a = " + a + ", b = " + b);
+  assertEquals(base, -a * -b, "*-a * -b where a = " + a + ", b = " + b);
 }
 
 testmulneg(2, 3);
diff --git a/test/mjsunit/number-limits.js b/test/mjsunit/number-limits.js
index 1d9a1e5..99ed4e1 100644
--- a/test/mjsunit/number-limits.js
+++ b/test/mjsunit/number-limits.js
@@ -33,10 +33,14 @@
     var addAboveMax = Number.MAX_VALUE + 1/eps;
     var mulBelowMin = Number.MIN_VALUE * (1 - eps);
     var addBelowMin = Number.MIN_VALUE - eps;
-    assertTrue(mulAboveMax == Number.MAX_VALUE || mulAboveMax == Infinity);
-    assertTrue(addAboveMax == Number.MAX_VALUE || addAboveMax == Infinity);
-    assertTrue(mulBelowMin == Number.MIN_VALUE || mulBelowMin <= 0);
-    assertTrue(addBelowMin == Number.MIN_VALUE || addBelowMin <= 0);
+    assertTrue(mulAboveMax == Number.MAX_VALUE ||
+               mulAboveMax == Infinity, "mul" + i);
+    assertTrue(addAboveMax == Number.MAX_VALUE ||
+               addAboveMax == Infinity, "add" + i);
+    assertTrue(mulBelowMin == Number.MIN_VALUE ||
+               mulBelowMin <= 0, "mul2" + i);
+    assertTrue(addBelowMin == Number.MIN_VALUE ||
+               addBelowMin <= 0, "add2" + i);
   }
 }
 
diff --git a/test/mjsunit/receiver-in-with-calls.js b/test/mjsunit/receiver-in-with-calls.js
new file mode 100644
index 0000000..5f2bdac
--- /dev/null
+++ b/test/mjsunit/receiver-in-with-calls.js
@@ -0,0 +1,47 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// When invoking functions from within a 'with' statement, we must set
+// the receiver to the object where we found the function.
+
+(function () {
+  var x = { get_this: function() { return this; } };
+  assertTrue(x === x.get_this());
+  with (x) assertTrue(x === get_this());
+})();
+
+
+assertTrue({ f: function() {
+  function g() { return this; };
+  return eval("g")();
+} }.f() == this);
+
+
+assertTrue({ f: function() {
+  function g() { return this; };
+  return eval("g()");
+} }.f() == this);
diff --git a/test/mjsunit/regexp-multiline-stack-trace.js b/test/mjsunit/regexp-multiline-stack-trace.js
index aa2de88..fc248ef 100644
--- a/test/mjsunit/regexp-multiline-stack-trace.js
+++ b/test/mjsunit/regexp-multiline-stack-trace.js
@@ -25,6 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// The flags below are to test the trace-calls functionality and the
+// preallocated meessage memory.
 // Flags: --trace-calls --preallocate-message-memory
 
 /**
diff --git a/test/mjsunit/regress/regress-318.js b/test/mjsunit/regress/regress-318.js
index 9e00b5f..e94f1cb 100644
--- a/test/mjsunit/regress/regress-318.js
+++ b/test/mjsunit/regress/regress-318.js
@@ -25,11 +25,11 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Should not raise an exception.
+// Should not crash or raise an exception.
 
 function test(value) {
   if (typeof(value) == 'boolean') value = value + '';
   if (typeof(value) == 'number') value = value + '';
 }
 
-assertDoesNotThrow(test(0));
+assertDoesNotThrow('test(0)');
diff --git a/test/mjsunit/smi-ops.js b/test/mjsunit/smi-ops.js
index bdd7509..80d2012 100644
--- a/test/mjsunit/smi-ops.js
+++ b/test/mjsunit/smi-ops.js
@@ -100,3 +100,98 @@
 assertEquals(ONE_HUNDRED - SMI_MIN, Sub100Reversed(SMI_MIN));  // overflow
 assertEquals(42 - ONE_HUNDRED, Sub100(OBJ_42));  // non-smi
 assertEquals(ONE_HUNDRED - 42, Sub100Reversed(OBJ_42));  // non-smi
+
+
+function Shr1(x) {
+  return x >>> 1;
+}
+
+function Shr100(x) {
+  return x >>> 100;
+}
+
+function Shr1Reversed(x) {
+  return 1 >>> x;
+}
+
+function Shr100Reversed(x) {
+  return 100 >>> x;
+}
+
+function Sar1(x) {
+  return x >> 1;
+}
+
+function Sar100(x) {
+  return x >> 100;
+}
+
+function Sar1Reversed(x) {
+  return 1 >> x;
+}
+
+function Sar100Reversed(x) {
+  return 100 >> x;
+}
+
+
+assertEquals(0, Shr1(1));
+assertEquals(0, Sar1(1));
+assertEquals(0, Shr1Reversed(2));
+assertEquals(0, Sar1Reversed(2));
+assertEquals(1610612736, Shr1(SMI_MIN));
+assertEquals(-536870912, Sar1(SMI_MIN));
+assertEquals(1, Shr1Reversed(SMI_MIN));
+assertEquals(1, Sar1Reversed(SMI_MIN));
+assertEquals(21, Shr1(OBJ_42));
+assertEquals(21, Sar1(OBJ_42));
+assertEquals(0, Shr1Reversed(OBJ_42));
+assertEquals(0, Sar1Reversed(OBJ_42));
+
+assertEquals(6, Shr100(100));
+assertEquals(6, Sar100(100));
+assertEquals(12, Shr100Reversed(99));
+assertEquals(12, Sar100Reversed(99));
+assertEquals(201326592, Shr100(SMI_MIN));
+assertEquals(-67108864, Sar100(SMI_MIN));
+assertEquals(100, Shr100Reversed(SMI_MIN));
+assertEquals(100, Sar100Reversed(SMI_MIN));
+assertEquals(2, Shr100(OBJ_42));
+assertEquals(2, Sar100(OBJ_42));
+assertEquals(0, Shr100Reversed(OBJ_42));
+assertEquals(0, Sar100Reversed(OBJ_42));
+
+
+function Xor1(x) {
+  return x ^ 1;
+}
+
+function Xor100(x) {
+  return x ^ 100;
+}
+
+function Xor1Reversed(x) {
+  return 1 ^ x;
+}
+
+function Xor100Reversed(x) {
+  return 100 ^ x;
+}
+
+
+assertEquals(0, Xor1(1));
+assertEquals(3, Xor1Reversed(2));
+assertEquals(SMI_MIN + 1, Xor1(SMI_MIN));
+assertEquals(SMI_MIN + 1, Xor1Reversed(SMI_MIN));
+assertEquals(43, Xor1(OBJ_42));
+assertEquals(43, Xor1Reversed(OBJ_42));
+
+assertEquals(0, Xor100(100));
+assertEquals(7, Xor100Reversed(99));
+assertEquals(-1073741724, Xor100(SMI_MIN));
+assertEquals(-1073741724, Xor100Reversed(SMI_MIN));
+assertEquals(78, Xor100(OBJ_42));
+assertEquals(78, Xor100Reversed(OBJ_42));
+
+var x = 0x23; var y = 0x35;
+assertEquals(0x16, x ^ y);
diff --git a/test/mjsunit/tools/codemap.js b/test/mjsunit/tools/codemap.js
new file mode 100644
index 0000000..7f344a6
--- /dev/null
+++ b/test/mjsunit/tools/codemap.js
@@ -0,0 +1,116 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load Splay tree and CodeMap implementations from <project root>/tools.
+// Files: tools/splaytree.js tools/codemap.js
+
+
+function newCodeEntry(size, name) {
+  return new devtools.profiler.CodeMap.CodeEntry(size, name);
+};
+
+
+function assertEntry(codeMap, expected_name, addr) {
+  var entry = codeMap.findEntry(addr);
+  assertNotNull(entry, 'no entry at ' + addr.toString(16));
+  assertEquals(expected_name, entry.name, 'at ' + addr.toString(16));
+};
+
+
+function assertNoEntry(codeMap, addr) {
+  assertNull(codeMap.findEntry(addr), 'at ' + addr.toString(16));
+};
+
+
+(function testStaticCode() {
+  var codeMap = new devtools.profiler.CodeMap();
+  codeMap.addStaticCode(0x1500, newCodeEntry(0x3000, 'lib1'));
+  codeMap.addStaticCode(0x15500, newCodeEntry(0x5000, 'lib2'));
+  codeMap.addStaticCode(0x155500, newCodeEntry(0x10000, 'lib3'));
+  assertNoEntry(codeMap, 0);
+  assertNoEntry(codeMap, 0x1500 - 1);
+  assertEntry(codeMap, 'lib1', 0x1500);
+  assertEntry(codeMap, 'lib1', 0x1500 + 0x100);
+  assertEntry(codeMap, 'lib1', 0x1500 + 0x1000);
+  assertEntry(codeMap, 'lib1', 0x1500 + 0x3000 - 1);
+  assertNoEntry(codeMap, 0x1500 + 0x3000);
+  assertNoEntry(codeMap, 0x15500 - 1);
+  assertEntry(codeMap, 'lib2', 0x15500);
+  assertEntry(codeMap, 'lib2', 0x15500 + 0x100);
+  assertEntry(codeMap, 'lib2', 0x15500 + 0x1000);
+  assertEntry(codeMap, 'lib2', 0x15500 + 0x5000 - 1);
+  assertNoEntry(codeMap, 0x15500 + 0x5000);
+  assertNoEntry(codeMap, 0x155500 - 1);
+  assertEntry(codeMap, 'lib3', 0x155500);
+  assertEntry(codeMap, 'lib3', 0x155500 + 0x100);
+  assertEntry(codeMap, 'lib3', 0x155500 + 0x1000);
+  assertEntry(codeMap, 'lib3', 0x155500 + 0x10000 - 1);
+  assertNoEntry(codeMap, 0x155500 + 0x10000);
+  assertNoEntry(codeMap, 0xFFFFFFFF);
+})();
+
+
+(function testDynamicCode() {
+  var codeMap = new devtools.profiler.CodeMap();
+  codeMap.addCode(0x1500, newCodeEntry(0x200, 'code1'));
+  codeMap.addCode(0x1700, newCodeEntry(0x100, 'code2'));
+  codeMap.addCode(0x1900, newCodeEntry(0x50, 'code3'));
+  codeMap.addCode(0x1950, newCodeEntry(0x10, 'code4'));
+  assertNoEntry(codeMap, 0);
+  assertNoEntry(codeMap, 0x1500 - 1);
+  assertEntry(codeMap, 'code1', 0x1500);
+  assertEntry(codeMap, 'code1', 0x1500 + 0x100);
+  assertEntry(codeMap, 'code1', 0x1500 + 0x200 - 1);
+  assertEntry(codeMap, 'code2', 0x1700);
+  assertEntry(codeMap, 'code2', 0x1700 + 0x50);
+  assertEntry(codeMap, 'code2', 0x1700 + 0x100 - 1);
+  assertNoEntry(codeMap, 0x1700 + 0x100);
+  assertNoEntry(codeMap, 0x1900 - 1);
+  assertEntry(codeMap, 'code3', 0x1900);
+  assertEntry(codeMap, 'code3', 0x1900 + 0x28);
+  assertEntry(codeMap, 'code4', 0x1950);
+  assertEntry(codeMap, 'code4', 0x1950 + 0x7);
+  assertEntry(codeMap, 'code4', 0x1950 + 0x10 - 1);
+  assertNoEntry(codeMap, 0x1950 + 0x10);
+  assertNoEntry(codeMap, 0xFFFFFFFF);
+})();
+
+
+(function testCodeMovesAndDeletions() {
+  var codeMap = new devtools.profiler.CodeMap();
+  codeMap.addCode(0x1500, newCodeEntry(0x200, 'code1'));
+  codeMap.addCode(0x1700, newCodeEntry(0x100, 'code2'));
+  assertEntry(codeMap, 'code1', 0x1500);
+  assertEntry(codeMap, 'code2', 0x1700);
+  codeMap.moveCode(0x1500, 0x1800);
+  assertNoEntry(codeMap, 0x1500);
+  assertEntry(codeMap, 'code2', 0x1700);
+  assertEntry(codeMap, 'code1', 0x1800);
+  codeMap.deleteCode(0x1700);
+  assertNoEntry(codeMap, 0x1700);
+  assertEntry(codeMap, 'code1', 0x1800);
+})();
diff --git a/test/mjsunit/tools/csvparser.js b/test/mjsunit/tools/csvparser.js
new file mode 100644
index 0000000..db3a2eb
--- /dev/null
+++ b/test/mjsunit/tools/csvparser.js
@@ -0,0 +1,79 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load CSV parser implementation from <project root>/tools.
+// Files: tools/csvparser.js
+
+var parser = new devtools.profiler.CsvParser();
+
+assertEquals(
+    [],
+    parser.parseLine(''));
+
+assertEquals(
+    ['', ''],
+    parser.parseLine(','));
+
+assertEquals(
+    ['1997','Ford','E350'],
+    parser.parseLine('1997,Ford,E350'));
+
+assertEquals(
+    ['1997','Ford','E350'],
+    parser.parseLine('"1997","Ford","E350"'));
+
+assertEquals(
+    ['1997','Ford','E350','Super, luxurious truck'],
+    parser.parseLine('1997,Ford,E350,"Super, luxurious truck"'));
+
+assertEquals(
+    ['1997','Ford','E350','Super "luxurious" truck'],
+    parser.parseLine('1997,Ford,E350,"Super ""luxurious"" truck"'));
+
+assertEquals(
+    ['1997','Ford','E350','Super "luxurious" "truck"'],
+    parser.parseLine('1997,Ford,E350,"Super ""luxurious"" ""truck"""'));
+
+assertEquals(
+    ['1997','Ford','E350','Super "luxurious""truck"'],
+    parser.parseLine('1997,Ford,E350,"Super ""luxurious""""truck"""'));
+
+assertEquals(
+    ['shared-library','/lib/ld-2.3.6.so','0x489a2000','0x489b7000'],
+    parser.parseLine('shared-library,"/lib/ld-2.3.6.so",0x489a2000,0x489b7000'));
+
+assertEquals(
+    ['code-creation','LazyCompile','0xf6fe2d20','1201','APPLY_PREPARE native runtime.js:165'],
+    parser.parseLine('code-creation,LazyCompile,0xf6fe2d20,1201,"APPLY_PREPARE native runtime.js:165"'));
+
+assertEquals(
+    ['code-creation','LazyCompile','0xf6fe4bc0','282',' native v8natives.js:69'],
+    parser.parseLine('code-creation,LazyCompile,0xf6fe4bc0,282," native v8natives.js:69"'));
+
+assertEquals(
+    ['code-creation','RegExp','0xf6c21c00','826','NccyrJroXvg\\/([^,]*)'],
+    parser.parseLine('code-creation,RegExp,0xf6c21c00,826,"NccyrJroXvg\\/([^,]*)"'));
diff --git a/test/mjsunit/tools/profile.js b/test/mjsunit/tools/profile.js
new file mode 100644
index 0000000..87ec8fa
--- /dev/null
+++ b/test/mjsunit/tools/profile.js
@@ -0,0 +1,283 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load source code files from <project root>/tools.
+// Files: tools/splaytree.js tools/codemap.js tools/profile.js
+
+
+function stackToString(stack) {
+  return stack.join(' -> ');
+};
+
+
+function assertPathExists(root, path, opt_message) {
+  var message = opt_message ? ' (' + opt_message + ')' : '';
+  assertNotNull(root.descendToChild(path, function(node, pos) {
+    assertNotNull(node,
+      stackToString(path.slice(0, pos)) + ' has no child ' +
+                    path[pos] + message);
+  }), opt_message);
+};
+
+
+function assertNoPathExists(root, path, opt_message) {
+  var message = opt_message ? ' (' + opt_message + ')' : '';
+  assertNull(root.descendToChild(path), opt_message);
+};
+
+
+function countNodes(profile, traverseFunc) {
+  var count = 0;
+  traverseFunc.call(profile, function () { count++; });
+  return count;
+};
+
+
+function ProfileTestDriver() {
+  this.profile = new devtools.profiler.Profile();
+  this.stack_ = [];
+  this.addFunctions_();
+};
+
+
+// Addresses inside functions.
+ProfileTestDriver.prototype.funcAddrs_ = {
+    'lib1-f1': 0x11110, 'lib1-f2': 0x11210,
+    'lib2-f1': 0x21110, 'lib2-f2': 0x21210,
+    'T: F1': 0x50110, 'T: F2': 0x50210, 'T: F3': 0x50410 };
+
+
+ProfileTestDriver.prototype.addFunctions_ = function() {
+  this.profile.addStaticCode('lib1', 0x11000, 0x12000);
+  this.profile.addStaticCode('lib1-f1', 0x11100, 0x11900);
+  this.profile.addStaticCode('lib1-f2', 0x11200, 0x11500);
+  this.profile.addStaticCode('lib2', 0x21000, 0x22000);
+  this.profile.addStaticCode('lib2-f1', 0x21100, 0x21900);
+  this.profile.addStaticCode('lib2-f2', 0x21200, 0x21500);
+  this.profile.addCode('T', 'F1', 0x50100, 0x100);
+  this.profile.addCode('T', 'F2', 0x50200, 0x100);
+  this.profile.addCode('T', 'F3', 0x50400, 0x100);
+};
+
+
+ProfileTestDriver.prototype.enter = function(funcName) {
+  // Stack looks like this: [pc, caller, ..., main].
+  // Therefore, we are adding entries at the beginning.
+  this.stack_.unshift(this.funcAddrs_[funcName]);
+  this.profile.recordTick(this.stack_);
+};
+
+
+ProfileTestDriver.prototype.stay = function() {
+  this.profile.recordTick(this.stack_);
+};
+
+
+ProfileTestDriver.prototype.leave = function() {
+  this.stack_.shift();
+};
+
+
+ProfileTestDriver.prototype.execute = function() {
+  this.enter('lib1-f1');
+    this.enter('lib1-f2');
+      this.enter('T: F1');
+        this.enter('T: F2');
+        this.leave();
+      this.stay();
+        this.enter('lib2-f1');
+          this.enter('lib2-f1');
+          this.leave();
+        this.stay();
+        this.leave();
+        this.enter('T: F3');
+          this.enter('T: F3');
+            this.enter('T: F3');
+            this.leave();
+            this.enter('T: F2');
+            this.stay();
+            this.leave();
+          this.leave();
+        this.leave();
+      this.leave();
+    this.stay();
+  this.leave();
+};
+
+
+function Inherits(childCtor, parentCtor) {
+  function tempCtor() {};
+  tempCtor.prototype = parentCtor.prototype;
+  childCtor.superClass_ = parentCtor.prototype;
+  childCtor.prototype = new tempCtor();
+  childCtor.prototype.constructor = childCtor;
+};
+
+
+(function testCallTreeBuilding() {
+  function Driver() {
+    ProfileTestDriver.call(this);
+    this.namesTopDown = [];
+    this.namesBottomUp = [];
+  };
+  Inherits(Driver, ProfileTestDriver);
+
+  Driver.prototype.enter = function(func) {
+    this.namesTopDown.push(func);
+    this.namesBottomUp.unshift(func);
+    assertNoPathExists(this.profile.getTopDownTreeRoot(), this.namesTopDown,
+        'pre enter/topDown');
+    assertNoPathExists(this.profile.getBottomUpTreeRoot(), this.namesBottomUp,
+        'pre enter/bottomUp');
+    Driver.superClass_.enter.call(this, func);
+    assertPathExists(this.profile.getTopDownTreeRoot(), this.namesTopDown,
+        'post enter/topDown');
+    assertPathExists(this.profile.getBottomUpTreeRoot(), this.namesBottomUp,
+        'post enter/bottomUp');
+  };
+
+  Driver.prototype.stay = function() {
+    var preTopDownNodes = countNodes(this.profile, this.profile.traverseTopDownTree);
+    var preBottomUpNodes = countNodes(this.profile, this.profile.traverseBottomUpTree);
+    Driver.superClass_.stay.call(this);
+    var postTopDownNodes = countNodes(this.profile, this.profile.traverseTopDownTree);
+    var postBottomUpNodes = countNodes(this.profile, this.profile.traverseBottomUpTree);
+    // Must be no changes in tree layout.
+    assertEquals(preTopDownNodes, postTopDownNodes, 'stay/topDown');
+    assertEquals(preBottomUpNodes, postBottomUpNodes, 'stay/bottomUp');
+  };
+
+  Driver.prototype.leave = function() {
+    Driver.superClass_.leave.call(this);
+    this.namesTopDown.pop();
+    this.namesBottomUp.shift();
+  };
+
+  var testDriver = new Driver();
+  testDriver.execute();
+})();
+
+
+function assertNodeWeights(root, path, selfTicks, totalTicks) {
+  var node = root.descendToChild(path);
+  var stack = stackToString(path);
+  assertNotNull(node, 'node not found: ' + stack);
+  assertEquals(selfTicks, node.selfWeight, 'self of ' + stack);
+  assertEquals(totalTicks, node.totalWeight, 'total of ' + stack);
+};
+
+
+(function testTopDownRootProfileTicks() {
+  var testDriver = new ProfileTestDriver();
+  testDriver.execute();
+
+  var pathWeights = [
+    [['lib1-f1'], 1, 14],
+    [['lib1-f1', 'lib1-f2'], 2, 13],
+    [['lib1-f1', 'lib1-f2', 'T: F1'], 2, 11],
+    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F2'], 1, 1],
+    [['lib1-f1', 'lib1-f2', 'T: F1', 'lib2-f1'], 2, 3],
+    [['lib1-f1', 'lib1-f2', 'T: F1', 'lib2-f1', 'lib2-f1'], 1, 1],
+    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3'], 1, 5],
+    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3'], 1, 4],
+    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3', 'T: F3'], 1, 1],
+    [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3', 'T: F2'], 2, 2]
+  ];
+
+  var root = testDriver.profile.getTopDownTreeRoot();
+  for (var i = 0; i < pathWeights.length; ++i) {
+    var data = pathWeights[i];
+    assertNodeWeights(root, data[0], data[1], data[2]);
+  }
+})();
+
+
+(function testRootFlatProfileTicks() {
+  function Driver() {
+    ProfileTestDriver.call(this);
+    this.namesTopDown = [''];
+    this.counters = {};
+  };
+  Inherits(Driver, ProfileTestDriver);
+
+  Driver.prototype.increment = function(func, self, total) {
+    if (!(func in this.counters)) {
+      this.counters[func] = { self: 0, total: 0 };
+    }
+    this.counters[func].self += self;
+    this.counters[func].total += total;
+  };
+
+  Driver.prototype.incrementTotals = function() {
+    // Only count each function in the stack once.
+    var met = {};
+    for (var i = 0; i < this.namesTopDown.length; ++i) {
+      var name = this.namesTopDown[i];
+      if (!(name in met)) {
+        this.increment(name, 0, 1);
+      }
+      met[name] = true;
+    }
+  };
+
+  Driver.prototype.enter = function(func) {
+    Driver.superClass_.enter.call(this, func);
+    this.namesTopDown.push(func);
+    this.increment(func, 1, 0);
+    this.incrementTotals();
+  };
+
+  Driver.prototype.stay = function() {
+    Driver.superClass_.stay.call(this);
+    this.increment(this.namesTopDown[this.namesTopDown.length - 1], 1, 0);
+    this.incrementTotals();
+  };
+
+  Driver.prototype.leave = function() {
+    Driver.superClass_.leave.call(this);
+    this.namesTopDown.pop();
+  };
+
+  var testDriver = new Driver();
+  testDriver.execute();
+
+  var counted = 0;
+  for (var c in testDriver.counters) {
+    counted++;
+  }
+
+  var flatProfile = testDriver.profile.getFlatProfile();
+  assertEquals(counted, flatProfile.length, 'counted vs. flatProfile');
+  for (var i = 0; i < flatProfile.length; ++i) {
+    var rec = flatProfile[i];
+    assertTrue(rec.label in testDriver.counters, 'uncounted: ' + rec.label);
+    var reference = testDriver.counters[rec.label];
+    assertEquals(reference.self, rec.selfWeight, 'self of ' + rec.label);
+    assertEquals(reference.total, rec.totalWeight, 'total of ' + rec.label);
+  }
+
+})();
diff --git a/tools/codemap.js b/tools/codemap.js
new file mode 100644
index 0000000..5149cfc
--- /dev/null
+++ b/tools/codemap.js
@@ -0,0 +1,210 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Constructs a mapper that maps addresses into code entries.
+ *
+ * @constructor
+ */
+devtools.profiler.CodeMap = function() {
+  /**
+   * Dynamic code entries. Used for JIT compiled code.
+   */
+  this.dynamics_ = new goog.structs.SplayTree();
+
+  /**
+   * Deleted code entries. Used for code collected by the GC.
+   */
+  this.deleted_ = [];
+
+  /**
+   * Static code entries. Used for libraries code.
+   */
+  this.statics_ = new goog.structs.SplayTree();
+
+  /**
+   * Map of memory pages occupied with static code.
+   */
+  this.pages_ = [];
+};
+
+
+/**
+ * The number of alignment bits in a page address.
+ */
+devtools.profiler.CodeMap.PAGE_ALIGNMENT = 12;
+
+
+/**
+ * Page size in bytes.
+ */
+devtools.profiler.CodeMap.PAGE_SIZE =
+    1 << devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+
+
+/**
+ * Adds a dynamic (i.e. moveable and discardable) code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addCode = function(start, codeEntry) {
+  this.dynamics_.insert(start, codeEntry);
+};
+
+
+/**
+ * Moves a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} from The starting address of the entry being moved.
+ * @param {number} to The destination address.
+ */
+devtools.profiler.CodeMap.prototype.moveCode = function(from, to) {
+  var removedNode = this.dynamics_.remove(from);
+  this.dynamics_.insert(to, removedNode.value);
+};
+
+
+/**
+ * Discards a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address. The entry will still be
+ * returned from the 'getAllDynamicEntries' method.
+ *
+ * @param {number} start The starting address of the entry being deleted.
+ */
+devtools.profiler.CodeMap.prototype.deleteCode = function(start) {
+  var removedNode = this.dynamics_.remove(start);
+  this.deleted_.push(removedNode.value);
+};
+
+
+/**
+ * Adds a static code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addStaticCode = function(
+    start, codeEntry) {
+  this.markPages_(start, start + codeEntry.size);
+  this.statics_.insert(start, codeEntry);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.markPages_ = function(start, end) {
+  for (var addr = start; addr <= end;
+       addr += devtools.profiler.CodeMap.PAGE_SIZE) {
+    this.pages_[addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT] = 1;
+  }
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.isAddressBelongsTo_ = function(addr, node) {
+  return addr >= node.key && addr < (node.key + node.value.size);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.findInTree_ = function(tree, addr) {
+  var node = tree.findGreatestLessThan(addr);
+  return node && this.isAddressBelongsTo_(addr, node) ? node.value : null;
+};
+
+
+/**
+ * Finds a code entry that contains the specified address. Both static and
+ * dynamic code entries are considered.
+ *
+ * @param {number} addr Address.
+ */
+devtools.profiler.CodeMap.prototype.findEntry = function(addr) {
+  var pageAddr = addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+  if (pageAddr in this.pages_) {
+    return this.findInTree_(this.statics_, addr);
+  }
+  var min = this.dynamics_.findMin();
+  var max = this.dynamics_.findMax();
+  if (max != null && addr < (max.key + max.value.size) && addr >= min.key) {
+    return this.findInTree_(this.dynamics_, addr);
+  }
+  return null;
+};
+
+
+/**
+ * Returns an array of all dynamic code entries, including deleted ones.
+ */
+devtools.profiler.CodeMap.prototype.getAllDynamicEntries = function() {
+  var dynamicEntries = this.dynamics_.exportValues();
+  return dynamicEntries.concat(this.deleted_);
+};
+
+
+/**
+ * Returns an array of all static code entries.
+ */
+devtools.profiler.CodeMap.prototype.getAllStaticEntries = function() {
+  return this.statics_.exportValues();
+};
+
+
+/**
+ * Creates a code entry object.
+ *
+ * @param {number} size Code entry size in bytes.
+ * @param {string} opt_name Code entry name.
+ * @constructor
+ */
+devtools.profiler.CodeMap.CodeEntry = function(size, opt_name) {
+  this.size = size;
+  this.name = opt_name || '';
+};
+
+
+devtools.profiler.CodeMap.CodeEntry.prototype.getName = function() {
+  return this.name;
+};
+
+    
+devtools.profiler.CodeMap.CodeEntry.prototype.toString = function() {
+  return this.name + ': ' + this.size.toString(16);
+};
diff --git a/tools/csvparser.js b/tools/csvparser.js
new file mode 100644
index 0000000..9e58dea
--- /dev/null
+++ b/tools/csvparser.js
@@ -0,0 +1,98 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Initlialize namespaces.
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a CSV lines parser.
+ */
+devtools.profiler.CsvParser = function() {
+};
+
+
+/**
+ * A regex for matching a trailing quote.
+ * @private
+ */
+devtools.profiler.CsvParser.TRAILING_QUOTE_RE_ = /\"$/;
+
+
+/**
+ * A regex for matching a double quote.
+ * @private
+ */
+devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_ = /\"\"/g;
+
+
+/**
+ * Parses a line of CSV-encoded values. Returns an array of fields.
+ *
+ * @param {string} line Input line.
+ */
+devtools.profiler.CsvParser.prototype.parseLine = function(line) {
+  var insideQuotes = false;
+  var fields = [];
+  var prevPos = 0;
+  for (var i = 0, n = line.length; i < n; ++i) {
+    switch (line.charAt(i)) {
+      case ',':
+        if (!insideQuotes) {
+          fields.push(line.substring(prevPos, i));
+          prevPos = i + 1;
+        }
+        break;
+      case '"':
+        if (!insideQuotes) {
+          insideQuotes = true;
+          // Skip the leading quote.
+          prevPos++;
+        } else {
+          if (i + 1 < n && line.charAt(i + 1) != '"') {
+            insideQuotes = false;
+          } else {
+            i++;
+          }
+        }
+        break;
+    }
+  }
+  if (n > 0) {
+    fields.push(line.substring(prevPos));
+  }
+
+  for (i = 0; i < fields.length; ++i) {
+    // Eliminate trailing quotes.
+    fields[i] = fields[i].replace(devtools.profiler.CsvParser.TRAILING_QUOTE_RE_, '');
+    // Convert quoted quotes into single ones.
+    fields[i] = fields[i].replace(devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_, '"');
+  }
+  return fields;
+};
diff --git a/tools/profile.js b/tools/profile.js
new file mode 100644
index 0000000..e70d244
--- /dev/null
+++ b/tools/profile.js
@@ -0,0 +1,468 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a profile object for processing profiling-related events
+ * and calculating function execution times.
+ *
+ * @constructor
+ */
+devtools.profiler.Profile = function() {
+  this.codeMap_ = new devtools.profiler.CodeMap();
+  this.topDownTree_ = new devtools.profiler.CallTree();
+  this.bottomUpTree_ = new devtools.profiler.CallTree();
+};
+
+
+/**
+ * Returns whether a function with the specified name must be skipped.
+ * Should be overriden by subclasses.
+ *
+ * @param {string} name Function name.
+ */
+devtools.profiler.Profile.prototype.skipThisFunction = function(name) {
+  return false;
+};
+
+
+/**
+ * Called whenever the specified operation has failed finding a function
+ * containing the specified address. Should be overriden by subclasses.
+ * Operation is one of the following: 'move', 'delete', 'tick'.
+ *
+ * @param {string} operation Operation name.
+ * @param {number} addr Address of the unknown code.
+ */
+devtools.profiler.Profile.prototype.handleUnknownCode = function(
+    operation, addr) {
+};
+
+
+/**
+ * Registers static (library) code entry.
+ *
+ * @param {string} name Code entry name.
+ * @param {number} startAddr Starting address.
+ * @param {number} endAddr Ending address.
+ */
+devtools.profiler.Profile.prototype.addStaticCode = function(
+    name, startAddr, endAddr) {
+  this.codeMap_.addStaticCode(startAddr,
+      new devtools.profiler.CodeMap.CodeEntry(endAddr - startAddr, name));
+};
+
+
+/**
+ * Registers dynamic (JIT-compiled) code entry.
+ *
+ * @param {string} type Code entry type.
+ * @param {string} name Code entry name.
+ * @param {number} start Starting address.
+ * @param {number} size Code entry size.
+ */
+devtools.profiler.Profile.prototype.addCode = function(
+    type, name, start, size) {
+  this.codeMap_.addCode(start,
+      new devtools.profiler.Profile.DynamicCodeEntry(size, type, name));
+};
+
+
+/**
+ * Reports about moving of a dynamic code entry.
+ *
+ * @param {number} from Current code entry address.
+ * @param {number} to New code entry address.
+ */
+devtools.profiler.Profile.prototype.moveCode = function(from, to) {
+  try {
+    this.codeMap_.moveCode(from, to);
+  } catch (e) {
+    this.handleUnknownCode('move', from);
+  }
+};
+
+
+/**
+ * Reports about deletion of a dynamic code entry.
+ *
+ * @param {number} start Starting address.
+ */
+devtools.profiler.Profile.prototype.deleteCode = function(start) {
+  try {
+    this.codeMap_.deleteCode(start);
+  } catch (e) {
+    this.handleUnknownCode('delete', start);
+  }
+};
+
+
+/**
+ * Records a tick event. Stack must contain a sequence of
+ * addresses starting with the program counter value.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.recordTick = function(stack) {
+  var processedStack = this.resolveAndFilterFuncs_(stack);
+  this.bottomUpTree_.addPath(processedStack);
+  processedStack.reverse();
+  this.topDownTree_.addPath(processedStack);
+};
+
+
+/**
+ * Translates addresses into function names and filters unneeded
+ * functions.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
+  var result = [];
+  for (var i = 0; i < stack.length; ++i) {
+    var entry = this.codeMap_.findEntry(stack[i]);
+    if (entry) {
+      var name = entry.getName();
+      if (!this.skipThisFunction(name)) {
+        result.push(name);
+      }
+    } else {
+      this.handleUnknownCode('tick', stack[i]);
+    }
+  }
+  return result;
+};
+
+
+/**
+ * Returns the root of the top down call graph.
+ */
+devtools.profiler.Profile.prototype.getTopDownTreeRoot = function() {
+  this.topDownTree_.computeTotalWeights();
+  return this.topDownTree_.root_;
+};
+
+
+/**
+ * Returns the root of the bottom up call graph.
+ */
+devtools.profiler.Profile.prototype.getBottomUpTreeRoot = function() {
+  this.bottomUpTree_.computeTotalWeights();
+  return this.bottomUpTree_.root_;
+};
+
+
+/**
+ * Traverses the top down call graph in preorder.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseTopDownTree = function(f) {
+  this.topDownTree_.traverse(f);
+};
+
+
+/**
+ * Traverses the bottom up call graph in preorder.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseBottomUpTree = function(f) {
+  this.bottomUpTree_.traverse(f);
+};
+
+
+/**
+ * Calculates a flat profile of callees starting from the specified node.
+ *
+ * @param {devtools.profiler.CallTree.Node} opt_root Starting node.
+ */
+devtools.profiler.Profile.prototype.getFlatProfile = function(opt_root) {
+  var counters = new devtools.profiler.CallTree.Node('');
+  var precs = {};
+  this.topDownTree_.computeTotalWeights();
+  this.topDownTree_.traverseInDepth(
+    function onEnter(node) {
+      if (!(node.label in precs)) {
+        precs[node.label] = 0;
+      }
+      var rec = counters.findOrAddChild(node.label);
+      rec.selfWeight += node.selfWeight;
+      if (precs[node.label] == 0) {
+        rec.totalWeight += node.totalWeight;
+      }
+      precs[node.label]++;
+    },
+    function onExit(node) {
+      precs[node.label]--;
+    },
+    opt_root);
+  return counters.exportChildren();
+};
+
+
+/**
+ * Creates a dynamic code entry.
+ *
+ * @param {number} size Code size.
+ * @param {string} type Code type.
+ * @param {string} name Function name.
+ * @constructor
+ */
+devtools.profiler.Profile.DynamicCodeEntry = function(size, type, name) {
+  devtools.profiler.CodeMap.CodeEntry.call(this, size, name);
+  this.type = type;
+};
+
+
+/**
+ * Returns node name.
+ */
+devtools.profiler.Profile.DynamicCodeEntry.prototype.getName = function() {
+  var name = this.name;
+  if (name.length == 0) {
+    name = '<anonymous>';
+  } else if (name.charAt(0) == ' ') {
+    // An anonymous function with location: " aaa.js:10".
+    name = '<anonymous>' + name;
+  }
+  return this.type + ': ' + name;
+};
+
+
+/**
+ * Constructs a call graph.
+ *
+ * @constructor
+ */
+devtools.profiler.CallTree = function() {
+  this.root_ = new devtools.profiler.CallTree.Node('');
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CallTree.prototype.totalsComputed_ = false;
+
+
+/**
+ * Adds the specified call path, constructing nodes as necessary.
+ *
+ * @param {Array<string>} path Call path.
+ */
+devtools.profiler.CallTree.prototype.addPath = function(path) {
+  if (path.length == 0) {
+    return;
+  }
+  var curr = this.root_;
+  for (var i = 0; i < path.length; ++i) {
+    curr = curr.findOrAddChild(path[i]);
+  }
+  curr.selfWeight++;
+  this.totalsComputed_ = false;
+};
+
+
+/**
+ * Computes total weights in the call graph.
+ */
+devtools.profiler.CallTree.prototype.computeTotalWeights = function() {
+  if (this.totalsComputed_) {
+    return;
+  }
+  this.root_.computeTotalWeight();
+  this.totalsComputed_ = true;
+};
+
+
+/**
+ * Traverses the call graph in preorder.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ * @param {devtools.profiler.CallTree.Node} opt_start Starting node.
+ */
+devtools.profiler.CallTree.prototype.traverse = function(f, opt_start) {
+  var nodesToVisit = [opt_start || this.root_];
+  while (nodesToVisit.length > 0) {
+    var node = nodesToVisit.shift();
+    f(node);
+    nodesToVisit = nodesToVisit.concat(node.exportChildren());
+  }
+};
+
+
+/**
+ * Performs an indepth call graph traversal.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} enter A function called
+ *     prior to visiting node's children.
+ * @param {function(devtools.profiler.CallTree.Node)} exit A function called
+ *     after visiting node's children.
+ * @param {devtools.profiler.CallTree.Node} opt_start Starting node.
+ */
+devtools.profiler.CallTree.prototype.traverseInDepth = function(
+    enter, exit, opt_start) {
+  function traverse(node) {
+    enter(node);
+    node.forEachChild(traverse);
+    exit(node);
+  }
+  traverse(opt_start || this.root_);
+};
+
+
+/**
+ * Constructs a call graph node.
+ *
+ * @param {string} label Node label.
+ * @param {devtools.profiler.CallTree.Node} opt_parent Node parent.
+ */
+devtools.profiler.CallTree.Node = function(label, opt_parent) {
+  this.label = label;
+  this.parent = opt_parent;
+  this.children = {};
+};
+
+
+/**
+ * Node self weight (how many times this node was the last node in
+ * a call path).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.selfWeight = 0;
+
+
+/**
+ * Node total weight (includes weights of all children).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.totalWeight = 0;
+
+
+/**
+ * Adds a child node.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.addChild = function(label) {
+  var child = new devtools.profiler.CallTree.Node(label, this);
+  this.children[label] = child;
+  return child;
+};
+
+
+/**
+ * Computes node's total weight.
+ */
+devtools.profiler.CallTree.Node.prototype.computeTotalWeight =
+    function() {
+  var totalWeight = this.selfWeight;
+  this.forEachChild(function(child) {
+      totalWeight += child.computeTotalWeight(); });
+  return this.totalWeight = totalWeight;
+};
+
+
+/**
+ * Returns all node's children as an array.
+ */
+devtools.profiler.CallTree.Node.prototype.exportChildren = function() {
+  var result = [];
+  this.forEachChild(function (node) { result.push(node); });
+  return result;
+};
+
+
+/**
+ * Finds an immediate child with the specified label.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findChild = function(label) {
+  return this.children[label] || null;
+};
+
+
+/**
+ * Finds an immediate child with the specified label, creates a child
+ * node if necessary.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findOrAddChild = function(
+    label) {
+  return this.findChild(label) || this.addChild(label);
+};
+
+
+/**
+ * Calls the specified function for every child.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.forEachChild = function(f) {
+  for (var c in this.children) {
+    f(this.children[c]);
+  }
+};
+
+
+/**
+ * Walks up from the current node up to the call tree root.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.walkUpToRoot = function(f) {
+  for (var curr = this; curr != null; curr = curr.parent) {
+    f(curr);
+  }
+};
+
+
+/**
+ * Tries to find a node with the specified path.
+ *
+ * @param {Array<string>} labels The path.
+ * @param {function(devtools.profiler.CallTree.Node)} opt_f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.descendToChild = function(
+    labels, opt_f) {
+  for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) {
+    var child = curr.findChild(labels[pos]);
+    if (opt_f) {
+      opt_f(child, pos);
+    }
+    curr = child;
+  }
+  return curr;
+};
diff --git a/tools/splaytree.js b/tools/splaytree.js
index 3045456..f3beb16 100644
--- a/tools/splaytree.js
+++ b/tools/splaytree.js
@@ -94,7 +94,6 @@
 };
 
 
-
 /**
  * Removes a node with the specified key from the tree if the tree
  * contains a node with this key. The removed node is returned. If the
diff --git a/tools/visual_studio/v8_base_arm.vcproj b/tools/visual_studio/v8_base_arm.vcproj
index a91d63a..04ed230 100644
--- a/tools/visual_studio/v8_base_arm.vcproj
+++ b/tools/visual_studio/v8_base_arm.vcproj
@@ -349,6 +349,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\debug-agent.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug-agent.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\debug-arm.cc"
 				>
 			</File>
@@ -593,6 +601,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\oprofile-agent.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\oprofile-agent.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\parser.cc"
 				>
 			</File>