Version 2.5.0

Fixed bug in cache handling of lastIndex on global regexps (issue http://crbug.com/58740).

Added USE_SIMULATOR macro that explicitly indicates that we wish to use the simulator as the execution engine (by Mark Lam <mark.lam@palm.com> from Hewlett-Packard Development Company, LP).

Fixed compilation error on ARM with gcc 4.4 (issue 894).


git-svn-id: http://v8.googlecode.com/svn/trunk@5638 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 43f4d87..e6fd607 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -447,9 +447,6 @@
   void Branch(bool if_true, JumpTarget* target);
   void CheckStack();
 
-  static InlineFunctionGenerator FindInlineFunctionGenerator(
-      Runtime::FunctionId function_id);
-
   bool CheckForInlineRuntimeCall(CallRuntime* node);
 
   static Handle<Code> ComputeLazyCompile(int argc);
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 9fc0c09..2855ca4 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -62,6 +62,13 @@
   SetFunctionPosition(function());
   Comment cmnt(masm_, "[ function compiled by full code generator");
 
+#ifdef DEBUG
+  if (strlen(FLAG_stop_at) > 0 &&
+      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+    __ stop("stop-at");
+  }
+#endif
+
   int locals_count = scope()->num_stack_slots();
 
   __ Push(lr, fp, cp, r1);
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 40be9bb..84d9d01 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -37,7 +37,7 @@
 #include "arm/constants-arm.h"
 #include "arm/simulator-arm.h"
 
-#if !defined(__arm__)
+#if !defined(__arm__) || defined(USE_SIMULATOR)
 
 // Only build the simulator if not compiling for real ARM hardware.
 namespace assembler {
@@ -2840,6 +2840,6 @@
 
 } }  // namespace assembler::arm
 
-#endif  // __arm__
+#endif  // !__arm__ || USE_SIMULATOR
 
 #endif  // V8_TARGET_ARCH_ARM
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index fee296e..d4c8250 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -38,7 +38,7 @@
 
 #include "allocation.h"
 
-#if defined(__arm__)
+#if defined(__arm__) && !defined(USE_SIMULATOR)
 
 // When running without a simulator we call the entry directly.
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@@ -70,7 +70,7 @@
   reinterpret_cast<TryCatch*>(try_catch_address)
 
 
-#else  // defined(__arm__)
+#else  // !defined(__arm__) || defined(USE_SIMULATOR)
 
 // When running with the simulator transition into simulated execution at this
 // point.
@@ -356,6 +356,6 @@
 };
 
 
-#endif  // defined(__arm__)
+#endif  // !defined(__arm__) || defined(USE_SIMULATOR)
 
 #endif  // V8_ARM_SIMULATOR_ARM_H_
diff --git a/src/codegen.cc b/src/codegen.cc
index 295d7b0..bda697a 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -361,24 +361,19 @@
 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
 
 
-CodeGenerator::InlineFunctionGenerator
-  CodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
-    return kInlineFunctionGenerators[
-      static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
-}
-
-
 bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
   ZoneList<Expression*>* args = node->arguments();
   Handle<String> name = node->name();
   Runtime::Function* function = node->function();
   if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
-    InlineFunctionGenerator generator =
-        FindInlineFunctionGenerator(function->function_id);
-    if (generator != NULL) {
-      ((*this).*(generator))(args);
-      return true;
-    }
+    int lookup_index = static_cast<int>(function->function_id) -
+        static_cast<int>(Runtime::kFirstInlineFunction);
+    ASSERT(lookup_index >= 0);
+    ASSERT(static_cast<size_t>(lookup_index) <
+           ARRAY_SIZE(kInlineFunctionGenerators));
+    InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
+    (this->*generator)(args);
+    return true;
   }
   return false;
 }
diff --git a/src/codegen.h b/src/codegen.h
index 2a4d9d4..8f923dd 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -62,7 +62,6 @@
 //   ComputeCallInitializeInLoop
 //   ProcessDeclarations
 //   DeclareGlobals
-//   FindInlineRuntimeLUT
 //   CheckForInlineRuntimeCall
 //   AnalyzeCondition
 //   CodeForFunctionPosition
diff --git a/src/conversions.cc b/src/conversions.cc
index a7a0867..790e807 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -353,7 +353,7 @@
 
     ASSERT(buffer_pos < kBufferSize);
     buffer[buffer_pos] = '\0';
-    Vector<char> buffer_vector(buffer, buffer_pos);
+    Vector<const char> buffer_vector(buffer, buffer_pos);
     return sign ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
   }
 
@@ -653,7 +653,7 @@
   ASSERT(buffer_pos < kBufferSize);
   buffer[buffer_pos] = '\0';
 
-  double converted = Strtod(Vector<char>(buffer, buffer_pos), exponent);
+  double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
   return sign? -converted: converted;
 }
 
diff --git a/src/d8.js b/src/d8.js
index 5c3da13..a758e09 100644
--- a/src/d8.js
+++ b/src/d8.js
@@ -949,7 +949,7 @@
       case 'suspend':
         details.text = 'stopped';
         break;
-        
+
       case 'setbreakpoint':
         result = 'set breakpoint #';
         result += body.breakpoint;
@@ -961,7 +961,7 @@
         result += body.breakpoint;
         details.text = result;
         break;
-        
+
       case 'listbreakpoints':
         result = 'breakpoints: (' + body.breakpoints.length + ')';
         for (var i = 0; i < body.breakpoints.length; i++) {
diff --git a/src/date.js b/src/date.js
index b101ea6..9601470 100644
--- a/src/date.js
+++ b/src/date.js
@@ -246,7 +246,7 @@
 
 
 var ltcache = {
-  key: null, 
+  key: null,
   val: null
 };
 
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index 34eb0f0..a0c6808 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -2118,7 +2118,7 @@
   }
   var script_id = request.arguments.script_id;
   var preview_only = !!request.arguments.preview_only;
-  
+
   var scripts = %DebugGetLoadedScripts();
 
   var the_script = null;
@@ -2139,11 +2139,11 @@
   }
 
   var new_source = request.arguments.new_source;
-  
+
   var result_description = Debug.LiveEdit.SetScriptSource(the_script,
       new_source, preview_only, change_log);
   response.body = {change_log: change_log, result: result_description};
-  
+
   if (!preview_only && !this.running_ && result_description.stack_modified) {
     response.body.stepin_recommended = true;
   }
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index ec6ad22..b072409 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -624,9 +624,6 @@
 
   void CheckStack();
 
-  static InlineFunctionGenerator FindInlineFunctionGenerator(
-      Runtime::FunctionId function_id);
-
   bool CheckForInlineRuntimeCall(CallRuntime* node);
 
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index cf53f4b..150df99 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -61,6 +61,13 @@
   SetFunctionPosition(function());
   Comment cmnt(masm_, "[ function compiled by full code generator");
 
+#ifdef DEBUG
+  if (strlen(FLAG_stop_at) > 0 &&
+      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+    __ int3();
+  }
+#endif
+
   __ push(ebp);  // Caller's frame pointer.
   __ mov(ebp, esp);
   __ push(esi);  // Callee's context.
diff --git a/src/liveedit-debugger.js b/src/liveedit-debugger.js
index be97989..83b703f 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -46,8 +46,7 @@
 
   // Forward declaration for minifier.
   var FunctionStatus;
-  
-  
+
   // Applies the change to the script.
   // The change is in form of list of chunks encoded in a single array as
   // a series of triplets (pos1_start, pos1_end, pos2_end)
@@ -58,7 +57,7 @@
 
     // Gather compile information about old version of script.
     var old_compile_info = GatherCompileInfo(old_source, script);
-  
+
     // Build tree structures for old and new versions of the script.
     var root_old_node = BuildCodeInfoTree(old_compile_info);
 
@@ -69,7 +68,7 @@
 
     // Find all SharedFunctionInfo's that were compiled from this script.
     FindLiveSharedInfos(root_old_node, script);
-    
+
     // Gather compile information about new version of script.
     var new_compile_info;
     try {
@@ -81,7 +80,7 @@
 
     // Link recompiled script data with other data.
     FindCorrespondingFunctions(root_old_node, root_new_node);
-    
+
     // Prepare to-do lists.
     var replace_code_list = new Array();
     var link_to_old_script_list = new Array();
@@ -104,7 +103,7 @@
           CollectNew(node_list[i].children);
         }
       }
-      
+
       if (old_node.status == FunctionStatus.DAMAGED) {
         CollectDamaged(old_node);
         return;
@@ -131,17 +130,17 @@
         },
         updated: false
     };
-    
+
     if (preview_only) {
       return preview_description;
     }
-    
+
     HarvestTodo(root_old_node);
-    
+
     // Collect shared infos for functions whose code need to be patched.
     var replaced_function_infos = new Array();
     for (var i = 0; i < replace_code_list.length; i++) {
-      var info_wrapper = replace_code_list[i].live_shared_info_wrapper; 
+      var info_wrapper = replace_code_list[i].live_shared_info_wrapper;
       if (info_wrapper) {
         replaced_function_infos.push(info_wrapper);
       }
@@ -149,14 +148,14 @@
 
     // We haven't changed anything before this line yet.
     // Committing all changes.
-    
+
     // Check that function being patched is not currently on stack or drop them.
     var dropped_functions_number =
         CheckStackActivations(replaced_function_infos, change_log);
-    
-    preview_description.stack_modified = dropped_functions_number != 0; 
-  
-    // Start with breakpoints. Convert their line/column positions and 
+
+    preview_description.stack_modified = dropped_functions_number != 0;
+
+    // Start with breakpoints. Convert their line/column positions and
     // temporary remove.
     var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log);
 
@@ -169,24 +168,24 @@
       old_script = void 0;
     } else {
       var old_script_name = CreateNameForOldScript(script);
-      
+
       // Update the script text and create a new script representing an old
       // version of the script.
       old_script = %LiveEditReplaceScript(script, new_source,
           old_script_name);
-      
+
       var link_to_old_script_report = new Array();
       change_log.push( { linked_to_old_script: link_to_old_script_report } );
-    
+
       // We need to link to old script all former nested functions.
       for (var i = 0; i < link_to_old_script_list.length; i++) {
         LinkToOldScript(link_to_old_script_list[i], old_script,
             link_to_old_script_report);
       }
-      
+
       preview_description.created_script_name = old_script_name;
     }
-    
+
     // Link to an actual script all the functions that we are going to use.
     for (var i = 0; i < link_to_original_script_list.length; i++) {
       %LiveEditFunctionSetScript(
@@ -196,26 +195,26 @@
     for (var i = 0; i < replace_code_list.length; i++) {
       PatchFunctionCode(replace_code_list[i], change_log);
     }
-  
+
     var position_patch_report = new Array();
     change_log.push( {position_patched: position_patch_report} );
-    
+
     for (var i = 0; i < update_positions_list.length; i++) {
       // TODO(LiveEdit): take into account wether it's source_changed or
       // unchanged and whether positions changed at all.
       PatchPositions(update_positions_list[i], diff_array,
           position_patch_report);
     }
-    
+
     break_points_restorer(pos_translator, old_script);
-    
+
     preview_description.updated = true;
     return preview_description;
   }
   // Function is public.
   this.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
 
-  
+
   // Fully compiles source string as a script. Returns Array of
   // FunctionCompileInfo -- a descriptions of all functions of the script.
   // Elements of array are ordered by start positions of functions (from top
@@ -224,7 +223,7 @@
   //
   // All functions get compiled linked to script provided as parameter script.
   // TODO(LiveEdit): consider not using actual scripts as script, because
-  //     we have to manually erase all links right after compile. 
+  // we have to manually erase all links right after compile.
   function GatherCompileInfo(source, script) {
     // Get function info, elements are partially sorted (it is a tree of
     // nested functions serialized as parent followed by serialized children.
@@ -291,7 +290,7 @@
     return compile_info;
   }
 
-  
+
   // Replaces function's Code.
   function PatchFunctionCode(old_node, change_log) {
     var new_info = old_node.corresponding_node.info;
@@ -318,7 +317,7 @@
           }
         }
       }
-      
+
       change_log.push( {function_patched: new_info.function_name} );
     } else {
       change_log.push( {function_patched: new_info.function_name,
@@ -326,7 +325,7 @@
     }
   }
 
-  
+
   // Makes a function associated with another instance of a script (the
   // one representing its old version). This way the function still
   // may access its own text.
@@ -340,12 +339,12 @@
           { name: old_info_node.info.function_name, not_found: true } );
     }
   }
-  
+
 
   // Returns function that restores breakpoints.
   function TemporaryRemoveBreakPoints(original_script, change_log) {
     var script_break_points = GetScriptBreakPoints(original_script);
-    
+
     var break_points_update_report = [];
     change_log.push( { break_points_update: break_points_update_report } );
 
@@ -354,11 +353,11 @@
       var break_point = script_break_points[i];
 
       break_point.clear();
-      
-      // TODO(LiveEdit): be careful with resource offset here. 
+
+      // TODO(LiveEdit): be careful with resource offset here.
       var break_point_position = Debug.findScriptSourcePosition(original_script,
           break_point.line(), break_point.column());
-      
+
       var old_position_description = {
           position: break_point_position,
           line: break_point.line(),
@@ -366,8 +365,8 @@
       }
       break_point_old_positions.push(old_position_description);
     }
-    
-    
+
+
     // Restores breakpoints and creates their copies in the "old" copy of
     // the script.
     return function (pos_translator, old_script_copy_opt) {
@@ -378,19 +377,19 @@
         if (old_script_copy_opt) {
           var clone = break_point.cloneForOtherScript(old_script_copy_opt);
           clone.set(old_script_copy_opt);
-          
+
           break_points_update_report.push( {
             type: "copied_to_old",
             id: break_point.number(),
-            new_id: clone.number(), 
+            new_id: clone.number(),
             positions: break_point_old_positions[i]
             } );
         }
-        
+
         var updated_position = pos_translator.Translate(
             break_point_old_positions[i].position,
             PosTranslator.ShiftWithTopInsideChunkHandler);
-        
+
         var new_location =
             original_script.locationFromPosition(updated_position, false);
 
@@ -401,9 +400,9 @@
             line: new_location.line,
             column: new_location.column
         }
-        
+
         break_point.set(original_script);
-        
+
         break_points_update_report.push( { type: "position_changed",
           id: break_point.number(),
           old_positions: break_point_old_positions[i],
@@ -413,7 +412,7 @@
     }
   }
 
-  
+
   function Assert(condition, message) {
     if (!condition) {
       if (message) {
@@ -430,7 +429,7 @@
     this.len1 = len1;
     this.len2 = len2;
   }
-  
+
   function PosTranslator(diff_array) {
     var chunks = new Array();
     var current_diff = 0;
@@ -441,16 +440,16 @@
       var pos2_end = diff_array[i + 2];
       chunks.push(new DiffChunk(pos1_begin, pos2_begin, pos1_end - pos1_begin,
           pos2_end - pos2_begin));
-      current_diff = pos2_end - pos1_end; 
+      current_diff = pos2_end - pos1_end;
     }
     this.chunks = chunks;
   }
   PosTranslator.prototype.GetChunks = function() {
     return this.chunks;
   }
-  
+
   PosTranslator.prototype.Translate = function(pos, inside_chunk_handler) {
-    var array = this.chunks; 
+    var array = this.chunks;
     if (array.length == 0 || pos < array[0].pos1) {
       return pos;
     }
@@ -467,9 +466,9 @@
     }
     var chunk = array[chunk_index1];
     if (pos >= chunk.pos1 + chunk.len1) {
-      return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1; 
+      return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1;
     }
-    
+
     if (!inside_chunk_handler) {
       inside_chunk_handler = PosTranslator.DefaultInsideChunkHandler;
     }
@@ -479,17 +478,17 @@
   PosTranslator.DefaultInsideChunkHandler = function(pos, diff_chunk) {
     Assert(false, "Cannot translate position in changed area");
   }
-  
+
   PosTranslator.ShiftWithTopInsideChunkHandler =
       function(pos, diff_chunk) {
     // We carelessly do not check whether we stay inside the chunk after
     // translation.
-    return pos - diff_chunk.pos1 + diff_chunk.pos2; 
+    return pos - diff_chunk.pos1 + diff_chunk.pos2;
   }
-  
+
   var FunctionStatus = {
       // No change to function or its inner functions; however its positions
-      // in script may have been shifted. 
+      // in script may have been shifted.
       UNCHANGED: "unchanged",
       // The code of a function remains unchanged, but something happened inside
       // some inner functions.
@@ -500,14 +499,14 @@
       // Function is changed but cannot be patched.
       DAMAGED: "damaged"
   }
-  
+
   function CodeInfoTreeNode(code_info, children, array_index) {
     this.info = code_info;
     this.children = children;
     // an index in array of compile_info
-    this.array_index = array_index; 
+    this.array_index = array_index;
     this.parent = void 0;
-    
+
     this.status = FunctionStatus.UNCHANGED;
     // Status explanation is used for debugging purposes and will be shown
     // in user UI if some explanations are needed.
@@ -516,26 +515,26 @@
     this.new_end_pos = void 0;
     this.corresponding_node = void 0;
     this.unmatched_new_nodes = void 0;
-    
+
     // 'Textual' correspondence/matching is weaker than 'pure'
     // correspondence/matching. We need 'textual' level for visual presentation
     // in UI, we use 'pure' level for actual code manipulation.
     // Sometimes only function body is changed (functions in old and new script
     // textually correspond), but we cannot patch the code, so we see them
-    // as an old function deleted and new function created.  
+    // as an old function deleted and new function created.
     this.textual_corresponding_node = void 0;
     this.textually_unmatched_new_nodes = void 0;
-    
+
     this.live_shared_info_wrapper = void 0;
   }
-  
+
   // From array of function infos that is implicitly a tree creates
   // an actual tree of functions in script.
   function BuildCodeInfoTree(code_info_array) {
     // Throughtout all function we iterate over input array.
     var index = 0;
 
-    // Recursive function that builds a branch of tree. 
+    // Recursive function that builds a branch of tree.
     function BuildNode() {
       var my_index = index;
       index++;
@@ -551,7 +550,7 @@
       }
       return node;
     }
-    
+
     var root = BuildNode();
     Assert(index == code_info_array.length);
     return root;
@@ -570,7 +569,7 @@
       this.current = function() { return chunks[chunk_index]; }
       this.next = function() {
         var chunk = chunks[chunk_index];
-        pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1); 
+        pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1);
         chunk_index++;
       }
       this.done = function() { return chunk_index >= chunks.length; }
@@ -582,7 +581,7 @@
     // below function start.
     function ProcessInternals(info_node) {
       info_node.new_start_pos = chunk_it.TranslatePos(
-          info_node.info.start_position); 
+          info_node.info.start_position);
       var child_index = 0;
       var code_changed = false;
       var source_changed = false;
@@ -591,7 +590,7 @@
           chunk_it.current().pos1 < info_node.info.end_position) {
         if (child_index < info_node.children.length) {
           var child = info_node.children[child_index];
-          
+
           if (child.info.end_position <= chunk_it.current().pos1) {
             ProcessUnchangedChild(child);
             child_index++;
@@ -620,7 +619,7 @@
             continue;
           }
         } else {
-          if (chunk_it.current().pos1 + chunk_it.current().len1 <= 
+          if (chunk_it.current().pos1 + chunk_it.current().len1 <=
               info_node.info.end_position) {
             info_node.status = FunctionStatus.CHANGED;
             chunk_it.next();
@@ -645,14 +644,14 @@
         info_node.status = FunctionStatus.SOURCE_CHANGED;
       }
       info_node.new_end_pos =
-          chunk_it.TranslatePos(info_node.info.end_position); 
+          chunk_it.TranslatePos(info_node.info.end_position);
     }
-    
+
     function ProcessUnchangedChild(node) {
       node.new_start_pos = chunk_it.TranslatePos(node.info.start_position);
       node.new_end_pos = chunk_it.TranslatePos(node.info.end_position);
     }
-    
+
     ProcessInternals(code_info_tree);
   }
 
@@ -670,7 +669,7 @@
     function ProcessChildren(old_node, new_node) {
       var old_children = old_node.children;
       var new_children = new_node.children;
-      
+
       var unmatched_new_nodes_list = [];
       var textually_unmatched_new_nodes_list = [];
 
@@ -728,13 +727,13 @@
           old_index++;
         }
       }
-      
+
       while (new_index < new_children.length) {
         unmatched_new_nodes_list.push(new_children[new_index]);
         textually_unmatched_new_nodes_list.push(new_children[new_index]);
         new_index++;
       }
-      
+
       if (old_node.status == FunctionStatus.CHANGED) {
         var why_wrong_expectations =
             WhyFunctionExpectationsDiffer(old_node.info, new_node.info);
@@ -749,23 +748,23 @@
     }
 
     ProcessChildren(old_code_tree, new_code_tree);
-    
+
     old_code_tree.corresponding_node = new_code_tree;
     old_code_tree.textual_corresponding_node = new_code_tree;
 
     Assert(old_code_tree.status != FunctionStatus.DAMAGED,
         "Script became damaged");
   }
-  
+
   function FindLiveSharedInfos(old_code_tree, script) {
     var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
-    
+
     var shared_infos = new Array();
-  
+
     for (var i = 0; i < shared_raw_list.length; i++) {
       shared_infos.push(new SharedInfoWrapper(shared_raw_list[i]));
     }
-    
+
     // Finds SharedFunctionInfo that corresponds compile info with index
     // in old version of the script.
     function FindFunctionInfo(compile_info) {
@@ -777,7 +776,7 @@
         }
       }
     }
-    
+
     function TraverseTree(node) {
       var info_wrapper = FindFunctionInfo(node.info);
       if (info_wrapper) {
@@ -791,7 +790,7 @@
     TraverseTree(old_code_tree);
   }
 
-  
+
   // An object describing function compilation details. Its index fields
   // apply to indexes inside array that stores these objects.
   function FunctionCompileInfo(raw_array) {
@@ -807,7 +806,7 @@
     this.next_sibling_index = null;
     this.raw_array = raw_array;
   }
-  
+
   function SharedInfoWrapper(raw_array) {
     this.function_name = raw_array[0];
     this.start_position = raw_array[1];
@@ -821,7 +820,7 @@
     var shared_info_wrapper = old_info_node.live_shared_info_wrapper;
     if (!shared_info_wrapper) {
       // TODO(LiveEdit): function is not compiled yet or is already collected.
-      report_array.push( 
+      report_array.push(
           { name: old_info_node.info.function_name, info_not_found: true } );
       return;
     }
@@ -835,44 +834,44 @@
     // TODO(635): try better than this; support several changes.
     return script.name + " (old)";
   }
-  
+
   // Compares a function interface old and new version, whether it
   // changed or not. Returns explanation if they differ.
   function WhyFunctionExpectationsDiffer(function_info1, function_info2) {
     // Check that function has the same number of parameters (there may exist
     // an adapter, that won't survive function parameter number change).
     if (function_info1.param_num != function_info2.param_num) {
-      return "Changed parameter number: " + function_info1.param_num + 
+      return "Changed parameter number: " + function_info1.param_num +
           " and " + function_info2.param_num;
     }
     var scope_info1 = function_info1.scope_info;
     var scope_info2 = function_info2.scope_info;
 
-    var scope_info1_text; 
-    var scope_info2_text; 
-    
+    var scope_info1_text;
+    var scope_info2_text;
+
     if (scope_info1) {
-      scope_info1_text = scope_info1.toString(); 
+      scope_info1_text = scope_info1.toString();
     } else {
       scope_info1_text = "";
     }
     if (scope_info2) {
-      scope_info2_text = scope_info2.toString(); 
+      scope_info2_text = scope_info2.toString();
     } else {
       scope_info2_text = "";
     }
-    
+
     if (scope_info1_text != scope_info2_text) {
       return "Incompatible variable maps: [" + scope_info1_text +
-          "] and [" + scope_info2_text + "]";  
+          "] and [" + scope_info2_text + "]";
     }
     // No differences. Return undefined.
     return;
   }
-  
+
   // Minifier forward declaration.
   var FunctionPatchabilityStatus;
-  
+
   // For array of wrapped shared function infos checks that none of them
   // have activations on stack (of any thread). Throws a Failure exception
   // if this proves to be false.
@@ -886,7 +885,7 @@
       // Extra array element may contain error message.
       throw new Failure(result[shared_list.length]);
     }
-  
+
     var problems = new Array();
     var dropped = new Array();
     for (var i = 0; i < shared_list.length; i++) {
@@ -896,7 +895,7 @@
       } else if (result[i] != FunctionPatchabilityStatus.AVAILABLE_FOR_PATCH) {
         var description = {
             name: shared.function_name,
-            start_pos: shared.start_position, 
+            start_pos: shared.start_position,
             end_pos: shared.end_position,
             replace_problem:
                 FunctionPatchabilityStatus.SymbolName(result[i])
@@ -911,10 +910,10 @@
       change_log.push( { functions_on_stack: problems } );
       throw new Failure("Blocked by functions on stack");
     }
-    
+
     return dropped.length;
   }
-  
+
   // A copy of the FunctionPatchabilityStatus enum from liveedit.h
   var FunctionPatchabilityStatus = {
       AVAILABLE_FOR_PATCH: 1,
@@ -923,17 +922,17 @@
       BLOCKED_UNDER_NATIVE_CODE: 4,
       REPLACED_ON_ACTIVE_STACK: 5
   }
-  
+
   FunctionPatchabilityStatus.SymbolName = function(code) {
     var enum = FunctionPatchabilityStatus;
     for (name in enum) {
       if (enum[name] == code) {
         return name;
       }
-    }      
+    }
   }
-  
-  
+
+
   // A logical failure in liveedit process. This means that change_log
   // is valid and consistent description of what happened.
   function Failure(message) {
@@ -941,11 +940,11 @@
   }
   // Function (constructor) is public.
   this.Failure = Failure;
-  
+
   Failure.prototype.toString = function() {
     return "LiveEdit Failure: " + this.message;
   }
-  
+
   // A testing entry.
   function GetPcFromSourcePos(func, source_pos) {
     return %GetFunctionCodePositionFromSource(func, source_pos);
@@ -962,7 +961,7 @@
   }
   // Function is public.
   this.SetScriptSource = SetScriptSource;
-  
+
   function CompareStringsLinewise(s1, s2) {
     return %LiveEditCompareStringsLinewise(s1, s2);
   }
@@ -978,19 +977,19 @@
   function ApplySingleChunkPatch(script, change_pos, change_len, new_str,
       change_log) {
     var old_source = script.source;
-  
+
     // Prepare new source string.
     var new_source = old_source.substring(0, change_pos) +
         new_str + old_source.substring(change_pos + change_len);
-    
+
     return ApplyPatchMultiChunk(script,
         [ change_pos, change_pos + change_len, change_pos + new_str.length],
         new_source, false, change_log);
   }
-  
+
   // Creates JSON description for a change tree.
   function DescribeChangeTree(old_code_tree) {
-    
+
     function ProcessOldNode(node) {
       var child_infos = [];
       for (var i = 0; i < node.children.length; i++) {
@@ -1011,7 +1010,7 @@
         positions: DescribePositions(node),
         status: node.status,
         children: child_infos,
-        new_children: new_child_infos  
+        new_children: new_child_infos
       };
       if (node.status_explanation) {
         res.status_explanation = node.status_explanation;
@@ -1021,7 +1020,7 @@
       }
       return res;
     }
-    
+
     function ProcessNewNode(node) {
       var child_infos = [];
       // Do not list ancestors.
@@ -1037,18 +1036,18 @@
       };
       return res;
     }
-    
+
     function DescribePositions(node) {
       return {
         start_position: node.info.start_position,
         end_position: node.info.end_position
       };
     }
-    
+
     return ProcessOldNode(old_code_tree);
   }
 
-  
+
   // Functions are public for tests.
   this.TestApi = {
     PosTranslator: PosTranslator,
diff --git a/src/messages.js b/src/messages.js
index 4f492bc..7f9c0f8 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -438,18 +438,18 @@
 
 /**
  * Returns the name of script if available, contents of sourceURL comment
- * otherwise. See 
+ * otherwise. See
  * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
  * for details on using //@ sourceURL comment to identify scritps that don't
  * have name.
- * 
+ *
  * @return {?string} script name if present, value for //@ sourceURL comment
  * otherwise.
  */
 Script.prototype.nameOrSourceURL = function() {
   if (this.name)
     return this.name;
-  // TODO(608): the spaces in a regexp below had to be escaped as \040 
+  // TODO(608): the spaces in a regexp below had to be escaped as \040
   // because this file is being processed by js2c whose handling of spaces
   // in regexps is broken. Also, ['"] are excluded from allowed URLs to
   // avoid matches against sources that invoke evals with sourceURL.
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 57bed6a..59a5373 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -39,7 +39,7 @@
 
 namespace v8i = v8::internal;
 
-#if !defined(__mips)
+#if !defined(__mips) || defined(USE_SIMULATOR)
 
 // Only build the simulator if not compiling for real MIPS hardware.
 namespace assembler {
@@ -1645,6 +1645,6 @@
 
 } }  // namespace assembler::mips
 
-#endif  // __mips
+#endif  // !__mips || USE_SIMULATOR
 
 #endif  // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
index d5dfc30..6e42683 100644
--- a/src/mips/simulator-mips.h
+++ b/src/mips/simulator-mips.h
@@ -38,7 +38,7 @@
 
 #include "allocation.h"
 
-#if defined(__mips)
+#if defined(__mips) && !defined(USE_SIMULATOR)
 
 // When running without a simulator we call the entry directly.
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@@ -79,7 +79,7 @@
   reinterpret_cast<TryCatch*>(try_catch_address)
 
 
-#else   // #if defined(__mips)
+#else  // #if !defined(__mips) || defined(USE_SIMULATOR)
 
 // When running with the simulator transition into simulated execution at this
 // point.
@@ -305,7 +305,7 @@
   }
 };
 
-#endif  // defined(__mips)
+#endif  // !defined(__mips) || defined(USE_SIMULATOR)
 
 #endif  // V8_MIPS_SIMULATOR_MIPS_H_
 
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 761b9b3..6b9e965 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -1611,7 +1611,7 @@
     result += ' returning ';
     result += this.returnValue().toText();
   }
-  
+
   return result;
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index 883d789..59ed1de 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1180,7 +1180,11 @@
   if (map()->constructor()->IsJSFunction()) {
     JSFunction* constructor = JSFunction::cast(map()->constructor());
     String* name = String::cast(constructor->shared()->name());
-    return name->length() > 0 ? name : constructor->shared()->inferred_name();
+    if (name->length() > 0) return name;
+    String* inferred_name = constructor->shared()->inferred_name();
+    if (inferred_name->length() > 0) return inferred_name;
+    Object* proto = GetPrototype();
+    if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
   }
   // If the constructor is not present, return "Object".
   return Heap::Object_symbol();
@@ -6473,7 +6477,7 @@
         // When we set the is_extensible flag to false we always force
         // the element into dictionary mode (and force them to stay there).
         if (!map()->is_extensible()) {
-          Handle<Object> number(Heap::NumberFromUint32(index));
+          Handle<Object> number(Factory::NewNumberFromUint(index));
           Handle<String> index_string(Factory::NumberToString(number));
           Handle<Object> args[1] = { index_string };
           return Top::Throw(*Factory::NewTypeError("object_not_extensible",
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 08ee046..977c67c 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -94,12 +94,18 @@
 }
 
 
+static void DeleteIndexName(char** name_ptr) {
+  DeleteArray(*name_ptr);
+}
+
+
 StringsStorage::~StringsStorage() {
   for (HashMap::Entry* p = names_.Start();
        p != NULL;
        p = names_.Next(p)) {
     DeleteArray(reinterpret_cast<const char*>(p->value));
   }
+  index_names_.Iterate(DeleteIndexName);
 }
 
 
@@ -120,6 +126,22 @@
 }
 
 
+const char* StringsStorage::GetName(int index) {
+  ASSERT(index >= 0);
+  if (index_names_.length() <= index) {
+    index_names_.AddBlock(
+        NULL, index - index_names_.length() + 1);
+  }
+  if (index_names_[index] == NULL) {
+    const int kMaximumNameLength = 32;
+    char* name = NewArray<char>(kMaximumNameLength);
+    OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
+    index_names_[index] = name;
+  }
+  return index_names_[index];
+}
+
+
 const char* CodeEntry::kEmptyNamePrefix = "";
 
 
@@ -485,11 +507,6 @@
 }
 
 
-static void DeleteArgsCountName(char** name_ptr) {
-  DeleteArray(*name_ptr);
-}
-
-
 static void DeleteCodeEntry(CodeEntry** entry_ptr) {
   delete *entry_ptr;
 }
@@ -508,7 +525,6 @@
   current_profiles_.Iterate(DeleteCpuProfile);
   profiles_by_token_.Iterate(DeleteProfilesList);
   code_entries_.Iterate(DeleteCodeEntry);
-  args_count_names_.Iterate(DeleteArgsCountName);
 }
 
 
@@ -706,22 +722,6 @@
 }
 
 
-const char* CpuProfilesCollection::GetName(int args_count) {
-  ASSERT(args_count >= 0);
-  if (args_count_names_.length() <= args_count) {
-    args_count_names_.AddBlock(
-        NULL, args_count - args_count_names_.length() + 1);
-  }
-  if (args_count_names_[args_count] == NULL) {
-    const int kMaximumNameLength = 32;
-    char* name = NewArray<char>(kMaximumNameLength);
-    OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", args_count);
-    args_count_names_[args_count] = name;
-  }
-  return args_count_names_[args_count];
-}
-
-
 void CpuProfilesCollection::AddPathToCurrentProfiles(
     const Vector<CodeEntry*>& path) {
   // As starting / stopping profiles is rare relatively to this
@@ -1001,6 +1001,8 @@
     case kString: return "/string/";
     case kCode: return "/code/";
     case kArray: return "/array/";
+    case kRegExp: return "/regexp/";
+    case kHeapNumber: return "/number/";
     default: return "???";
   }
 }
@@ -1284,11 +1286,16 @@
   } else if (object->IsJSFunction()) {
     JSFunction* func = JSFunction::cast(object);
     SharedFunctionInfo* shared = func->shared();
-    String* name = String::cast(shared->name())->length() > 0 ?
-        String::cast(shared->name()) : shared->inferred_name();
     return AddEntry(object,
                     HeapEntry::kClosure,
-                    collection_->GetFunctionName(name),
+                    collection_->GetName(String::cast(shared->name())),
+                    children_count,
+                    retainers_count);
+  } else if (object->IsJSRegExp()) {
+    JSRegExp* re = JSRegExp::cast(object);
+    return AddEntry(object,
+                    HeapEntry::kRegExp,
+                    collection_->GetName(re->Pattern()),
                     children_count,
                     retainers_count);
   } else if (object->IsJSObject()) {
@@ -1333,6 +1340,12 @@
                     "",
                     children_count,
                     retainers_count);
+  } else if (object->IsHeapNumber()) {
+    return AddEntry(object,
+                    HeapEntry::kHeapNumber,
+                    "number",
+                    children_count,
+                    retainers_count);
   }
   // No interest in this object.
   return NULL;
@@ -1342,12 +1355,14 @@
 bool HeapSnapshot::WillAddEntry(HeapObject* object) {
   return object == kInternalRootObject
       || object->IsJSFunction()
+      || object->IsJSRegExp()
       || object->IsJSObject()
       || object->IsString()
       || object->IsCode()
       || object->IsSharedFunctionInfo()
       || object->IsScript()
-      || object->IsFixedArray();
+      || object->IsFixedArray()
+      || object->IsHeapNumber();
 }
 
 
@@ -1904,13 +1919,21 @@
     ExtractClosureReferences(js_obj, entry);
     ExtractPropertyReferences(js_obj, entry);
     ExtractElementReferences(js_obj, entry);
+    ExtractInternalReferences(js_obj, entry);
     SetPropertyReference(
-        obj, entry, Heap::prototype_symbol(), js_obj->map()->prototype());
+        obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
+    if (obj->IsJSFunction()) {
+      JSFunction* js_fun = JSFunction::cast(obj);
+      if (js_fun->has_prototype()) {
+        SetPropertyReference(
+            obj, entry, Heap::prototype_symbol(), js_fun->prototype());
+      }
+    }
   } else if (obj->IsString()) {
     if (obj->IsConsString()) {
       ConsString* cs = ConsString::cast(obj);
-      SetElementReference(obj, entry, 0, cs->first());
-      SetElementReference(obj, entry, 1, cs->second());
+      SetInternalReference(obj, entry, "1", cs->first());
+      SetInternalReference(obj, entry, "2", cs->second());
     }
   } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
     IndexedReferencesExtractor refs_extractor(this, obj, entry);
@@ -2005,6 +2028,16 @@
 }
 
 
+void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
+                                                      HeapEntry* entry) {
+  int length = js_obj->GetInternalFieldCount();
+  for (int i = 0; i < length; ++i) {
+    Object* o = js_obj->GetInternalField(i);
+    SetInternalReference(js_obj, entry, i, o);
+  }
+}
+
+
 void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
                                                 HeapEntry* parent_entry,
                                                 String* reference_name,
@@ -2049,13 +2082,31 @@
 }
 
 
+void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
+                                                 HeapEntry* parent_entry,
+                                                 int index,
+                                                 Object* child_obj) {
+  HeapEntry* child_entry = GetEntry(child_obj);
+  if (child_entry != NULL) {
+    filler_->SetNamedReference(HeapGraphEdge::kInternal,
+                               parent_obj,
+                               parent_entry,
+                               collection_->GetName(index),
+                               child_obj,
+                               child_entry);
+  }
+}
+
+
 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
                                                  HeapEntry* parent_entry,
                                                  String* reference_name,
                                                  Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
-    filler_->SetNamedReference(HeapGraphEdge::kProperty,
+    HeapGraphEdge::Type type = reference_name->length() > 0 ?
+        HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
+    filler_->SetNamedReference(type,
                                parent_obj,
                                parent_entry,
                                collection_->GetName(reference_name),
@@ -2351,7 +2402,9 @@
             "," JSON_S("string")
             "," JSON_S("object")
             "," JSON_S("code")
-            "," JSON_S("closure"))
+            "," JSON_S("closure")
+            "," JSON_S("regexp")
+            "," JSON_S("number"))
         "," JSON_S("string")
         "," JSON_S("number")
         "," JSON_S("number")
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 4206d29..6f63f6a 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -67,6 +67,7 @@
   ~StringsStorage();
 
   const char* GetName(String* name);
+  const char* GetName(int index);
   inline const char* GetFunctionName(String* name);
   inline const char* GetFunctionName(const char* name);
 
@@ -78,6 +79,8 @@
 
   // Mapping of strings by String::Hash to const char* strings.
   HashMap names_;
+  // Mapping from ints to char* strings.
+  List<char*> index_names_;
 
   DISALLOW_COPY_AND_ASSIGN(StringsStorage);
 };
@@ -284,6 +287,9 @@
   const char* GetName(String* name) {
     return function_and_resource_names_.GetName(name);
   }
+  const char* GetName(int args_count) {
+    return function_and_resource_names_.GetName(args_count);
+  }
   CpuProfile* GetProfile(int security_token_id, unsigned uid);
   bool IsLastProfile(const char* title);
 
@@ -302,7 +308,6 @@
   static const int kMaxSimultaneousProfiles = 100;
 
  private:
-  const char* GetName(int args_count);
   const char* GetFunctionName(String* name) {
     return function_and_resource_names_.GetFunctionName(name);
   }
@@ -317,8 +322,6 @@
   }
 
   StringsStorage function_and_resource_names_;
-  // Mapping from args_count (int) to char* strings.
-  List<char*> args_count_names_;
   List<CodeEntry*> code_entries_;
   List<List<CpuProfile*>* > profiles_by_token_;
   // Mapping from profiles' uids to indexes in the second nested list
@@ -502,7 +505,9 @@
     kString = v8::HeapGraphNode::kString,
     kObject = v8::HeapGraphNode::kObject,
     kCode = v8::HeapGraphNode::kCode,
-    kClosure = v8::HeapGraphNode::kClosure
+    kClosure = v8::HeapGraphNode::kClosure,
+    kRegExp = v8::HeapGraphNode::kRegExp,
+    kHeapNumber = v8::HeapGraphNode::kHeapNumber
   };
 
   HeapEntry() { }
@@ -824,6 +829,7 @@
   HeapSnapshot* GetSnapshot(unsigned uid);
 
   const char* GetName(String* name) { return names_.GetName(name); }
+  const char* GetName(int index) { return names_.GetName(index); }
   const char* GetFunctionName(String* name) {
     return names_.GetFunctionName(name);
   }
@@ -948,6 +954,7 @@
   void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry);
   void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);
   void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry);
+  void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry);
   void SetClosureReference(HeapObject* parent_obj,
                            HeapEntry* parent,
                            String* reference_name,
@@ -960,6 +967,10 @@
                             HeapEntry* parent,
                             const char* reference_name,
                             Object* child);
+  void SetInternalReference(HeapObject* parent_obj,
+                            HeapEntry* parent,
+                            int index,
+                            Object* child);
   void SetPropertyReference(HeapObject* parent_obj,
                             HeapEntry* parent,
                             String* reference_name,
diff --git a/src/regexp.js b/src/regexp.js
index faa525d..51f4b09 100644
--- a/src/regexp.js
+++ b/src/regexp.js
@@ -126,11 +126,11 @@
   this.regExp = 0;
   this.subject = 0;
   this.replaceString = 0;
-  this.lastIndex = 0;  // Also used for splitLimit when type is "split"
   this.answer = 0;
   // answerSaved marks whether the contents of answer is valid for a cache
   // hit in RegExpExec, StringMatch and StringSplit.
   this.answerSaved = false;
+  this.splitLimit = 0;  // Used only when type is "split".
 }
 
 
@@ -181,22 +181,30 @@
   var cache = regExpCache;
   var saveAnswer = false;
 
+  var lastIndex = this.lastIndex;
+
+  // Since cache.subject is always a string, a matching input can not
+  // cause visible side-effects when converted to a string, so we can omit
+  // the conversion required by the specification.
+  // Likewise, the regexp.lastIndex and regexp.global properties are value
+  // properties that are not configurable, so reading them can also not cause
+  // any side effects (converting lastIndex to a number can, though).
   if (%_ObjectEquals(cache.type, 'exec') &&
-      %_ObjectEquals(cache.lastIndex, this.lastIndex) &&
+      %_ObjectEquals(0, lastIndex) &&
       %_IsRegExpEquivalent(cache.regExp, this) &&
       %_ObjectEquals(cache.subject, string)) {
     if (cache.answerSaved) {
-      // If this regexp is not global, cache.lastIndex is zero, so we only get 
-      // here if this.lastIndex is zero, and resulting this.lastIndex
-      // must be zero too, so no change is necessary.
-      if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
+      // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+      // global RegExps we only cache negative results, which gives a lastIndex
+      // of zero as well.
+      this.lastIndex = 0;
       return %_RegExpCloneResult(cache.answer);
     } else {
       saveAnswer = true;
     }
   }
 
-  if (%_ArgumentsLength() == 0) {
+  if (%_ArgumentsLength() === 0) {
     var regExpInput = LAST_INPUT(lastMatchInfo);
     if (IS_UNDEFINED(regExpInput)) {
       throw MakeError('no_input_to_regexp', [this]);
@@ -209,41 +217,48 @@
   } else {
     s = ToString(string);
   }
-  var lastIndex = this.lastIndex;
+  var global = this.global;
 
-  var i = this.global ? TO_INTEGER(lastIndex) : 0;
-
-  if (i < 0 || i > s.length) {
-    this.lastIndex = 0;
-    return null;
+  // Conversion is required by the ES5 specification (RegExp.prototype.exec
+  // algorithm, step 5) even if the value is discarded for non-global RegExps.
+  var i = TO_INTEGER(lastIndex);
+  if (global) {
+    if (i < 0 || i > s.length) {
+      this.lastIndex = 0;
+      return null;
+    }
+  } else {
+    i = 0;
   }
 
   %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
   // matchIndices is either null or the lastMatchInfo array.
   var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
 
-  if (matchIndices == null) {
-    if (this.global) {
+  if (matchIndices === null) {
+    if (global) {
+      // Cache negative result only if initial lastIndex was zero.
       this.lastIndex = 0;
-      if (lastIndex != 0) return matchIndices;
+      if (lastIndex !== 0) return matchIndices;
     }
-    cache.lastIndex = lastIndex;
     cache.regExp = this;
-    cache.subject = s;
-    cache.answer = matchIndices;  // Null.
+    cache.subject = s;            // Always a string.
+    cache.answer = null;
     cache.answerSaved = true;     // Safe since no cloning is needed.
     cache.type = 'exec';
     return matchIndices;        // No match.
   }
+
+  // Successful match.
   lastMatchInfoOverride = null;
   var result = BuildResultFromMatchInfo(matchIndices, s);
 
-  if (this.global) {
+  if (global) {
+    // Don't cache positive results for global regexps.
     this.lastIndex = lastMatchInfo[CAPTURE1];
   } else {
     cache.regExp = this;
     cache.subject = s;
-    cache.lastIndex = lastIndex;
     if (saveAnswer) cache.answer = %_RegExpCloneResult(result);
     cache.answerSaved = saveAnswer;
     cache.type = 'exec';
@@ -273,32 +288,49 @@
     }
     string = regExpInput;
   }
+
+  var lastIndex = this.lastIndex;
+
+  var cache = regExpCache;
+  if (%_ObjectEquals(cache.type, 'test') &&
+      %_IsRegExpEquivalent(cache.regExp, this) &&
+      %_ObjectEquals(cache.subject, string) &&
+      %_ObjectEquals(0, lastIndex)) {
+    // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+    // global RegExps we only cache negative results, which gives a resulting
+    // lastIndex of zero as well.
+    if (global) this.lastIndex = 0;
+    return cache.answer;
+  }
+
   var s;
   if (IS_STRING(string)) {
     s = string;
   } else {
     s = ToString(string);
   }
+  var length = s.length;
 
-  var lastIndex = this.lastIndex;
-  var cache = regExpCache;
-  if (%_ObjectEquals(cache.type, 'test') &&
-      %_IsRegExpEquivalent(cache.regExp, this) &&
-      %_ObjectEquals(cache.subject, string) &&
-      %_ObjectEquals(cache.lastIndex, lastIndex)) {
-    // If this regexp is not global, cache.lastIndex is zero, so we only get 
-    // here if this.lastIndex is zero, and resulting this.lastIndex
-    // must be zero too, so no change is necessary.
-    if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
-    return cache.answer;
+  // Conversion is required by the ES5 specification (RegExp.prototype.exec
+  // algorithm, step 5) even if the value is discarded for non-global RegExps.
+  var i = TO_INTEGER(lastIndex);
+  if (global) {
+    if (i < 0 || i > length) {
+      this.lastIndex = 0;
+      return false;
+    }
+  } else {
+    i = 0;
   }
 
+  var global = this.global;
+
   // Remove irrelevant preceeding '.*' in a test regexp. The expression
   // checks whether this.source starts with '.*' and that the third
   // char is not a '?'
-  if (%_StringCharCodeAt(this.source,0) == 46 && // '.'
-      %_StringCharCodeAt(this.source,1) == 42 && // '*'
-      %_StringCharCodeAt(this.source,2) != 63) { // '?'
+  if (%_StringCharCodeAt(this.source, 0) == 46 &&  // '.'
+      %_StringCharCodeAt(this.source, 1) == 42 &&  // '*'
+      %_StringCharCodeAt(this.source, 2) != 63) {  // '?'
     if (!%_ObjectEquals(regexp_key, this)) {
       regexp_key = this;
       regexp_val = new $RegExp(this.source.substring(2, this.source.length),
@@ -309,33 +341,28 @@
     if (!regexp_val.test(s)) return false;
   }
 
-  var length = s.length;
-  var i = this.global ? TO_INTEGER(lastIndex) : 0;
-
-  cache.type = 'test';
-  cache.regExp = this;
-  cache.subject = s;
-  cache.lastIndex = i;
-
-  if (i < 0 || i > length) {
-    this.lastIndex = 0;
-    cache.answer = false;
-    return false;
-  }
-
   %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
   // matchIndices is either null or the lastMatchInfo array.
   var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
 
-  if (matchIndices == null) {
-    if (this.global) this.lastIndex = 0;
-    cache.answer = false;
-    return false;
+  var result = (matchIndices !== null);
+  if (result) {
+    lastMatchInfoOverride = null;
   }
-  lastMatchInfoOverride = null;
-  if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
-  cache.answer = true;
-  return true;
+  if (global) {
+    if (result) {
+      this.lastIndex = lastMatchInfo[CAPTURE1];
+      return true;
+    } else {
+      this.lastIndex = 0;
+      if (lastIndex !== 0) return false;
+    }
+  }
+  cache.type = 'test';
+  cache.regExp = this;
+  cache.subject = s;
+  cache.answer = result;
+  return result;
 }
 
 
@@ -345,12 +372,9 @@
   // ecma_2/RegExp/properties-001.js.
   var src = this.source ? this.source : '(?:)';
   var result = '/' + src + '/';
-  if (this.global)
-    result += 'g';
-  if (this.ignoreCase)
-    result += 'i';
-  if (this.multiline)
-    result += 'm';
+  if (this.global) result += 'g';
+  if (this.ignoreCase) result += 'i';
+  if (this.multiline) result += 'm';
   return result;
 }
 
diff --git a/src/string.js b/src/string.js
index 30eedb3..d97f632 100644
--- a/src/string.js
+++ b/src/string.js
@@ -611,7 +611,7 @@
   if (%_ObjectEquals(cache.type, 'split') &&
       %_IsRegExpEquivalent(cache.regExp, separator) &&
       %_ObjectEquals(cache.subject, subject) &&
-      %_ObjectEquals(cache.lastIndex, limit)) {
+      %_ObjectEquals(cache.splitLimit, limit)) {
     if (cache.answerSaved) {
       return CloneDenseArray(cache.answer);
     } else {
@@ -622,8 +622,7 @@
   cache.type = 'split';
   cache.regExp = separator;
   cache.subject = subject;
-  // Reuse lastIndex field for split limit when type is "split".
-  cache.lastIndex = limit;
+  cache.splitLimit = limit;
 
   %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
 
diff --git a/src/strtod.cc b/src/strtod.cc
index bfbb5db..68444fc 100644
--- a/src/strtod.cc
+++ b/src/strtod.cc
@@ -43,6 +43,14 @@
 // 2^64 = 18446744073709551616
 // Any integer with at most 19 digits will hence fit into a 64bit datatype.
 static const int kMaxUint64DecimalDigits = 19;
+// Max double: 1.7976931348623157 x 10^308
+// Min non-zero double: 4.9406564584124654 x 10^-324
+// Any x >= 10^309 is interpreted as +infinity.
+// Any x <= 10^-324 is interpreted as 0.
+// Note that 2.5e-324 (despite being smaller than the min double) will be read
+// as non-zero (equal to the min non-zero double).
+static const int kMaxDecimalPower = 309;
+static const int kMinDecimalPower = -324;
 
 static const double exact_powers_of_ten[] = {
   1.0,  // 10^0
@@ -76,26 +84,50 @@
 
 extern "C" double gay_strtod(const char* s00, const char** se);
 
-static double old_strtod(Vector<char> buffer, int exponent) {
+static double old_strtod(Vector<const char> buffer, int exponent) {
   char gay_buffer[1024];
   Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer));
-  buffer.start()[buffer.length()] = '\0';
-  OS::SNPrintF(gay_buffer_vector, "%se%d", buffer.start(), exponent);
+  int pos = 0;
+  for (int i = 0; i < buffer.length(); ++i) {
+    gay_buffer_vector[pos++] = buffer[i];
+  }
+  gay_buffer_vector[pos++] = 'e';
+  if (exponent < 0) {
+    gay_buffer_vector[pos++] = '-';
+    exponent = -exponent;
+  }
+  const int kNumberOfExponentDigits = 5;
+  for (int i = kNumberOfExponentDigits - 1; i >= 0; i--) {
+    gay_buffer_vector[pos + i] = exponent % 10 + '0';
+    exponent /= 10;
+  }
+  pos += kNumberOfExponentDigits;
+  gay_buffer_vector[pos] = '\0';
   return gay_strtod(gay_buffer, NULL);
 }
 
 
-static Vector<char> TrimTrailingZeros(Vector<char> buffer) {
-  for (int i = buffer.length() - 1; i >= 0; --i) {
+static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
+  for (int i = 0; i < buffer.length(); i++) {
     if (buffer[i] != '0') {
-      return Vector<char>(buffer.start(), i + 1);
+      return Vector<const char>(buffer.start() + i, buffer.length() - i);
     }
   }
-  return Vector<char>(buffer.start(), 0);
+  return Vector<const char>(buffer.start(), 0);
 }
 
 
-uint64_t ReadUint64(Vector<char> buffer) {
+static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
+  for (int i = buffer.length() - 1; i >= 0; --i) {
+    if (buffer[i] != '0') {
+      return Vector<const char>(buffer.start(), i + 1);
+    }
+  }
+  return Vector<const char>(buffer.start(), 0);
+}
+
+
+uint64_t ReadUint64(Vector<const char> buffer) {
   ASSERT(buffer.length() <= kMaxUint64DecimalDigits);
   uint64_t result = 0;
   for (int i = 0; i < buffer.length(); ++i) {
@@ -107,10 +139,13 @@
 }
 
 
-double Strtod(Vector<char> buffer, int exponent) {
-  Vector<char> trimmed = TrimTrailingZeros(buffer);
+double Strtod(Vector<const char> buffer, int exponent) {
+  Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
+  Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
+  exponent += left_trimmed.length() - trimmed.length();
   if (trimmed.length() == 0) return 0.0;
-  exponent += buffer.length() - trimmed.length();
+  if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
+  if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
   if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
     // The trimmed input fits into a double.
     // If the 10^exponent (resp. 10^-exponent) fits into a double too then we
diff --git a/src/strtod.h b/src/strtod.h
index 4d256ba..1a5a96c 100644
--- a/src/strtod.h
+++ b/src/strtod.h
@@ -33,7 +33,7 @@
 
 // The buffer must only contain digits in the range [0-9]. It must not
 // contain a dot or a sign. It must not start with '0', and must not be empty.
-double Strtod(Vector<char> buffer, int exponent);
+double Strtod(Vector<const char> buffer, int exponent);
 
 } }  // namespace v8::internal
 
diff --git a/src/v8.cc b/src/v8.cc
index 2313967..b30564a 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -68,7 +68,7 @@
   OS::Setup();
 
   // Initialize other runtime facilities
-#if !V8_HOST_ARCH_ARM && V8_TARGET_ARCH_ARM
+#if (defined(USE_SIMULATOR) || !V8_HOST_ARCH_ARM) && V8_TARGET_ARCH_ARM
   ::assembler::arm::Simulator::Initialize();
 #endif
 
diff --git a/src/v8natives.js b/src/v8natives.js
index ca1c99d..88aea9c 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -547,11 +547,11 @@
 
   if (!IS_UNDEFINED(current) && !current.isConfigurable()) {
     // Step 5 and 6
-    if ((!desc.hasEnumerable() || 
+    if ((!desc.hasEnumerable() ||
          SameValue(desc.isEnumerable() && current.isEnumerable())) &&
-        (!desc.hasConfigurable() || 
+        (!desc.hasConfigurable() ||
          SameValue(desc.isConfigurable(), current.isConfigurable())) &&
-        (!desc.hasWritable() || 
+        (!desc.hasWritable() ||
          SameValue(desc.isWritable(), current.isWritable())) &&
         (!desc.hasValue() ||
          SameValue(desc.getValue(), current.getValue())) &&
@@ -755,7 +755,7 @@
     var desc = GetOwnProperty(obj, name);
     if (desc.isConfigurable()) desc.setConfigurable(false);
     DefineOwnProperty(obj, name, desc, true);
-  }  
+  }
   return ObjectPreventExtension(obj);
 }
 
@@ -772,7 +772,7 @@
     if (IsDataDescriptor(desc)) desc.setWritable(false);
     if (desc.isConfigurable()) desc.setConfigurable(false);
     DefineOwnProperty(obj, name, desc, true);
-  }  
+  }
   return ObjectPreventExtension(obj);
 }
 
@@ -1118,12 +1118,12 @@
     var bound_args = new $Array(argc_bound);
     for(var i = 0; i < argc_bound; i++) {
       bound_args[i] = %_Arguments(i+1);
-    }  
+    }
   }
   var fn = this;
   var result = function() {
     // Combine the args we got from the bind call with the args
-    // given as argument to the invocation. 
+    // given as argument to the invocation.
     var argc = %_ArgumentsLength();
     var args = new $Array(argc + argc_bound);
     // Add bound arguments.
@@ -1132,7 +1132,7 @@
     }
     // Add arguments from call.
     for (var i = 0; i < argc; i++) {
-      args[argc_bound + i] = %_Arguments(i); 
+      args[argc_bound + i] = %_Arguments(i);
     }
     // If this is a construct call we use a special runtime method
     // to generate the actual object using the bound function.
@@ -1147,7 +1147,7 @@
   // try to redefine these as defined by the spec. The spec says
   // that bind should make these throw a TypeError if get or set
   // is called and make them non-enumerable and non-configurable.
-  // To be consistent with our normal functions we leave this as it is. 
+  // To be consistent with our normal functions we leave this as it is.
 
   // Set the correct length.
   var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0;
diff --git a/src/version.cc b/src/version.cc
index 03bf986..33b4977 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -33,8 +33,8 @@
 // NOTE these macros are used by the SCons build script so their names
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
-#define MINOR_VERSION     4
-#define BUILD_NUMBER      9
+#define MINOR_VERSION     5
+#define BUILD_NUMBER      0
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index b050ec8..d592037 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1413,20 +1413,8 @@
         __ j(equal, &done);
       }
       __ SmiNeg(rax, rax, &done);
+      __ jmp(&slow);  // zero, if not handled above, and Smi::kMinValue.
 
-      // Either zero or Smi::kMinValue, neither of which become a smi when
-      // negated. We handle negative zero here if required. We always enter
-      // the runtime system if we have Smi::kMinValue.
-      if (negative_zero_ == kStrictNegativeZero) {
-        __ SmiCompare(rax, Smi::FromInt(0));
-        __ j(not_equal, &slow);
-        __ Move(rax, Factory::minus_zero_value());
-        __ jmp(&done);
-      } else  {
-        __ SmiCompare(rax, Smi::FromInt(Smi::kMinValue));
-        __ j(equal, &slow);
-        __ jmp(&done);
-      }
       // Try floating point case.
       __ bind(&try_float);
     } else if (FLAG_debug_code) {
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 4ebf44a..7957324 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -584,9 +584,6 @@
 
   void CheckStack();
 
-  static InlineFunctionGenerator FindInlineFunctionGenerator(
-      Runtime::FunctionId function_id);
-
   bool CheckForInlineRuntimeCall(CallRuntime* node);
 
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 2256100..32d6242 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -61,6 +61,12 @@
   SetFunctionPosition(function());
   Comment cmnt(masm_, "[ function compiled by full code generator");
 
+#ifdef DEBUG
+  if (strlen(FLAG_stop_at) > 0 &&
+      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+    __ int3();
+  }
+#endif
   __ push(rbp);  // Caller's frame pointer.
   __ movq(rbp, rsp);
   __ push(rsi);  // Callee's context.