Version 3.2.10

Fixed bug in external float arrays on ARM (issue 1323).

Minor performance improvements and bug fixes.


git-svn-id: http://v8.googlecode.com/svn/trunk@7596 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index c2b2df8..a2373cd 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -4625,7 +4625,7 @@
 int V8::GetCurrentThreadId() {
   i::Isolate* isolate = i::Isolate::Current();
   EnsureInitializedForIsolate(isolate, "V8::GetCurrentThreadId()");
-  return isolate->thread_id();
+  return isolate->thread_id().ToInteger();
 }
 
 
@@ -4636,10 +4636,11 @@
   // If the thread_id identifies the current thread just terminate
   // execution right away.  Otherwise, ask the thread manager to
   // terminate the thread with the given id if any.
-  if (thread_id == isolate->thread_id()) {
+  i::ThreadId internal_tid = i::ThreadId::FromInteger(thread_id);
+  if (isolate->thread_id().Equals(internal_tid)) {
     isolate->stack_guard()->TerminateExecution();
   } else {
-    isolate->thread_manager()->TerminateExecution(thread_id);
+    isolate->thread_manager()->TerminateExecution(internal_tid);
   }
 }
 
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 73dddfd..fd8e8b5 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -59,12 +59,12 @@
 #endif  // def CAN_USE_ARMV7_INSTRUCTIONS
   // If the compiler is allowed to use VFP then we can use VFP too in our code
   // generation even when generating snapshots.  This won't work for cross
-  // compilation.
+  // compilation. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
 #if defined(__VFP_FP__) && !defined(__SOFTFP__)
-  answer |= 1u << VFP3;
+  answer |= 1u << VFP3 | 1u << ARMv7;
 #endif  // defined(__VFP_FP__) && !defined(__SOFTFP__)
 #ifdef CAN_USE_VFP_INSTRUCTIONS
-  answer |= 1u << VFP3;
+  answer |= 1u << VFP3 | 1u << ARMv7;
 #endif  // def CAN_USE_VFP_INSTRUCTIONS
   return answer;
 }
@@ -77,9 +77,10 @@
   initialized_ = true;
 #endif
 #ifndef __arm__
-  // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is enabled.
+  // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is
+  // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
   if (FLAG_enable_vfp3) {
-    supported_ |= 1u << VFP3;
+    supported_ |= 1u << VFP3 | 1u << ARMv7;
   }
   // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
   if (FLAG_enable_armv7) {
@@ -93,10 +94,11 @@
   }
 
   if (OS::ArmCpuHasFeature(VFP3)) {
-    // This implementation also sets the VFP flags if
-    // runtime detection of VFP returns true.
-    supported_ |= 1u << VFP3;
-    found_by_runtime_probing_ |= 1u << VFP3;
+    // This implementation also sets the VFP flags if runtime
+    // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
+    // 0406B, page A1-6.
+    supported_ |= 1u << VFP3 | 1u << ARMv7;
+    found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7;
   }
 
   if (OS::ArmCpuHasFeature(ARMv7)) {
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 6af30c4..4912449 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2474,15 +2474,11 @@
   Register key = ToRegister(instr->key());
   ExternalArrayType array_type = instr->array_type();
   if (array_type == kExternalFloatArray) {
-    if (CpuFeatures::IsSupported(VFP3)) {
-      CpuFeatures::Scope scope(VFP3);
-      DwVfpRegister result(ToDoubleRegister(instr->result()));
-      __ add(scratch0(), external_pointer, Operand(key, LSL, 2));
-      __ vldr(result, scratch0(), 0);
-    } else {
-      Register result(ToRegister(instr->result()));
-      __ ldr(result, MemOperand(external_pointer, key, LSL, 2));
-    }
+    CpuFeatures::Scope scope(VFP3);
+    DwVfpRegister result(ToDoubleRegister(instr->result()));
+    __ add(scratch0(), external_pointer, Operand(key, LSL, 2));
+    __ vldr(result.low(), scratch0(), 0);
+    __ vcvt_f64_f32(result, result.low());
   } else {
     Register result(ToRegister(instr->result()));
     switch (array_type) {
@@ -3182,15 +3178,11 @@
   Register key = ToRegister(instr->key());
   ExternalArrayType array_type = instr->array_type();
   if (array_type == kExternalFloatArray) {
-    if (CpuFeatures::IsSupported(VFP3)) {
-      CpuFeatures::Scope scope(VFP3);
-      DwVfpRegister value(ToDoubleRegister(instr->value()));
-      __ add(scratch0(), external_pointer, Operand(key, LSL, 2));
-      __ vstr(value, scratch0(), 0);
-    } else {
-      Register value(ToRegister(instr->value()));
-      __ str(value, MemOperand(external_pointer, key, LSL, 2));
-    }
+    CpuFeatures::Scope scope(VFP3);
+    DwVfpRegister value(ToDoubleRegister(instr->value()));
+    __ add(scratch0(), external_pointer, Operand(key, LSL, 2));
+    __ vcvt_f32_f64(double_scratch0().low(), value);
+    __ vstr(double_scratch0().low(), scratch0(), 0);
   } else {
     Register value(ToRegister(instr->value()));
     switch (array_type) {
diff --git a/src/ast.cc b/src/ast.cc
index 6ea8c27..7ae0f34 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -349,6 +349,143 @@
 // ----------------------------------------------------------------------------
 // Inlining support
 
+bool Declaration::IsInlineable() const {
+  UNREACHABLE();
+  return false;
+}
+
+
+bool TargetCollector::IsInlineable() const {
+  UNREACHABLE();
+  return false;
+}
+
+
+bool Slot::IsInlineable() const {
+  UNREACHABLE();
+  return false;
+}
+
+
+bool ForInStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool WithEnterStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool WithExitStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool SwitchStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool TryStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool TryCatchStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool TryFinallyStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool CatchExtensionObject::IsInlineable() const {
+  return false;
+}
+
+
+bool DebuggerStatement::IsInlineable() const {
+  return false;
+}
+
+
+bool Throw::IsInlineable() const {
+  // TODO(1143): Make functions containing throw inlineable.
+  return false;
+}
+
+
+bool MaterializedLiteral::IsInlineable() const {
+  // TODO(1322): Allow materialized literals.
+  return false;
+}
+
+
+bool FunctionLiteral::IsInlineable() const {
+  // TODO(1322): Allow materialized literals.
+  return false;
+}
+
+
+bool ThisFunction::IsInlineable() const {
+  return false;
+}
+
+
+bool SharedFunctionInfoLiteral::IsInlineable() const {
+  return false;
+}
+
+
+bool ValidLeftHandSideSentinel::IsInlineable() const {
+  UNREACHABLE();
+  return false;
+}
+
+
+bool ForStatement::IsInlineable() const {
+  return (init() == NULL || init()->IsInlineable())
+      && (cond() == NULL || cond()->IsInlineable())
+      && (next() == NULL || next()->IsInlineable())
+      && body()->IsInlineable();
+}
+
+
+bool WhileStatement::IsInlineable() const {
+  return cond()->IsInlineable()
+      && body()->IsInlineable();
+}
+
+
+bool DoWhileStatement::IsInlineable() const {
+  return cond()->IsInlineable()
+      && body()->IsInlineable();
+}
+
+
+bool ContinueStatement::IsInlineable() const {
+  return true;
+}
+
+
+bool BreakStatement::IsInlineable() const {
+  return true;
+}
+
+
+bool EmptyStatement::IsInlineable() const {
+  return true;
+}
+
+
+bool Literal::IsInlineable() const {
+  return true;
+}
+
+
 bool Block::IsInlineable() const {
   const int count = statements_.length();
   for (int i = 0; i < count; ++i) {
@@ -364,8 +501,9 @@
 
 
 bool IfStatement::IsInlineable() const {
-  return condition()->IsInlineable() && then_statement()->IsInlineable() &&
-      else_statement()->IsInlineable();
+  return condition()->IsInlineable()
+      && then_statement()->IsInlineable()
+      && else_statement()->IsInlineable();
 }
 
 
diff --git a/src/ast.h b/src/ast.h
index 7f52c88..65a25a9 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -159,7 +159,7 @@
   virtual Slot* AsSlot() { return NULL; }
 
   // True if the node is simple enough for us to inline calls containing it.
-  virtual bool IsInlineable() const { return false; }
+  virtual bool IsInlineable() const = 0;
 
   static int Count() { return Isolate::Current()->ast_node_count(); }
   static void ResetIds() { Isolate::Current()->set_ast_node_id(0); }
@@ -291,6 +291,7 @@
  public:
   virtual bool IsValidLeftHandSide() { return true; }
   virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
+  virtual bool IsInlineable() const;
 };
 
 
@@ -375,6 +376,7 @@
   VariableProxy* proxy() const { return proxy_; }
   Variable::Mode mode() const { return mode_; }
   FunctionLiteral* fun() const { return fun_; }  // may be NULL
+  virtual bool IsInlineable() const;
 
  private:
   VariableProxy* proxy_;
@@ -433,6 +435,8 @@
   virtual int ContinueId() const { return continue_id_; }
   int BackEdgeId() const { return back_edge_id_; }
 
+  virtual bool IsInlineable() const;
+
  private:
   Expression* cond_;
   int condition_position_;
@@ -459,6 +463,7 @@
   void set_may_have_function_literal(bool value) {
     may_have_function_literal_ = value;
   }
+  virtual bool IsInlineable() const;
 
   // Bailout support.
   virtual int ContinueId() const { return EntryId(); }
@@ -506,6 +511,7 @@
   bool is_fast_smi_loop() { return loop_variable_ != NULL; }
   Variable* loop_variable() { return loop_variable_; }
   void set_loop_variable(Variable* var) { loop_variable_ = var; }
+  virtual bool IsInlineable() const;
 
  private:
   Statement* init_;
@@ -533,6 +539,7 @@
 
   Expression* each() const { return each_; }
   Expression* enumerable() const { return enumerable_; }
+  virtual bool IsInlineable() const;
 
   // Bailout support.
   int AssignmentId() const { return assignment_id_; }
@@ -573,6 +580,7 @@
   DECLARE_NODE_TYPE(ContinueStatement)
 
   IterationStatement* target() const { return target_; }
+  virtual bool IsInlineable() const;
 
  private:
   IterationStatement* target_;
@@ -587,6 +595,7 @@
   DECLARE_NODE_TYPE(BreakStatement)
 
   BreakableStatement* target() const { return target_; }
+  virtual bool IsInlineable() const;
 
  private:
   BreakableStatement* target_;
@@ -618,6 +627,7 @@
   Expression* expression() const { return expression_; }
 
   bool is_catch_block() const { return is_catch_block_; }
+  virtual bool IsInlineable() const;
 
  private:
   Expression* expression_;
@@ -629,6 +639,8 @@
  public:
   WithExitStatement() { }
 
+  virtual bool IsInlineable() const;
+
   DECLARE_NODE_TYPE(WithExitStatement)
 };
 
@@ -679,6 +691,7 @@
 
   Expression* tag() const { return tag_; }
   ZoneList<CaseClause*>* cases() const { return cases_; }
+  virtual bool IsInlineable() const;
 
  private:
   Expression* tag_;
@@ -744,6 +757,7 @@
   virtual TargetCollector* AsTargetCollector() { return this; }
 
   ZoneList<Label*>* targets() { return targets_; }
+  virtual bool IsInlineable() const;
 
  private:
   ZoneList<Label*>* targets_;
@@ -761,6 +775,7 @@
 
   Block* try_block() const { return try_block_; }
   ZoneList<Label*>* escaping_targets() const { return escaping_targets_; }
+  virtual bool IsInlineable() const;
 
  private:
   Block* try_block_;
@@ -782,6 +797,7 @@
 
   VariableProxy* catch_var() const { return catch_var_; }
   Block* catch_block() const { return catch_block_; }
+  virtual bool IsInlineable() const;
 
  private:
   VariableProxy* catch_var_;
@@ -798,6 +814,7 @@
   DECLARE_NODE_TYPE(TryFinallyStatement)
 
   Block* finally_block() const { return finally_block_; }
+  virtual bool IsInlineable() const;
 
  private:
   Block* finally_block_;
@@ -807,6 +824,7 @@
 class DebuggerStatement: public Statement {
  public:
   DECLARE_NODE_TYPE(DebuggerStatement)
+  virtual bool IsInlineable() const;
 };
 
 
@@ -814,7 +832,7 @@
  public:
   DECLARE_NODE_TYPE(EmptyStatement)
 
-  virtual bool IsInlineable() const { return true; }
+  virtual bool IsInlineable() const;
 };
 
 
@@ -825,7 +843,6 @@
   DECLARE_NODE_TYPE(Literal)
 
   virtual bool IsTrivial() { return true; }
-  virtual bool IsInlineable() const { return true; }
   virtual bool IsSmiLiteral() { return handle_->IsSmi(); }
 
   // Check if this literal is identical to the other literal.
@@ -864,6 +881,7 @@
   }
 
   Handle<Object> handle() const { return handle_; }
+  virtual bool IsInlineable() const;
 
  private:
   Handle<Object> handle_;
@@ -885,6 +903,7 @@
   bool is_simple() const { return is_simple_; }
 
   int depth() const { return depth_; }
+  virtual bool IsInlineable() const;
 
  private:
   int literal_index_;
@@ -1034,6 +1053,7 @@
 
   Literal* key() const { return key_; }
   VariableProxy* value() const { return value_; }
+  virtual bool IsInlineable() const;
 
  private:
   Literal* key_;
@@ -1160,6 +1180,7 @@
   Type type() const { return type_; }
   int index() const { return index_; }
   bool is_arguments() const { return var_->is_arguments(); }
+  virtual bool IsInlineable() const;
 
  private:
   Variable* var_;
@@ -1643,6 +1664,7 @@
 
   Expression* exception() const { return exception_; }
   virtual int position() const { return pos_; }
+  virtual bool IsInlineable() const;
 
  private:
   Expression* exception_;
@@ -1715,6 +1737,7 @@
 
   bool pretenure() { return pretenure_; }
   void set_pretenure(bool value) { pretenure_ = value; }
+  virtual bool IsInlineable() const;
 
  private:
   Handle<String> name_;
@@ -1745,6 +1768,7 @@
   Handle<SharedFunctionInfo> shared_function_info() const {
     return shared_function_info_;
   }
+  virtual bool IsInlineable() const;
 
  private:
   Handle<SharedFunctionInfo> shared_function_info_;
@@ -1754,6 +1778,7 @@
 class ThisFunction: public Expression {
  public:
   DECLARE_NODE_TYPE(ThisFunction)
+  virtual bool IsInlineable() const;
 };
 
 
diff --git a/src/conversions.cc b/src/conversions.cc
index c3d7bdf..1458584 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -109,11 +109,11 @@
 
 // Returns true if a nonspace found and false if the end has reached.
 template <class Iterator, class EndMark>
-static inline bool AdvanceToNonspace(ScannerConstants* scanner_constants,
+static inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
                                      Iterator* current,
                                      EndMark end) {
   while (*current != end) {
-    if (!scanner_constants->IsWhiteSpace(**current)) return true;
+    if (!unicode_cache->IsWhiteSpace(**current)) return true;
     ++*current;
   }
   return false;
@@ -134,7 +134,7 @@
 
 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
 template <int radix_log_2, class Iterator, class EndMark>
-static double InternalStringToIntDouble(ScannerConstants* scanner_constants,
+static double InternalStringToIntDouble(UnicodeCache* unicode_cache,
                                         Iterator current,
                                         EndMark end,
                                         bool negative,
@@ -161,7 +161,7 @@
       digit = static_cast<char>(*current) - 'A' + 10;
     } else {
       if (allow_trailing_junk ||
-          !AdvanceToNonspace(scanner_constants, &current, end)) {
+          !AdvanceToNonspace(unicode_cache, &current, end)) {
         break;
       } else {
         return JUNK_STRING_VALUE;
@@ -193,7 +193,7 @@
       }
 
       if (!allow_trailing_junk &&
-          AdvanceToNonspace(scanner_constants, &current, end)) {
+          AdvanceToNonspace(unicode_cache, &current, end)) {
         return JUNK_STRING_VALUE;
       }
 
@@ -237,14 +237,14 @@
 
 
 template <class Iterator, class EndMark>
-static double InternalStringToInt(ScannerConstants* scanner_constants,
+static double InternalStringToInt(UnicodeCache* unicode_cache,
                                   Iterator current,
                                   EndMark end,
                                   int radix) {
   const bool allow_trailing_junk = true;
   const double empty_string_val = JUNK_STRING_VALUE;
 
-  if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+  if (!AdvanceToNonspace(unicode_cache, &current, end)) {
     return empty_string_val;
   }
 
@@ -254,12 +254,12 @@
   if (*current == '+') {
     // Ignore leading sign; skip following spaces.
     ++current;
-    if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+    if (!AdvanceToNonspace(unicode_cache, &current, end)) {
       return JUNK_STRING_VALUE;
     }
   } else if (*current == '-') {
     ++current;
-    if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+    if (!AdvanceToNonspace(unicode_cache, &current, end)) {
       return JUNK_STRING_VALUE;
     }
     negative = true;
@@ -312,21 +312,21 @@
     switch (radix) {
       case 2:
         return InternalStringToIntDouble<1>(
-            scanner_constants, current, end, negative, allow_trailing_junk);
+            unicode_cache, current, end, negative, allow_trailing_junk);
       case 4:
         return InternalStringToIntDouble<2>(
-            scanner_constants, current, end, negative, allow_trailing_junk);
+            unicode_cache, current, end, negative, allow_trailing_junk);
       case 8:
         return InternalStringToIntDouble<3>(
-            scanner_constants, current, end, negative, allow_trailing_junk);
+            unicode_cache, current, end, negative, allow_trailing_junk);
 
       case 16:
         return InternalStringToIntDouble<4>(
-            scanner_constants, current, end, negative, allow_trailing_junk);
+            unicode_cache, current, end, negative, allow_trailing_junk);
 
       case 32:
         return InternalStringToIntDouble<5>(
-            scanner_constants, current, end, negative, allow_trailing_junk);
+            unicode_cache, current, end, negative, allow_trailing_junk);
       default:
         UNREACHABLE();
     }
@@ -352,7 +352,7 @@
     }
 
     if (!allow_trailing_junk &&
-        AdvanceToNonspace(scanner_constants, &current, end)) {
+        AdvanceToNonspace(unicode_cache, &current, end)) {
       return JUNK_STRING_VALUE;
     }
 
@@ -418,7 +418,7 @@
   } while (!done);
 
   if (!allow_trailing_junk &&
-      AdvanceToNonspace(scanner_constants, &current, end)) {
+      AdvanceToNonspace(unicode_cache, &current, end)) {
     return JUNK_STRING_VALUE;
   }
 
@@ -432,7 +432,7 @@
 // 2. *current - gets the current character in the sequence.
 // 3. ++current (advances the position).
 template <class Iterator, class EndMark>
-static double InternalStringToDouble(ScannerConstants* scanner_constants,
+static double InternalStringToDouble(UnicodeCache* unicode_cache,
                                      Iterator current,
                                      EndMark end,
                                      int flags,
@@ -445,7 +445,7 @@
   // 'parsing_done'.
   // 4. 'current' is not dereferenced after the 'parsing_done' label.
   // 5. Code before 'parsing_done' may rely on 'current != end'.
-  if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+  if (!AdvanceToNonspace(unicode_cache, &current, end)) {
     return empty_string_val;
   }
 
@@ -483,7 +483,7 @@
     }
 
     if (!allow_trailing_junk &&
-        AdvanceToNonspace(scanner_constants, &current, end)) {
+        AdvanceToNonspace(unicode_cache, &current, end)) {
       return JUNK_STRING_VALUE;
     }
 
@@ -505,7 +505,7 @@
         return JUNK_STRING_VALUE;  // "0x".
       }
 
-      return InternalStringToIntDouble<4>(scanner_constants,
+      return InternalStringToIntDouble<4>(unicode_cache,
                                           current,
                                           end,
                                           negative,
@@ -643,7 +643,7 @@
   }
 
   if (!allow_trailing_junk &&
-      AdvanceToNonspace(scanner_constants, &current, end)) {
+      AdvanceToNonspace(unicode_cache, &current, end)) {
     return JUNK_STRING_VALUE;
   }
 
@@ -651,7 +651,7 @@
   exponent += insignificant_digits;
 
   if (octal) {
-    return InternalStringToIntDouble<3>(scanner_constants,
+    return InternalStringToIntDouble<3>(unicode_cache,
                                         buffer,
                                         buffer + buffer_pos,
                                         negative,
@@ -671,23 +671,22 @@
 }
 
 
-double StringToDouble(String* str, int flags, double empty_string_val) {
-  ScannerConstants* scanner_constants =
-      Isolate::Current()->scanner_constants();
+double StringToDouble(UnicodeCache* unicode_cache,
+                      String* str, int flags, double empty_string_val) {
   StringShape shape(str);
   if (shape.IsSequentialAscii()) {
     const char* begin = SeqAsciiString::cast(str)->GetChars();
     const char* end = begin + str->length();
-    return InternalStringToDouble(scanner_constants, begin, end, flags,
+    return InternalStringToDouble(unicode_cache, begin, end, flags,
                                   empty_string_val);
   } else if (shape.IsSequentialTwoByte()) {
     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
     const uc16* end = begin + str->length();
-    return InternalStringToDouble(scanner_constants, begin, end, flags,
+    return InternalStringToDouble(unicode_cache, begin, end, flags,
                                   empty_string_val);
   } else {
     StringInputBuffer buffer(str);
-    return InternalStringToDouble(scanner_constants,
+    return InternalStringToDouble(unicode_cache,
                                   StringInputBufferIterator(&buffer),
                                   StringInputBufferIterator::EndMarker(),
                                   flags,
@@ -696,21 +695,21 @@
 }
 
 
-double StringToInt(String* str, int radix) {
-  ScannerConstants* scanner_constants =
-      Isolate::Current()->scanner_constants();
+double StringToInt(UnicodeCache* unicode_cache,
+                   String* str,
+                   int radix) {
   StringShape shape(str);
   if (shape.IsSequentialAscii()) {
     const char* begin = SeqAsciiString::cast(str)->GetChars();
     const char* end = begin + str->length();
-    return InternalStringToInt(scanner_constants, begin, end, radix);
+    return InternalStringToInt(unicode_cache, begin, end, radix);
   } else if (shape.IsSequentialTwoByte()) {
     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
     const uc16* end = begin + str->length();
-    return InternalStringToInt(scanner_constants, begin, end, radix);
+    return InternalStringToInt(unicode_cache, begin, end, radix);
   } else {
     StringInputBuffer buffer(str);
-    return InternalStringToInt(scanner_constants,
+    return InternalStringToInt(unicode_cache,
                                StringInputBufferIterator(&buffer),
                                StringInputBufferIterator::EndMarker(),
                                radix);
@@ -718,22 +717,20 @@
 }
 
 
-double StringToDouble(const char* str, int flags, double empty_string_val) {
-  ScannerConstants* scanner_constants =
-      Isolate::Current()->scanner_constants();
+double StringToDouble(UnicodeCache* unicode_cache,
+                      const char* str, int flags, double empty_string_val) {
   const char* end = str + StrLength(str);
-  return InternalStringToDouble(scanner_constants, str, end, flags,
+  return InternalStringToDouble(unicode_cache, str, end, flags,
                                 empty_string_val);
 }
 
 
-double StringToDouble(Vector<const char> str,
+double StringToDouble(UnicodeCache* unicode_cache,
+                      Vector<const char> str,
                       int flags,
                       double empty_string_val) {
-  ScannerConstants* scanner_constants =
-      Isolate::Current()->scanner_constants();
   const char* end = str.start() + str.length();
-  return InternalStringToDouble(scanner_constants, str.start(), end, flags,
+  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
                                 empty_string_val);
 }
 
diff --git a/src/conversions.h b/src/conversions.h
index 312e6ae..a14dc9a 100644
--- a/src/conversions.h
+++ b/src/conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -28,6 +28,8 @@
 #ifndef V8_CONVERSIONS_H_
 #define V8_CONVERSIONS_H_
 
+#include "scanner-base.h"
+
 namespace v8 {
 namespace internal {
 
@@ -91,15 +93,22 @@
 
 
 // Converts a string into a double value according to ECMA-262 9.3.1
-double StringToDouble(String* str, int flags, double empty_string_val = 0);
-double StringToDouble(Vector<const char> str,
+double StringToDouble(UnicodeCache* unicode_cache,
+                      String* str,
+                      int flags,
+                      double empty_string_val = 0);
+double StringToDouble(UnicodeCache* unicode_cache,
+                      Vector<const char> str,
                       int flags,
                       double empty_string_val = 0);
 // This version expects a zero-terminated character array.
-double StringToDouble(const char* str, int flags, double empty_string_val = 0);
+double StringToDouble(UnicodeCache* unicode_cache,
+                      const char* str,
+                      int flags,
+                      double empty_string_val = 0);
 
 // Converts a string into an integer.
-double StringToInt(String* str, int radix);
+double StringToInt(UnicodeCache* unicode_cache, String* str, int radix);
 
 // Converts a double to a string value according to ECMA-262 9.8.1.
 // The buffer should be large enough for any floating point number.
diff --git a/src/dateparser-inl.h b/src/dateparser-inl.h
index ac28c62..7f8fac8 100644
--- a/src/dateparser-inl.h
+++ b/src/dateparser-inl.h
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -34,9 +34,11 @@
 namespace internal {
 
 template <typename Char>
-bool DateParser::Parse(Vector<Char> str, FixedArray* out) {
+bool DateParser::Parse(Vector<Char> str,
+                       FixedArray* out,
+                       UnicodeCache* unicode_cache) {
   ASSERT(out->length() >= OUTPUT_SIZE);
-  InputReader<Char> in(str);
+  InputReader<Char> in(unicode_cache, str);
   TimeZoneComposer tz;
   TimeComposer time;
   DayComposer day;
diff --git a/src/dateparser.h b/src/dateparser.h
index 51109ee..9d29715 100644
--- a/src/dateparser.h
+++ b/src/dateparser.h
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -49,7 +49,7 @@
   // [7]: UTC offset in seconds, or null value if no timezone specified
   // If parsing fails, return false (content of output array is not defined).
   template <typename Char>
-  static bool Parse(Vector<Char> str, FixedArray* output);
+  static bool Parse(Vector<Char> str, FixedArray* output, UnicodeCache* cache);
 
   enum {
     YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND, UTC_OFFSET, OUTPUT_SIZE
@@ -67,11 +67,11 @@
   template <typename Char>
   class InputReader BASE_EMBEDDED {
    public:
-    explicit InputReader(Vector<Char> s)
+    InputReader(UnicodeCache* unicode_cache, Vector<Char> s)
         : index_(0),
           buffer_(s),
           has_read_number_(false),
-          scanner_constants_(Isolate::Current()->scanner_constants()) {
+          unicode_cache_(unicode_cache) {
       Next();
     }
 
@@ -122,7 +122,7 @@
     }
 
     bool SkipWhiteSpace() {
-      if (scanner_constants_->IsWhiteSpace(ch_)) {
+      if (unicode_cache_->IsWhiteSpace(ch_)) {
         Next();
         return true;
       }
@@ -158,7 +158,7 @@
     Vector<Char> buffer_;
     bool has_read_number_;
     uint32_t ch_;
-    ScannerConstants* scanner_constants_;
+    UnicodeCache* unicode_cache_;
   };
 
   enum KeywordType { INVALID, MONTH_NAME, TIME_ZONE_NAME, AM_PM };
diff --git a/src/extensions/experimental/experimental.gyp b/src/extensions/experimental/experimental.gyp
index 761f4c7..a8585fd 100644
--- a/src/extensions/experimental/experimental.gyp
+++ b/src/extensions/experimental/experimental.gyp
@@ -41,6 +41,7 @@
         'break-iterator.h',
         'i18n-extension.cc',
         'i18n-extension.h',
+	'<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc',
       ],
       'include_dirs': [
         '<(icu_src_dir)/public/common',
@@ -48,8 +49,39 @@
       ],
       'dependencies': [
         '<(icu_src_dir)/icu.gyp:*',
+	'js2c_i18n#host',
         '../../../tools/gyp/v8.gyp:v8',
       ],
     },
+    {
+      'target_name': 'js2c_i18n',
+      'type': 'none',
+      'toolsets': ['host'],
+      'variables': {
+        'library_files': [
+	  'i18n.js'
+	],
+      },
+      'actions': [
+        {
+	  'action_name': 'js2c_i18n',
+	  'inputs': [
+	    '../../../tools/js2c.py',
+	    '<@(library_files)',
+	  ],
+	  'outputs': [
+	    '<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc',
+	    '<(SHARED_INTERMEDIATE_DIR)/i18n-js-empty.cc'
+	  ],
+	  'action': [
+	    'python',
+	    '../../../tools/js2c.py',
+	    '<@(_outputs)',
+	    'I18N',
+	    '<@(library_files)'
+	  ],
+	},
+      ],
+    },
   ],  # targets
 }
diff --git a/src/extensions/experimental/i18n-extension.cc b/src/extensions/experimental/i18n-extension.cc
index f14fd9e..6e3ab15 100644
--- a/src/extensions/experimental/i18n-extension.cc
+++ b/src/extensions/experimental/i18n-extension.cc
@@ -31,6 +31,7 @@
 #include <string>
 
 #include "break-iterator.h"
+#include "natives.h"
 #include "unicode/locid.h"
 #include "unicode/uloc.h"
 
@@ -39,73 +40,19 @@
 
 I18NExtension* I18NExtension::extension_ = NULL;
 
-// TODO(cira): maybe move JS code to a .js file and generata cc files from it?
-// TODO(cira): Remove v8 prefix from v8Locale once we have stable API.
-const char* const I18NExtension::kSource =
-  "v8Locale = function(optLocale) {"
-  "  native function NativeJSLocale();"
-  "  var properties = NativeJSLocale(optLocale);"
-  "  this.locale = properties.locale;"
-  "  this.language = properties.language;"
-  "  this.script = properties.script;"
-  "  this.region = properties.region;"
-  "};"
-  "v8Locale.availableLocales = function() {"
-  "  native function NativeJSAvailableLocales();"
-  "  return NativeJSAvailableLocales();"
-  "};"
-  "v8Locale.prototype.maximizedLocale = function() {"
-  "  native function NativeJSMaximizedLocale();"
-  "  return new v8Locale(NativeJSMaximizedLocale(this.locale));"
-  "};"
-  "v8Locale.prototype.minimizedLocale = function() {"
-  "  native function NativeJSMinimizedLocale();"
-  "  return new v8Locale(NativeJSMinimizedLocale(this.locale));"
-  "};"
-  "v8Locale.prototype.displayLocale_ = function(displayLocale) {"
-  "  var result = this.locale;"
-  "  if (displayLocale !== undefined) {"
-  "    result = displayLocale.locale;"
-  "  }"
-  "  return result;"
-  "};"
-  "v8Locale.prototype.displayLanguage = function(optDisplayLocale) {"
-  "  var displayLocale = this.displayLocale_(optDisplayLocale);"
-  "  native function NativeJSDisplayLanguage();"
-  "  return NativeJSDisplayLanguage(this.locale, displayLocale);"
-  "};"
-  "v8Locale.prototype.displayScript = function(optDisplayLocale) {"
-  "  var displayLocale = this.displayLocale_(optDisplayLocale);"
-  "  native function NativeJSDisplayScript();"
-  "  return NativeJSDisplayScript(this.locale, displayLocale);"
-  "};"
-  "v8Locale.prototype.displayRegion = function(optDisplayLocale) {"
-  "  var displayLocale = this.displayLocale_(optDisplayLocale);"
-  "  native function NativeJSDisplayRegion();"
-  "  return NativeJSDisplayRegion(this.locale, displayLocale);"
-  "};"
-  "v8Locale.prototype.displayName = function(optDisplayLocale) {"
-  "  var displayLocale = this.displayLocale_(optDisplayLocale);"
-  "  native function NativeJSDisplayName();"
-  "  return NativeJSDisplayName(this.locale, displayLocale);"
-  "};"
-  "v8Locale.v8BreakIterator = function(locale, type) {"
-  "  native function NativeJSBreakIterator();"
-  "  var iterator = NativeJSBreakIterator(locale, type);"
-  "  iterator.type = type;"
-  "  return iterator;"
-  "};"
-  "v8Locale.v8BreakIterator.BreakType = {"
-  "  'unknown': -1,"
-  "  'none': 0,"
-  "  'number': 100,"
-  "  'word': 200,"
-  "  'kana': 300,"
-  "  'ideo': 400"
-  "};"
-  "v8Locale.prototype.v8CreateBreakIterator = function(type) {"
-  "  return new v8Locale.v8BreakIterator(this.locale, type);"
-  "};";
+// Returns a pointer to static string containing the actual
+// JavaScript code generated from i18n.js file.
+static const char* GetScriptSource() {
+  int index = NativesCollection<I18N>::GetIndex("i18n");
+  Vector<const char> script_data =
+      NativesCollection<I18N>::GetScriptSource(index);
+
+  return script_data.start();
+}
+
+I18NExtension::I18NExtension()
+    : v8::Extension("v8/i18n", GetScriptSource()) {
+}
 
 v8::Handle<v8::FunctionTemplate> I18NExtension::GetNativeFunction(
     v8::Handle<v8::String> name) {
diff --git a/src/extensions/experimental/i18n-extension.h b/src/extensions/experimental/i18n-extension.h
index 629332b..54c973f 100644
--- a/src/extensions/experimental/i18n-extension.h
+++ b/src/extensions/experimental/i18n-extension.h
@@ -36,7 +36,8 @@
 
 class I18NExtension : public v8::Extension {
  public:
-  I18NExtension() : v8::Extension("v8/i18n", kSource) {}
+  I18NExtension();
+
   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
       v8::Handle<v8::String> name);
 
@@ -55,7 +56,6 @@
   static I18NExtension* get();
 
  private:
-  static const char* const kSource;
   static I18NExtension* extension_;
 };
 
diff --git a/src/extensions/experimental/i18n.js b/src/extensions/experimental/i18n.js
new file mode 100644
index 0000000..baf3859
--- /dev/null
+++ b/src/extensions/experimental/i18n.js
@@ -0,0 +1,103 @@
+// Copyright 2006-2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// TODO(cira): Remove v8 prefix from v8Locale once we have stable API.
+v8Locale = function(optLocale) {
+  native function NativeJSLocale();
+  var properties = NativeJSLocale(optLocale);
+  this.locale = properties.locale;
+  this.language = properties.language;
+  this.script = properties.script;
+  this.region = properties.region;
+};
+
+v8Locale.availableLocales = function() {
+  native function NativeJSAvailableLocales();
+  return NativeJSAvailableLocales();
+};
+
+v8Locale.prototype.maximizedLocale = function() {
+  native function NativeJSMaximizedLocale();
+  return new v8Locale(NativeJSMaximizedLocale(this.locale));
+};
+
+v8Locale.prototype.minimizedLocale = function() {
+  native function NativeJSMinimizedLocale();
+  return new v8Locale(NativeJSMinimizedLocale(this.locale));
+};
+
+v8Locale.prototype.displayLocale_ = function(displayLocale) {
+  var result = this.locale;
+  if (displayLocale !== undefined) {
+    result = displayLocale.locale;
+  }
+  return result;
+};
+
+v8Locale.prototype.displayLanguage = function(optDisplayLocale) {
+  var displayLocale = this.displayLocale_(optDisplayLocale);
+  native function NativeJSDisplayLanguage();
+  return NativeJSDisplayLanguage(this.locale, displayLocale);
+};
+
+v8Locale.prototype.displayScript = function(optDisplayLocale) {
+  var displayLocale = this.displayLocale_(optDisplayLocale);
+  native function NativeJSDisplayScript();
+  return NativeJSDisplayScript(this.locale, displayLocale);
+};
+
+v8Locale.prototype.displayRegion = function(optDisplayLocale) {
+  var displayLocale = this.displayLocale_(optDisplayLocale);
+  native function NativeJSDisplayRegion();
+  return NativeJSDisplayRegion(this.locale, displayLocale);
+};
+
+v8Locale.prototype.displayName = function(optDisplayLocale) {
+  var displayLocale = this.displayLocale_(optDisplayLocale);
+  native function NativeJSDisplayName();
+  return NativeJSDisplayName(this.locale, displayLocale);
+};
+
+v8Locale.v8BreakIterator = function(locale, type) {
+  native function NativeJSBreakIterator();
+  var iterator = NativeJSBreakIterator(locale, type);
+  iterator.type = type;
+  return iterator;
+};
+
+v8Locale.v8BreakIterator.BreakType = {
+  'unknown': -1,
+  'none': 0,
+  'number': 100,
+  'word': 200,
+  'kana': 300,
+  'ideo': 400
+};
+
+v8Locale.prototype.v8CreateBreakIterator = function(type) {
+  return new v8Locale.v8BreakIterator(this.locale, type);
+};
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index d6cb6e3..15f8def 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -162,7 +162,8 @@
 DEFINE_bool(enable_sahf, true,
             "enable use of SAHF instruction if available (X64 only)")
 DEFINE_bool(enable_vfp3, true,
-            "enable use of VFP3 instructions if available (ARM only)")
+            "enable use of VFP3 instructions if available - this implies "
+            "enabling ARMv7 instructions (ARM only)")
 DEFINE_bool(enable_armv7, true,
             "enable use of ARMv7 instructions if available (ARM only)")
 DEFINE_bool(enable_fpu, true,
diff --git a/src/heap.cc b/src/heap.cc
index c77364b..9a3cfe4 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -3386,8 +3386,8 @@
   const uc32 kMaxSupportedChar = 0xFFFF;
   // Count the number of characters in the UTF-8 string and check if
   // it is an ASCII string.
-  Access<ScannerConstants::Utf8Decoder>
-      decoder(isolate_->scanner_constants()->utf8_decoder());
+  Access<UnicodeCache::Utf8Decoder>
+      decoder(isolate_->unicode_cache()->utf8_decoder());
   decoder->Reset(string.start(), string.length());
   int chars = 0;
   while (decoder->has_more()) {
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index c736553..a623775 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -274,7 +274,7 @@
     return kind_ == other.kind_;
   }
 
-  Kind kind() const { return kind_; }
+  Kind kind() const { return static_cast<Kind>(kind_); }
   bool IsNone() const { return kind_ == kNone; }
   bool IsTagged() const { return kind_ == kTagged; }
   bool IsInteger32() const { return kind_ == kInteger32; }
@@ -288,7 +288,10 @@
  private:
   explicit Representation(Kind k) : kind_(k) { }
 
-  Kind kind_;
+  // Make sure kind fits in int8.
+  STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
+
+  int8_t kind_;
 };
 
 
@@ -395,9 +398,12 @@
     kUninitialized = 0x1fff  // 0001 1111 1111 1111
   };
 
+  // Make sure type fits in int16.
+  STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
+
   explicit HType(Type t) : type_(t) { }
 
-  Type type_;
+  int16_t type_;
 };
 
 
@@ -611,8 +617,8 @@
   int id_;
 
   Representation representation_;
-  SmallPointerList<HValue> uses_;
   HType type_;
+  SmallPointerList<HValue> uses_;
   Range* range_;
   int flags_;
 
diff --git a/src/isolate.cc b/src/isolate.cc
index b8a7fb7..e42d78e 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -54,6 +54,21 @@
 namespace v8 {
 namespace internal {
 
+Atomic32 ThreadId::highest_thread_id_ = 0;
+
+int ThreadId::AllocateThreadId() {
+  int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
+  return new_id;
+}
+
+int ThreadId::GetCurrentThreadId() {
+  int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_);
+  if (thread_id == 0) {
+    thread_id = AllocateThreadId();
+    Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
+  }
+  return thread_id;
+}
 
 // Create a dummy thread that will wait forever on a semaphore. The only
 // purpose for this thread is to have some stack area to save essential data
@@ -245,7 +260,6 @@
 Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
 Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
-Isolate::ThreadId Isolate::highest_thread_id_ = 0;
 
 
 class IsolateInitializer {
@@ -265,20 +279,12 @@
 static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated();
 
 
-Isolate::ThreadId Isolate::AllocateThreadId() {
-  ThreadId new_id;
-  {
-    ScopedLock lock(process_wide_mutex_);
-    new_id = ++highest_thread_id_;
-  }
-  return new_id;
-}
+
 
 
 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
     ThreadId thread_id) {
-  ASSERT(thread_id != 0);
-  ASSERT(Thread::GetThreadLocalInt(thread_id_key_) == thread_id);
+  ASSERT(!thread_id.Equals(ThreadId::Invalid()));
   PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id);
   {
     ScopedLock lock(process_wide_mutex_);
@@ -292,11 +298,7 @@
 
 Isolate::PerIsolateThreadData*
     Isolate::FindOrAllocatePerThreadDataForThisThread() {
-  ThreadId thread_id = Thread::GetThreadLocalInt(thread_id_key_);
-  if (thread_id == 0) {
-    thread_id = AllocateThreadId();
-    Thread::SetThreadLocalInt(thread_id_key_, thread_id);
-  }
+  ThreadId thread_id = ThreadId::Current();
   PerIsolateThreadData* per_thread = NULL;
   {
     ScopedLock lock(process_wide_mutex_);
@@ -361,7 +363,8 @@
 
 
 Isolate::PerIsolateThreadData*
-    Isolate::ThreadDataTable::Lookup(Isolate* isolate, ThreadId thread_id) {
+    Isolate::ThreadDataTable::Lookup(Isolate* isolate,
+                                     ThreadId thread_id) {
   for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
     if (data->Matches(isolate, thread_id)) return data;
   }
@@ -383,7 +386,8 @@
 }
 
 
-void Isolate::ThreadDataTable::Remove(Isolate* isolate, ThreadId thread_id) {
+void Isolate::ThreadDataTable::Remove(Isolate* isolate,
+                                      ThreadId thread_id) {
   PerIsolateThreadData* data = Lookup(isolate, thread_id);
   if (data != NULL) {
     Remove(data);
@@ -429,7 +433,7 @@
       context_slot_cache_(NULL),
       descriptor_lookup_cache_(NULL),
       handle_scope_implementer_(NULL),
-      scanner_constants_(NULL),
+      unicode_cache_(NULL),
       in_use_list_(0),
       free_list_(0),
       preallocated_storage_preallocated_(false),
@@ -564,8 +568,8 @@
   producer_heap_profile_ = NULL;
 #endif
 
-  delete scanner_constants_;
-  scanner_constants_ = NULL;
+  delete unicode_cache_;
+  unicode_cache_ = NULL;
 
   delete regexp_stack_;
   regexp_stack_ = NULL;
@@ -672,7 +676,7 @@
   keyed_lookup_cache_ = new KeyedLookupCache();
   context_slot_cache_ = new ContextSlotCache();
   descriptor_lookup_cache_ = new DescriptorLookupCache();
-  scanner_constants_ = new ScannerConstants();
+  unicode_cache_ = new UnicodeCache();
   pc_to_code_cache_ = new PcToCodeCache(this);
   write_input_buffer_ = new StringInputBuffer();
   global_handles_ = new GlobalHandles(this);
@@ -833,8 +837,8 @@
       ASSERT(Current() == this);
       ASSERT(entry_stack_ != NULL);
       ASSERT(entry_stack_->previous_thread_data == NULL ||
-             entry_stack_->previous_thread_data->thread_id() ==
-                 Thread::GetThreadLocalInt(thread_id_key_));
+             entry_stack_->previous_thread_data->thread_id().Equals(
+                 ThreadId::Current()));
       // Same thread re-enters the isolate, no need to re-init anything.
       entry_stack_->entry_count++;
       return;
@@ -872,8 +876,8 @@
 void Isolate::Exit() {
   ASSERT(entry_stack_ != NULL);
   ASSERT(entry_stack_->previous_thread_data == NULL ||
-         entry_stack_->previous_thread_data->thread_id() ==
-             Thread::GetThreadLocalInt(thread_id_key_));
+         entry_stack_->previous_thread_data->thread_id().Equals(
+             ThreadId::Current()));
 
   if (--entry_stack_->entry_count > 0) return;
 
diff --git a/src/isolate.h b/src/isolate.h
index dd0a1fe..01b721d 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -72,7 +72,7 @@
 class ProducerHeapProfile;
 class RegExpStack;
 class SaveContext;
-class ScannerConstants;
+class UnicodeCache;
 class StringInputBuffer;
 class StringTracker;
 class StubCache;
@@ -136,6 +136,53 @@
 #endif
 
 
+// Platform-independent, reliable thread identifier.
+class ThreadId {
+ public:
+  // Creates an invalid ThreadId.
+  ThreadId() : id_(kInvalidId) {}
+
+  // Returns ThreadId for current thread.
+  static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
+
+  // Returns invalid ThreadId (guaranteed not to be equal to any thread).
+  static ThreadId Invalid() { return ThreadId(kInvalidId); }
+
+  // Compares ThreadIds for equality.
+  INLINE(bool Equals(const ThreadId& other) const) {
+    return id_ == other.id_;
+  }
+
+  // Checks whether this ThreadId refers to any thread.
+  INLINE(bool IsValid() const) {
+    return id_ != kInvalidId;
+  }
+
+  // Converts ThreadId to an integer representation
+  // (required for public API: V8::V8::GetCurrentThreadId).
+  int ToInteger() const { return id_; }
+
+  // Converts ThreadId to an integer representation
+  // (required for public API: V8::V8::TerminateExecution).
+  static ThreadId FromInteger(int id) { return ThreadId(id); }
+
+ private:
+  static const int kInvalidId = -1;
+
+  explicit ThreadId(int id) : id_(id) {}
+
+  static int AllocateThreadId();
+
+  static int GetCurrentThreadId();
+
+  int id_;
+
+  static Atomic32 highest_thread_id_;
+
+  friend class Isolate;
+};
+
+
 class ThreadLocalTop BASE_EMBEDDED {
  public:
   // Initialize the thread data.
@@ -176,7 +223,7 @@
   // The context where the current execution method is created and for variable
   // lookups.
   Context* context_;
-  int thread_id_;
+  ThreadId thread_id_;
   MaybeObject* pending_exception_;
   bool has_pending_message_;
   Object* pending_message_obj_;
@@ -188,9 +235,6 @@
   // unify them later.
   MaybeObject* scheduled_exception_;
   bool external_caught_exception_;
-  // True if unhandled message is being currently reported by
-  // MessageHandler::ReportMessage.
-  bool in_exception_reporting_;
   SaveContext* save_context_;
   v8::TryCatch* catcher_;
 
@@ -332,8 +376,6 @@
  public:
   ~Isolate();
 
-  typedef int ThreadId;
-
   // A thread has a PerIsolateThreadData instance for each isolate that it has
   // entered. That instance is allocated when the isolate is initially entered
   // and reused on subsequent entries.
@@ -366,7 +408,7 @@
 #endif
 
     bool Matches(Isolate* isolate, ThreadId thread_id) const {
-      return isolate_ == isolate && thread_id_ == thread_id;
+      return isolate_ == isolate && thread_id_.Equals(thread_id);
     }
 
    private:
@@ -458,9 +500,6 @@
     return thread_id_key_;
   }
 
-  // Atomically allocates a new thread ID.
-  static ThreadId AllocateThreadId();
-
   // If a client attempts to create a Locker without specifying an isolate,
   // we assume that the client is using legacy behavior. Set up the current
   // thread to be inside the implicit isolate (or fail a check if we have
@@ -486,8 +525,8 @@
   }
 
   // Access to current thread id.
-  int thread_id() { return thread_local_top_.thread_id_; }
-  void set_thread_id(int id) { thread_local_top_.thread_id_ = id; }
+  ThreadId thread_id() { return thread_local_top_.thread_id_; }
+  void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; }
 
   // Interface to pending exception.
   MaybeObject* pending_exception() {
@@ -526,12 +565,6 @@
   bool* external_caught_exception_address() {
     return &thread_local_top_.external_caught_exception_;
   }
-  bool in_exception_reporting() {
-    return thread_local_top_.in_exception_reporting_;
-  }
-  void set_in_exception_reporting(bool value) {
-    thread_local_top_.in_exception_reporting_ = value;
-  }
   v8::TryCatch* catcher() {
     return thread_local_top_.catcher_;
   }
@@ -786,8 +819,8 @@
   }
   Zone* zone() { return &zone_; }
 
-  ScannerConstants* scanner_constants() {
-    return scanner_constants_;
+  UnicodeCache* unicode_cache() {
+    return unicode_cache_;
   }
 
   PcToCodeCache* pc_to_code_cache() { return pc_to_code_cache_; }
@@ -1005,7 +1038,6 @@
   static Thread::LocalStorageKey thread_id_key_;
   static Isolate* default_isolate_;
   static ThreadDataTable* thread_data_table_;
-  static ThreadId highest_thread_id_;
 
   bool PreInit();
 
@@ -1090,7 +1122,7 @@
   DescriptorLookupCache* descriptor_lookup_cache_;
   v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
   HandleScopeImplementer* handle_scope_implementer_;
-  ScannerConstants* scanner_constants_;
+  UnicodeCache* unicode_cache_;
   Zone zone_;
   PreallocatedStorage in_use_list_;
   PreallocatedStorage free_list_;
@@ -1165,6 +1197,7 @@
 
   friend class ExecutionAccess;
   friend class IsolateInitializer;
+  friend class ThreadId;
   friend class v8::Isolate;
   friend class v8::Locker;
 
diff --git a/src/messages.cc b/src/messages.cc
index 0cc8251..abc2537 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -104,15 +104,6 @@
 void MessageHandler::ReportMessage(Isolate* isolate,
                                    MessageLocation* loc,
                                    Handle<Object> message) {
-  // If we are in process of message reporting, just ignore all other requests
-  // to report a message as they are due to unhandled exceptions thrown in
-  // message callbacks.
-  if (isolate->in_exception_reporting()) {
-    PrintF("uncaught exception thrown while reporting\n");
-    return;
-  }
-  isolate->set_in_exception_reporting(true);
-
   // We are calling into embedder's code which can throw exceptions.
   // Thus we need to save current exception state, reset it to the clean one
   // and ignore scheduled exceptions callbacks can throw.
@@ -138,14 +129,16 @@
       v8::MessageCallback callback =
           FUNCTION_CAST<v8::MessageCallback>(callback_obj->proxy());
       Handle<Object> callback_data(listener.get(1));
-      callback(api_message_obj, v8::Utils::ToLocal(callback_data));
+      {
+        // Do not allow exceptions to propagate.
+        v8::TryCatch tryCatch;
+        callback(api_message_obj, v8::Utils::ToLocal(callback_data));
+      }
       if (isolate->has_scheduled_exception()) {
         isolate->clear_scheduled_exception();
       }
     }
   }
-
-  isolate->set_in_exception_reporting(false);
 }
 
 
diff --git a/src/natives.h b/src/natives.h
index 639a2d3..1df94b0 100644
--- a/src/natives.h
+++ b/src/natives.h
@@ -36,7 +36,7 @@
                                      int index);
 
 enum NativeType {
-  CORE, D8
+  CORE, D8, I18N
 };
 
 template <NativeType type>
diff --git a/src/objects-inl.h b/src/objects-inl.h
index ebdf0a0..823b2da 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -3309,6 +3309,11 @@
 }
 
 
+bool JSFunction::IsOptimizable() {
+  return code()->kind() == Code::FUNCTION && code()->optimizable();
+}
+
+
 bool JSFunction::IsMarkedForLazyRecompilation() {
   return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
 }
diff --git a/src/objects.cc b/src/objects.cc
index d211d62..6ce4c44 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1279,6 +1279,22 @@
 }
 
 
+static bool IsIdentifier(UnicodeCache* cache,
+                         unibrow::CharacterStream* buffer) {
+  // Checks whether the buffer contains an identifier (no escape).
+  if (!buffer->has_more()) return false;
+  if (!cache->IsIdentifierStart(buffer->GetNext())) {
+    return false;
+  }
+  while (buffer->has_more()) {
+    if (!cache->IsIdentifierPart(buffer->GetNext())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
 MaybeObject* JSObject::AddFastProperty(String* name,
                                        Object* value,
                                        PropertyAttributes attributes) {
@@ -1288,7 +1304,7 @@
   // hidden symbols) and is not a real identifier.
   Isolate* isolate = GetHeap()->isolate();
   StringInputBuffer buffer(name);
-  if (!isolate->scanner_constants()->IsIdentifier(&buffer)
+  if (!IsIdentifier(isolate->unicode_cache(), &buffer)
       && name != isolate->heap()->hidden_symbol()) {
     Object* obj;
     { MaybeObject* maybe_obj =
@@ -5423,8 +5439,8 @@
 bool String::IsEqualTo(Vector<const char> str) {
   Isolate* isolate = GetIsolate();
   int slen = length();
-  Access<ScannerConstants::Utf8Decoder>
-      decoder(isolate->scanner_constants()->utf8_decoder());
+  Access<UnicodeCache::Utf8Decoder>
+      decoder(isolate->unicode_cache()->utf8_decoder());
   decoder->Reset(str.start(), str.length());
   int i;
   for (i = 0; i < slen && decoder->has_more(); i++) {
@@ -7635,7 +7651,6 @@
   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
   Handle<Object> this_handle(receiver, isolate);
   Handle<JSObject> holder_handle(this, isolate);
-
   if (!interceptor->getter()->IsUndefined()) {
     v8::IndexedPropertyGetter getter =
         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
diff --git a/src/objects.h b/src/objects.h
index 449a210..03445e8 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4526,6 +4526,9 @@
   // Tells whether or not this function has been optimized.
   inline bool IsOptimized();
 
+  // Tells whether or not this function can be optimized.
+  inline bool IsOptimizable();
+
   // Mark this function for lazy recompilation. The function will be
   // recompiled the next time it is executed.
   void MarkForLazyRecompilation();
diff --git a/src/parser.cc b/src/parser.cc
index 4fad6e4..cf84bfa 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -576,7 +576,7 @@
     : isolate_(script->GetIsolate()),
       symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
       script_(script),
-      scanner_(isolate_->scanner_constants()),
+      scanner_(isolate_->unicode_cache()),
       top_scope_(NULL),
       with_nesting_level_(0),
       lexical_scope_(NULL),
@@ -2894,7 +2894,8 @@
     case Token::NUMBER: {
       Consume(Token::NUMBER);
       ASSERT(scanner().is_literal_ascii());
-      double value = StringToDouble(scanner().literal_ascii_string(),
+      double value = StringToDouble(isolate()->unicode_cache(),
+                                    scanner().literal_ascii_string(),
                                     ALLOW_HEX | ALLOW_OCTALS);
       result = NewNumberLiteral(value);
       break;
@@ -3392,7 +3393,8 @@
       case Token::NUMBER: {
         Consume(Token::NUMBER);
         ASSERT(scanner().is_literal_ascii());
-        double value = StringToDouble(scanner().literal_ascii_string(),
+        double value = StringToDouble(isolate()->unicode_cache(),
+                                      scanner().literal_ascii_string(),
                                       ALLOW_HEX | ALLOW_OCTALS);
         key = NewNumberLiteral(value);
         break;
@@ -5056,7 +5058,7 @@
                                   bool allow_lazy,
                                   ParserRecorder* recorder) {
   Isolate* isolate = Isolate::Current();
-  V8JavaScriptScanner scanner(isolate->scanner_constants());
+  V8JavaScriptScanner scanner(isolate->unicode_cache());
   scanner.Initialize(source);
   intptr_t stack_limit = isolate->stack_guard()->real_climit();
   if (!preparser::PreParser::PreParseProgram(&scanner,
diff --git a/src/parser.h b/src/parser.h
index e8cd102..a63651a 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -783,7 +783,7 @@
  private:
   JsonParser()
       : isolate_(Isolate::Current()),
-        scanner_(isolate_->scanner_constants()) { }
+        scanner_(isolate_->unicode_cache()) { }
   ~JsonParser() { }
 
   Isolate* isolate() { return isolate_; }
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index d591b9d..6511328 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -362,50 +362,17 @@
 }
 
 
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
  public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
-    Initialize(kind);
-  }
-
-  void Initialize(ThreadHandle::Kind kind) {
-    switch (kind) {
-      case ThreadHandle::SELF: thread_ = pthread_self(); break;
-      case ThreadHandle::INVALID: thread_ = kNoThread; break;
-    }
-  }
-
+  PlatformData() : thread_(kNoThread) {}
   pthread_t thread_;  // Thread handle for pthread.
 };
 
 
-ThreadHandle::ThreadHandle(Kind kind) {
-  data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
-  data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
-  delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
-  return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
-  return data_->thread_ != kNoThread;
-}
 
 
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData),
       isolate_(isolate),
       stack_size_(options.stack_size) {
   set_name(options.name);
@@ -413,7 +380,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData),
       isolate_(isolate),
       stack_size_(0) {
   set_name(name);
@@ -421,6 +388,7 @@
 
 
 Thread::~Thread() {
+  delete data_;
 }
 
 
@@ -429,8 +397,8 @@
   // This is also initialized by the first argument to pthread_create() but we
   // don't know which thread will run first (the original thread or the new
   // one) so we initialize it here too.
-  thread->thread_handle_data()->thread_ = pthread_self();
-  ASSERT(thread->IsValid());
+  thread->data()->thread_ = pthread_self();
+  ASSERT(thread->data()->thread_ != kNoThread);
   Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
@@ -451,13 +419,13 @@
     pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
     attr_ptr = &attr;
   }
-  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
-  ASSERT(IsValid());
+  pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
+  ASSERT(data_->thread_ != kNoThread);
 }
 
 
 void Thread::Join() {
-  pthread_join(thread_handle_data()->thread_, NULL);
+  pthread_join(data_->thread_, NULL);
 }
 
 
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 2a73b6e..ca4e54f 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -391,18 +391,8 @@
 }
 
 
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
  public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
-    Initialize(kind);
-  }
-
-  void Initialize(ThreadHandle::Kind kind) {
-    switch (kind) {
-      case ThreadHandle::SELF: thread_ = pthread_self(); break;
-      case ThreadHandle::INVALID: thread_ = kNoThread; break;
-    }
-  }
   pthread_t thread_;  // Thread handle for pthread.
 };
 
@@ -433,7 +423,7 @@
 
 
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData),
       isolate_(isolate),
       stack_size_(options.stack_size) {
   set_name(options.name);
@@ -441,7 +431,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData),
       isolate_(isolate),
       stack_size_(0) {
   set_name(name);
@@ -449,6 +439,7 @@
 
 
 Thread::~Thread() {
+  delete data_;
 }
 
 
@@ -457,7 +448,7 @@
   // This is also initialized by the first argument to pthread_create() but we
   // don't know which thread will run first (the original thread or the new
   // one) so we initialize it here too.
-  thread->thread_handle_data()->thread_ = pthread_self();
+  thread_->data_->thread_ = pthread_self();
   ASSERT(thread->IsValid());
   Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 73a6ccb..e2ab9d8 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -92,9 +92,10 @@
 
 uint64_t OS::CpuFeaturesImpliedByPlatform() {
 #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
-  // Here gcc is telling us that we are on an ARM and gcc is assuming that we
-  // have VFP3 instructions.  If gcc can assume it then so can we.
-  return 1u << VFP3;
+  // Here gcc is telling us that we are on an ARM and gcc is assuming
+  // that we have VFP3 instructions.  If gcc can assume it then so can
+  // we. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
+  return 1u << VFP3 | 1u << ARMv7;
 #elif CAN_USE_ARMV7_INSTRUCTIONS
   return 1u << ARMv7;
 #elif(defined(__mips_hard_float) && __mips_hard_float != 0)
@@ -588,50 +589,15 @@
 }
 
 
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
  public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
-    Initialize(kind);
-  }
-
-  void Initialize(ThreadHandle::Kind kind) {
-    switch (kind) {
-      case ThreadHandle::SELF: thread_ = pthread_self(); break;
-      case ThreadHandle::INVALID: thread_ = kNoThread; break;
-    }
-  }
+  PlatformData() : thread_(kNoThread) {}
 
   pthread_t thread_;  // Thread handle for pthread.
 };
 
-
-ThreadHandle::ThreadHandle(Kind kind) {
-  data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
-  data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
-  delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
-  return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
-  return data_->thread_ != kNoThread;
-}
-
-
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData()),
       isolate_(isolate),
       stack_size_(options.stack_size) {
   set_name(options.name);
@@ -639,7 +605,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData()),
       isolate_(isolate),
       stack_size_(0) {
   set_name(name);
@@ -647,6 +613,7 @@
 
 
 Thread::~Thread() {
+  delete data_;
 }
 
 
@@ -658,8 +625,8 @@
   prctl(PR_SET_NAME,
         reinterpret_cast<unsigned long>(thread->name()),  // NOLINT
         0, 0, 0);
-  thread->thread_handle_data()->thread_ = pthread_self();
-  ASSERT(thread->IsValid());
+  thread->data()->thread_ = pthread_self();
+  ASSERT(thread->data()->thread_ != kNoThread);
   Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
@@ -680,13 +647,13 @@
     pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
     attr_ptr = &attr;
   }
-  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
-  ASSERT(IsValid());
+  pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
+  ASSERT(data_->thread_ != kNoThread);
 }
 
 
 void Thread::Join() {
-  pthread_join(thread_handle_data()->thread_, NULL);
+  pthread_join(data_->thread_, NULL);
 }
 
 
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index bfdf3b2..3e10b6a 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -392,50 +392,14 @@
 }
 
 
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
  public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
-    Initialize(kind);
-  }
-
-  void Initialize(ThreadHandle::Kind kind) {
-    switch (kind) {
-      case ThreadHandle::SELF: thread_ = pthread_self(); break;
-      case ThreadHandle::INVALID: thread_ = kNoThread; break;
-    }
-  }
+  PlatformData() : thread_(kNoThread) {}
   pthread_t thread_;  // Thread handle for pthread.
 };
 
-
-
-ThreadHandle::ThreadHandle(Kind kind) {
-  data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
-  data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
-  delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
-  return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
-  return data_->thread_ != kNoThread;
-}
-
-
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData),
       isolate_(isolate),
       stack_size_(options.stack_size) {
   set_name(options.name);
@@ -443,7 +407,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData),
       isolate_(isolate),
       stack_size_(0) {
   set_name(name);
@@ -451,6 +415,7 @@
 
 
 Thread::~Thread() {
+  delete data_;
 }
 
 
@@ -476,9 +441,9 @@
   // This is also initialized by the first argument to pthread_create() but we
   // don't know which thread will run first (the original thread or the new
   // one) so we initialize it here too.
-  thread->thread_handle_data()->thread_ = pthread_self();
+  thread->data()->thread_ = pthread_self();
   SetThreadName(thread->name());
-  ASSERT(thread->IsValid());
+  ASSERT(thread->data()->thread_ != kNoThread);
   Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
@@ -499,13 +464,13 @@
     pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
     attr_ptr = &attr;
   }
-  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
-  ASSERT(IsValid());
+  pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
+  ASSERT(data_->thread_ != kNoThread);
 }
 
 
 void Thread::Join() {
-  pthread_join(thread_handle_data()->thread_, NULL);
+  pthread_join(data_->thread_, NULL);
 }
 
 
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
index 5409936..aacad14 100644
--- a/src/platform-nullos.cc
+++ b/src/platform-nullos.cc
@@ -299,9 +299,9 @@
 }
 
 
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
  public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
+  PlatformData() {
     UNIMPLEMENTED();
   }
 
@@ -309,39 +309,8 @@
 };
 
 
-ThreadHandle::ThreadHandle(Kind kind) {
-  UNIMPLEMENTED();
-  // Shared setup follows.
-  data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
-  UNIMPLEMENTED();
-}
-
-
-ThreadHandle::~ThreadHandle() {
-  UNIMPLEMENTED();
-  // Shared tear down follows.
-  delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
-  UNIMPLEMENTED();
-  return false;
-}
-
-
-bool ThreadHandle::IsValid() const {
-  UNIMPLEMENTED();
-  return false;
-}
-
-
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData()),
       isolate_(isolate),
       stack_size_(options.stack_size) {
   set_name(options.name);
@@ -350,7 +319,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData()),
       isolate_(isolate),
       stack_size_(0) {
   set_name(name);
@@ -359,6 +328,7 @@
 
 
 Thread::~Thread() {
+  delete data_;
   UNIMPLEMENTED();
 }
 
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index fe1a62a..e90b3e8 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -359,49 +359,16 @@
 }
 
 
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
  public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
-    Initialize(kind);
-  }
+  PlatformData() : thread_(kNoThread) {}
 
-  void Initialize(ThreadHandle::Kind kind) {
-    switch (kind) {
-      case ThreadHandle::SELF: thread_ = pthread_self(); break;
-      case ThreadHandle::INVALID: thread_ = kNoThread; break;
-    }
-  }
   pthread_t thread_;  // Thread handle for pthread.
 };
 
 
-ThreadHandle::ThreadHandle(Kind kind) {
-  data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
-  data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
-  delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
-  return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
-  return data_->thread_ != kNoThread;
-}
-
-
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData()),
       isolate_(isolate),
       stack_size_(options.stack_size) {
   set_name(options.name);
@@ -409,7 +376,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatfromData()),
       isolate_(isolate),
       stack_size_(0) {
   set_name(name);
@@ -417,6 +384,7 @@
 
 
 Thread::~Thread() {
+  delete data_;
 }
 
 
@@ -425,8 +393,8 @@
   // This is also initialized by the first argument to pthread_create() but we
   // don't know which thread will run first (the original thread or the new
   // one) so we initialize it here too.
-  thread->thread_handle_data()->thread_ = pthread_self();
-  ASSERT(thread->IsValid());
+  thread->data()->thread_ = pthread_self();
+  ASSERT(thread->data()->thread_ != kNoThread);
   Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
@@ -447,13 +415,13 @@
     pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
     attr_ptr = &attr;
   }
-  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
+  pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
   ASSERT(IsValid());
 }
 
 
 void Thread::Join() {
-  pthread_join(thread_handle_data()->thread_, NULL);
+  pthread_join(data_->thread_, NULL);
 }
 
 
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index da278f3..1a19bac 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -373,50 +373,15 @@
 }
 
 
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
  public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
-    Initialize(kind);
-  }
-
-  void Initialize(ThreadHandle::Kind kind) {
-    switch (kind) {
-      case ThreadHandle::SELF: thread_ = pthread_self(); break;
-      case ThreadHandle::INVALID: thread_ = kNoThread; break;
-    }
-  }
+  PlatformData() : thread_(kNoThread) {  }
 
   pthread_t thread_;  // Thread handle for pthread.
 };
 
-
-ThreadHandle::ThreadHandle(Kind kind) {
-  data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
-  data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
-  delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
-  return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
-  return data_->thread_ != kNoThread;
-}
-
-
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData()),
       isolate_(isolate),
       stack_size_(options.stack_size) {
   set_name(options.name);
@@ -424,7 +389,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
+    : data_(new PlatformData()),
       isolate_(isolate),
       stack_size_(0) {
   set_name(name);
@@ -432,6 +397,7 @@
 
 
 Thread::~Thread() {
+  delete data_;
 }
 
 
@@ -440,8 +406,8 @@
   // This is also initialized by the first argument to pthread_create() but we
   // don't know which thread will run first (the original thread or the new
   // one) so we initialize it here too.
-  thread->thread_handle_data()->thread_ = pthread_self();
-  ASSERT(thread->IsValid());
+  thread->data()->thread_ = pthread_self();
+  ASSERT(thread->data()->thread_ != kNoThread);
   Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
@@ -462,13 +428,13 @@
     pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
     attr_ptr = &attr;
   }
-  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
-  ASSERT(IsValid());
+  pthread_create(&data_->thread_, NULL, ThreadEntry, this);
+  ASSERT(data_->thread_ != kNoThread);
 }
 
 
 void Thread::Join() {
-  pthread_join(thread_handle_data()->thread_, NULL);
+  pthread_join(data_->thread_, NULL);
 }
 
 
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index ab03e3d..8673f04 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1468,24 +1468,6 @@
 
 // Definition of invalid thread handle and id.
 static const HANDLE kNoThread = INVALID_HANDLE_VALUE;
-static const DWORD kNoThreadId = 0;
-
-
-class ThreadHandle::PlatformData : public Malloced {
- public:
-  explicit PlatformData(ThreadHandle::Kind kind) {
-    Initialize(kind);
-  }
-
-  void Initialize(ThreadHandle::Kind kind) {
-    switch (kind) {
-      case ThreadHandle::SELF: tid_ = GetCurrentThreadId(); break;
-      case ThreadHandle::INVALID: tid_ = kNoThreadId; break;
-    }
-  }
-  DWORD tid_;  // Win32 thread identifier.
-};
-
 
 // Entry point for threads. The supplied argument is a pointer to the thread
 // object. The entry function dispatches to the run method in the thread
@@ -1496,41 +1478,12 @@
   // This is also initialized by the last parameter to _beginthreadex() but we
   // don't know which thread will run first (the original thread or the new
   // one) so we initialize it here too.
-  thread->thread_handle_data()->tid_ = GetCurrentThreadId();
   Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return 0;
 }
 
 
-// Initialize thread handle to invalid handle.
-ThreadHandle::ThreadHandle(ThreadHandle::Kind kind) {
-  data_ = new PlatformData(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
-  delete data_;
-}
-
-
-// The thread is running if it has the same id as the current thread.
-bool ThreadHandle::IsSelf() const {
-  return GetCurrentThreadId() == data_->tid_;
-}
-
-
-// Test for invalid thread handle.
-bool ThreadHandle::IsValid() const {
-  return data_->tid_ != kNoThreadId;
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
-  data_->Initialize(kind);
-}
-
-
 class Thread::PlatformData : public Malloced {
  public:
   explicit PlatformData(HANDLE thread) : thread_(thread) {}
@@ -1542,8 +1495,7 @@
 // handle until it is started.
 
 Thread::Thread(Isolate* isolate, const Options& options)
-    : ThreadHandle(ThreadHandle::INVALID),
-      isolate_(isolate),
+    : isolate_(isolate),
       stack_size_(options.stack_size) {
   data_ = new PlatformData(kNoThread);
   set_name(options.name);
@@ -1551,8 +1503,7 @@
 
 
 Thread::Thread(Isolate* isolate, const char* name)
-    : ThreadHandle(ThreadHandle::INVALID),
-      isolate_(isolate),
+    : isolate_(isolate),
       stack_size_(0) {
   data_ = new PlatformData(kNoThread);
   set_name(name);
@@ -1582,9 +1533,7 @@
                      ThreadEntry,
                      this,
                      0,
-                     reinterpret_cast<unsigned int*>(
-                         &thread_handle_data()->tid_)));
-  ASSERT(IsValid());
+                     NULL));
 }
 
 
diff --git a/src/platform.h b/src/platform.h
index fea16c8..fc417ef 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -354,40 +354,6 @@
   size_t size_;  // Size of the virtual memory.
 };
 
-
-// ----------------------------------------------------------------------------
-// ThreadHandle
-//
-// A ThreadHandle represents a thread identifier for a thread. The ThreadHandle
-// does not own the underlying os handle. Thread handles can be used for
-// refering to threads and testing equality.
-
-class ThreadHandle {
- public:
-  enum Kind { SELF, INVALID };
-  explicit ThreadHandle(Kind kind);
-
-  // Destructor.
-  ~ThreadHandle();
-
-  // Test for thread running.
-  bool IsSelf() const;
-
-  // Test for valid thread handle.
-  bool IsValid() const;
-
-  // Get platform-specific data.
-  class PlatformData;
-  PlatformData* thread_handle_data() { return data_; }
-
-  // Initialize the handle to kind
-  void Initialize(Kind kind);
-
- private:
-  PlatformData* data_;  // Captures platform dependent data.
-};
-
-
 // ----------------------------------------------------------------------------
 // Thread
 //
@@ -396,7 +362,7 @@
 // thread. The Thread object should not be deallocated before the thread has
 // terminated.
 
-class Thread: public ThreadHandle {
+class Thread {
  public:
   // Opaque data type for thread-local storage keys.
   // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
@@ -468,11 +434,15 @@
   // The thread name length is limited to 16 based on Linux's implementation of
   // prctl().
   static const int kMaxThreadNameLength = 16;
+
+  class PlatformData;
+  PlatformData* data() { return data_; }
+
  private:
   void set_name(const char *name);
 
-  class PlatformData;
   PlatformData* data_;
+
   Isolate* isolate_;
   char name_[kMaxThreadNameLength];
   int stack_size_;
diff --git a/src/preparser-api.cc b/src/preparser-api.cc
index 61e9e7e..9646eb6 100644
--- a/src/preparser-api.cc
+++ b/src/preparser-api.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -159,8 +159,8 @@
 
 class StandAloneJavaScriptScanner : public JavaScriptScanner {
  public:
-  explicit StandAloneJavaScriptScanner(ScannerConstants* scanner_constants)
-      : JavaScriptScanner(scanner_constants) { }
+  explicit StandAloneJavaScriptScanner(UnicodeCache* unicode_cache)
+      : JavaScriptScanner(unicode_cache) { }
 
   void Initialize(UC16CharacterStream* source) {
     source_ = source;
@@ -192,8 +192,8 @@
 PreParserData Preparse(UnicodeInputStream* input, size_t max_stack) {
   internal::InputStreamUTF16Buffer buffer(input);
   uintptr_t stack_limit = reinterpret_cast<uintptr_t>(&buffer) - max_stack;
-  internal::ScannerConstants scanner_constants;
-  internal::StandAloneJavaScriptScanner scanner(&scanner_constants);
+  internal::UnicodeCache unicode_cache;
+  internal::StandAloneJavaScriptScanner scanner(&unicode_cache);
   scanner.Initialize(&buffer);
   internal::CompleteParserRecorder recorder;
   preparser::PreParser::PreParseResult result =
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index 6e25169..97f0341 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -107,12 +107,6 @@
 }
 
 
-static bool IsOptimizable(JSFunction* function) {
-  Code* code = function->code();
-  return code->kind() == Code::FUNCTION && code->optimizable();
-}
-
-
 Atomic32 RuntimeProfiler::state_ = 0;
 // TODO(isolates): Create the semaphore lazily and clean it up when no
 // longer required.
@@ -120,6 +114,11 @@
 Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0);
 #endif
 
+#ifdef DEBUG
+bool RuntimeProfiler::has_been_globally_setup_ = false;
+#endif
+bool RuntimeProfiler::enabled_ = false;
+
 
 RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
     : isolate_(isolate),
@@ -140,13 +139,17 @@
 }
 
 
-bool RuntimeProfiler::IsEnabled() {
-  return V8::UseCrankshaft() && FLAG_opt;
+void RuntimeProfiler::GlobalSetup() {
+  ASSERT(!has_been_globally_setup_);
+  enabled_ = V8::UseCrankshaft() && FLAG_opt;
+#ifdef DEBUG
+  has_been_globally_setup_ = true;
+#endif
 }
 
 
 void RuntimeProfiler::Optimize(JSFunction* function, bool eager, int delay) {
-  ASSERT(IsOptimizable(function));
+  ASSERT(function->IsOptimizable());
   if (FLAG_trace_opt) {
     PrintF("[marking (%s) ", eager ? "eagerly" : "lazily");
     function->PrintName();
@@ -245,7 +248,7 @@
     if (current->IsValid()) {
       Handle<JSFunction> function = current->function();
       int delay = current->Delay();
-      if (IsOptimizable(*function)) {
+      if (function->IsOptimizable()) {
         Optimize(*function, true, delay);
       }
     }
@@ -290,7 +293,7 @@
     }
 
     // Do not record non-optimizable functions.
-    if (!IsOptimizable(function)) continue;
+    if (!function->IsOptimizable()) continue;
     samples[sample_count++] = function;
 
     int function_size = function->shared()->SourceSize();
@@ -330,7 +333,7 @@
 
 
 void RuntimeProfiler::OptimizeSoon(JSFunction* function) {
-  if (!IsOptimizable(function)) return;
+  if (!function->IsOptimizable()) return;
   PendingListNode* node = new PendingListNode(function);
   node->set_next(optimize_soon_list_);
   optimize_soon_list_ = node;
@@ -369,6 +372,7 @@
 
 
 void RuntimeProfiler::Setup() {
+  ASSERT(has_been_globally_setup_);
   ClearSampleBuffer();
   // If the ticker hasn't already started, make sure to do so to get
   // the ticks for the runtime profiler.
diff --git a/src/runtime-profiler.h b/src/runtime-profiler.h
index 3656893..692b4ff 100644
--- a/src/runtime-profiler.h
+++ b/src/runtime-profiler.h
@@ -44,7 +44,12 @@
  public:
   explicit RuntimeProfiler(Isolate* isolate);
 
-  static bool IsEnabled();
+  static void GlobalSetup();
+
+  static inline bool IsEnabled() {
+    ASSERT(has_been_globally_setup_);
+    return enabled_;
+  }
 
   void OptimizeNow();
   void OptimizeSoon(JSFunction* function);
@@ -143,6 +148,11 @@
   //   0 or positive => the number of isolates running JavaScript code.
   static Atomic32 state_;
   static Semaphore* semaphore_;
+
+#ifdef DEBUG
+  static bool has_been_globally_setup_;
+#endif
+  static bool enabled_;
 };
 
 
diff --git a/src/runtime.cc b/src/runtime.cc
index c7ff3a3..ceb6c10 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -4680,7 +4680,8 @@
   }
 
   // Slower case.
-  return isolate->heap()->NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
+  return isolate->heap()->NumberFromDouble(
+      StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
 }
 
 
@@ -5179,7 +5180,7 @@
   s->TryFlatten();
 
   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
-  double value = StringToInt(s, radix);
+  double value = StringToInt(isolate->unicode_cache(), s, radix);
   return isolate->heap()->NumberFromDouble(value);
 }
 
@@ -5189,7 +5190,8 @@
   CONVERT_CHECKED(String, str, args[0]);
 
   // ECMA-262 section 15.1.2.3, empty string is NaN
-  double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
+  double value = StringToDouble(isolate->unicode_cache(),
+                                str, ALLOW_TRAILING_JUNK, OS::nan_value());
 
   // Create a number object from the value.
   return isolate->heap()->NumberFromDouble(value);
@@ -7405,6 +7407,16 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSFunction, function, 0);
+  if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
+  function->MarkForLazyRecompilation();
+  return isolate->heap()->undefined_value();
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 1);
@@ -8069,10 +8081,14 @@
   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
   bool result;
   if (str->IsAsciiRepresentation()) {
-    result = DateParser::Parse(str->ToAsciiVector(), output_array);
+    result = DateParser::Parse(str->ToAsciiVector(),
+                               output_array,
+                               isolate->unicode_cache());
   } else {
     ASSERT(str->IsTwoByteRepresentation());
-    result = DateParser::Parse(str->ToUC16Vector(), output_array);
+    result = DateParser::Parse(str->ToUC16Vector(),
+                               output_array,
+                               isolate->unicode_cache());
   }
 
   if (result) {
@@ -10161,8 +10177,7 @@
     details->set(kThreadDetailsCurrentThreadIndex,
                  isolate->heap()->true_value());
     details->set(kThreadDetailsThreadIdIndex,
-                 Smi::FromInt(
-                     isolate->thread_manager()->CurrentId()));
+                 Smi::FromInt(ThreadId::Current().ToInteger()));
   } else {
     // Find the thread with the requested index.
     int n = 1;
@@ -10179,7 +10194,8 @@
     // Fill the details.
     details->set(kThreadDetailsCurrentThreadIndex,
                  isolate->heap()->false_value());
-    details->set(kThreadDetailsThreadIdIndex, Smi::FromInt(thread->id()));
+    details->set(kThreadDetailsThreadIdIndex,
+                 Smi::FromInt(thread->id().ToInteger()));
   }
 
   // Convert to JS array and return.
diff --git a/src/runtime.h b/src/runtime.h
index 58062ca..bf1ba68 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -84,7 +84,8 @@
   F(LazyRecompile, 1, 1) \
   F(NotifyDeoptimized, 1, 1) \
   F(NotifyOSR, 0, 1) \
-  F(DeoptimizeFunction, 1, 1)             \
+  F(DeoptimizeFunction, 1, 1) \
+  F(OptimizeFunctionOnNextCall, 1, 1) \
   F(CompileForOnStackReplacement, 1, 1) \
   F(SetNewFunctionAttributes, 1, 1) \
   F(AllocateInNewSpace, 1, 1) \
diff --git a/src/scanner-base.cc b/src/scanner-base.cc
index 2066b5a..9715ca9 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -35,29 +35,11 @@
 namespace internal {
 
 // ----------------------------------------------------------------------------
-// Compound predicates.
-
-bool ScannerConstants::IsIdentifier(unibrow::CharacterStream* buffer) {
-  // Checks whether the buffer contains an identifier (no escape).
-  if (!buffer->has_more()) return false;
-  if (!kIsIdentifierStart.get(buffer->GetNext())) {
-    return false;
-  }
-  while (buffer->has_more()) {
-    if (!kIsIdentifierPart.get(buffer->GetNext())) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// ----------------------------------------------------------------------------
 // Scanner
 
-Scanner::Scanner(ScannerConstants* scanner_constants)
-    : scanner_constants_(scanner_constants),
-      octal_pos_(kNoOctalLocation) {
-}
+Scanner::Scanner(UnicodeCache* unicode_cache)
+    : unicode_cache_(unicode_cache),
+      octal_pos_(kNoOctalLocation) { }
 
 
 uc32 Scanner::ScanHexEscape(uc32 c, int length) {
@@ -114,7 +96,7 @@
 // ----------------------------------------------------------------------------
 // JavaScriptScanner
 
-JavaScriptScanner::JavaScriptScanner(ScannerConstants* scanner_contants)
+JavaScriptScanner::JavaScriptScanner(UnicodeCache* scanner_contants)
     : Scanner(scanner_contants) { }
 
 
@@ -144,9 +126,9 @@
   while (true) {
     // We treat byte-order marks (BOMs) as whitespace for better
     // compatibility with Spidermonkey and other JavaScript engines.
-    while (scanner_constants_->IsWhiteSpace(c0_) || IsByteOrderMark(c0_)) {
+    while (unicode_cache_->IsWhiteSpace(c0_) || IsByteOrderMark(c0_)) {
       // IsWhiteSpace() includes line terminators!
-      if (scanner_constants_->IsLineTerminator(c0_)) {
+      if (unicode_cache_->IsLineTerminator(c0_)) {
         // Ignore line terminators, but remember them. This is necessary
         // for automatic semicolon insertion.
         has_line_terminator_before_next_ = true;
@@ -186,7 +168,7 @@
   // separately by the lexical grammar and becomes part of the
   // stream of input elements for the syntactic grammar (see
   // ECMA-262, section 7.4, page 12).
-  while (c0_ >= 0 && !scanner_constants_->IsLineTerminator(c0_)) {
+  while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
     Advance();
   }
 
@@ -451,7 +433,7 @@
         break;
 
       default:
-        if (scanner_constants_->IsIdentifierStart(c0_)) {
+        if (unicode_cache_->IsIdentifierStart(c0_)) {
           token = ScanIdentifierOrKeyword();
         } else if (IsDecimalDigit(c0_)) {
           token = ScanNumber(false);
@@ -499,7 +481,7 @@
   Advance();
 
   // Skip escaped newlines.
-  if (scanner_constants_->IsLineTerminator(c)) {
+  if (unicode_cache_->IsLineTerminator(c)) {
     // Allow CR+LF newlines in multiline string literals.
     if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
     // Allow LF+CR newlines in multiline string literals.
@@ -542,7 +524,7 @@
 
   LiteralScope literal(this);
   while (c0_ != quote && c0_ >= 0
-         && !scanner_constants_->IsLineTerminator(c0_)) {
+         && !unicode_cache_->IsLineTerminator(c0_)) {
     uc32 c = c0_;
     Advance();
     if (c == '\\') {
@@ -641,7 +623,7 @@
   // not be an identifier start or a decimal digit; see ECMA-262
   // section 7.8.3, page 17 (note that we read only one decimal digit
   // if the value is 0).
-  if (IsDecimalDigit(c0_) || scanner_constants_->IsIdentifierStart(c0_))
+  if (IsDecimalDigit(c0_) || unicode_cache_->IsIdentifierStart(c0_))
     return Token::ILLEGAL;
 
   literal.Complete();
@@ -663,14 +645,14 @@
 
 
 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
-  ASSERT(scanner_constants_->IsIdentifierStart(c0_));
+  ASSERT(unicode_cache_->IsIdentifierStart(c0_));
   LiteralScope literal(this);
   KeywordMatcher keyword_match;
   // Scan identifier start character.
   if (c0_ == '\\') {
     uc32 c = ScanIdentifierUnicodeEscape();
     // Only allow legal identifier start characters.
-    if (!scanner_constants_->IsIdentifierStart(c)) return Token::ILLEGAL;
+    if (!unicode_cache_->IsIdentifierStart(c)) return Token::ILLEGAL;
     AddLiteralChar(c);
     return ScanIdentifierSuffix(&literal);
   }
@@ -683,7 +665,7 @@
   }
 
   // Scan the rest of the identifier characters.
-  while (scanner_constants_->IsIdentifierPart(c0_)) {
+  while (unicode_cache_->IsIdentifierPart(c0_)) {
     if (c0_ != '\\') {
       uc32 next_char = c0_;
       Advance();
@@ -701,11 +683,11 @@
 
 Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) {
   // Scan the rest of the identifier characters.
-  while (scanner_constants_->IsIdentifierPart(c0_)) {
+  while (unicode_cache_->IsIdentifierPart(c0_)) {
     if (c0_ == '\\') {
       uc32 c = ScanIdentifierUnicodeEscape();
       // Only allow legal identifier part characters.
-      if (!scanner_constants_->IsIdentifierPart(c)) return Token::ILLEGAL;
+      if (!unicode_cache_->IsIdentifierPart(c)) return Token::ILLEGAL;
       AddLiteralChar(c);
     } else {
       AddLiteralChar(c0_);
@@ -735,10 +717,10 @@
     AddLiteralChar('=');
 
   while (c0_ != '/' || in_character_class) {
-    if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false;
+    if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
     if (c0_ == '\\') {  // Escape sequence.
       AddLiteralCharAdvance();
-      if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false;
+      if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
       AddLiteralCharAdvance();
       // If the escape allows more characters, i.e., \x??, \u????, or \c?,
       // only "safe" characters are allowed (letters, digits, underscore),
@@ -764,7 +746,7 @@
 bool JavaScriptScanner::ScanRegExpFlags() {
   // Scan regular expression flags.
   LiteralScope literal(this);
-  while (scanner_constants_->IsIdentifierPart(c0_)) {
+  while (unicode_cache_->IsIdentifierPart(c0_)) {
     if (c0_ == '\\') {
       uc32 c = ScanIdentifierUnicodeEscape();
       if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
diff --git a/src/scanner-base.h b/src/scanner-base.h
index 552f387..60b97d2 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -119,11 +119,11 @@
 };
 
 
-class ScannerConstants {
+class UnicodeCache {
 // ---------------------------------------------------------------------
-// Constants used by scanners.
+// Caching predicates used by scanners.
  public:
-  ScannerConstants() {}
+  UnicodeCache() {}
   typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
 
   StaticResource<Utf8Decoder>* utf8_decoder() {
@@ -135,8 +135,6 @@
   bool IsLineTerminator(unibrow::uchar c) { return kIsLineTerminator.get(c); }
   bool IsWhiteSpace(unibrow::uchar c) { return kIsWhiteSpace.get(c); }
 
-  bool IsIdentifier(unibrow::CharacterStream* buffer);
-
  private:
 
   unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
@@ -145,9 +143,10 @@
   unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
   StaticResource<Utf8Decoder> utf8_decoder_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScannerConstants);
+  DISALLOW_COPY_AND_ASSIGN(UnicodeCache);
 };
 
+
 // ----------------------------------------------------------------------------
 // LiteralBuffer -  Collector of chars of literals.
 
@@ -272,7 +271,7 @@
     bool complete_;
   };
 
-  explicit Scanner(ScannerConstants* scanner_contants);
+  explicit Scanner(UnicodeCache* scanner_contants);
 
   // Returns the current token again.
   Token::Value current_token() { return current_.token; }
@@ -427,7 +426,7 @@
     return source_->pos() - kCharacterLookaheadBufferSize;
   }
 
-  ScannerConstants* scanner_constants_;
+  UnicodeCache* unicode_cache_;
 
   // Buffers collecting literal strings, numbers, etc.
   LiteralBuffer literal_buffer1_;
@@ -473,7 +472,7 @@
     bool complete_;
   };
 
-  explicit JavaScriptScanner(ScannerConstants* scanner_contants);
+  explicit JavaScriptScanner(UnicodeCache* scanner_contants);
 
   // Returns the next token.
   Token::Value Next();
diff --git a/src/scanner.cc b/src/scanner.cc
index d9c2188..666818e 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -345,8 +345,8 @@
 // ----------------------------------------------------------------------------
 // JsonScanner
 
-JsonScanner::JsonScanner(ScannerConstants* scanner_constants)
-    : Scanner(scanner_constants) { }
+JsonScanner::JsonScanner(UnicodeCache* unicode_cache)
+    : Scanner(unicode_cache) { }
 
 
 void JsonScanner::Initialize(UC16CharacterStream* source) {
@@ -560,7 +560,8 @@
   }
   literal.Complete();
   ASSERT_NOT_NULL(next_.literal_chars);
-  number_ = StringToDouble(next_.literal_chars->ascii_literal(),
+  number_ = StringToDouble(unicode_cache_,
+                           next_.literal_chars->ascii_literal(),
                            NO_FLAGS,  // Hex, octal or trailing junk.
                            OS::nan_value());
   return Token::NUMBER;
@@ -575,7 +576,7 @@
     Advance();
     text++;
   }
-  if (scanner_constants_->IsIdentifierPart(c0_)) return Token::ILLEGAL;
+  if (unicode_cache_->IsIdentifierPart(c0_)) return Token::ILLEGAL;
   literal.Complete();
   return token;
 }
diff --git a/src/scanner.h b/src/scanner.h
index 776ba53..871c69b 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -134,8 +134,8 @@
 
 class V8JavaScriptScanner : public JavaScriptScanner {
  public:
-  explicit V8JavaScriptScanner(ScannerConstants* scanner_constants)
-      : JavaScriptScanner(scanner_constants) {}
+  explicit V8JavaScriptScanner(UnicodeCache* unicode_cache)
+      : JavaScriptScanner(unicode_cache) {}
 
   void Initialize(UC16CharacterStream* source);
 };
@@ -143,7 +143,7 @@
 
 class JsonScanner : public Scanner {
  public:
-  explicit JsonScanner(ScannerConstants* scanner_constants);
+  explicit JsonScanner(UnicodeCache* unicode_cache);
 
   void Initialize(UC16CharacterStream* source);
 
diff --git a/src/top.cc b/src/top.cc
index 8611a31..899dfbe 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -69,10 +69,8 @@
 #endif
   try_catch_handler_address_ = NULL;
   context_ = NULL;
-  int id = Isolate::Current()->thread_manager()->CurrentId();
-  thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id;
+  thread_id_ = ThreadId::Current();
   external_caught_exception_ = false;
-  in_exception_reporting_ = false;
   failed_access_check_callback_ = NULL;
   save_context_ = NULL;
   catcher_ = NULL;
diff --git a/src/v8.cc b/src/v8.cc
index 19ed184..0b562fc 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -63,8 +63,8 @@
   }
 
   ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL);
-  ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id() ==
-         i::Thread::GetThreadLocalInt(i::Isolate::thread_id_key()));
+  ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id().Equals(
+           i::ThreadId::Current()));
   ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() ==
          i::Isolate::Current());
 
@@ -204,6 +204,8 @@
     use_crankshaft_ = false;
   }
 
+  RuntimeProfiler::GlobalSetup();
+
   // Peephole optimization might interfere with deoptimization.
   FLAG_peephole_optimization = !use_crankshaft_;
 }
diff --git a/src/v8threads.cc b/src/v8threads.cc
index cecafaa..4b033fc 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -147,11 +147,11 @@
   // First check whether the current thread has been 'lazily archived', ie
   // not archived at all.  If that is the case we put the state storage we
   // had prepared back in the free list, since we didn't need it after all.
-  if (lazily_archived_thread_.IsSelf()) {
-    lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
+  if (lazily_archived_thread_.Equals(ThreadId::Current())) {
+    lazily_archived_thread_ = ThreadId::Invalid();
     ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() ==
            lazily_archived_thread_state_);
-    lazily_archived_thread_state_->set_id(kInvalidId);
+    lazily_archived_thread_state_->set_id(ThreadId::Invalid());
     lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
     lazily_archived_thread_state_ = NULL;
     Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL);
@@ -190,7 +190,7 @@
     isolate_->stack_guard()->TerminateExecution();
     state->set_terminate_on_restore(false);
   }
-  state->set_id(kInvalidId);
+  state->set_id(ThreadId::Invalid());
   state->Unlink();
   state->LinkInto(ThreadState::FREE_LIST);
   return true;
@@ -199,13 +199,13 @@
 
 void ThreadManager::Lock() {
   mutex_->Lock();
-  mutex_owner_.Initialize(ThreadHandle::SELF);
+  mutex_owner_ = ThreadId::Current();
   ASSERT(IsLockedByCurrentThread());
 }
 
 
 void ThreadManager::Unlock() {
-  mutex_owner_.Initialize(ThreadHandle::INVALID);
+  mutex_owner_ = ThreadId::Invalid();
   mutex_->Unlock();
 }
 
@@ -224,7 +224,7 @@
 
 
 ThreadState::ThreadState(ThreadManager* thread_manager)
-    : id_(ThreadManager::kInvalidId),
+    : id_(ThreadId::Invalid()),
       terminate_on_restore_(false),
       next_(this),
       previous_(this),
@@ -282,8 +282,8 @@
 // defined as 0.)
 ThreadManager::ThreadManager()
     : mutex_(OS::CreateMutex()),
-      mutex_owner_(ThreadHandle::INVALID),
-      lazily_archived_thread_(ThreadHandle::INVALID),
+      mutex_owner_(ThreadId::Invalid()),
+      lazily_archived_thread_(ThreadId::Invalid()),
       lazily_archived_thread_state_(NULL),
       free_anchor_(NULL),
       in_use_anchor_(NULL) {
@@ -298,16 +298,16 @@
 
 
 void ThreadManager::ArchiveThread() {
-  ASSERT(!lazily_archived_thread_.IsValid());
+  ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
   ASSERT(!IsArchived());
   ThreadState* state = GetFreeThreadState();
   state->Unlink();
   Isolate::CurrentPerIsolateThreadData()->set_thread_state(state);
-  lazily_archived_thread_.Initialize(ThreadHandle::SELF);
+  lazily_archived_thread_ = ThreadId::Current();
   lazily_archived_thread_state_ = state;
-  ASSERT(state->id() == kInvalidId);
+  ASSERT(state->id().Equals(ThreadId::Invalid()));
   state->set_id(CurrentId());
-  ASSERT(state->id() != kInvalidId);
+  ASSERT(!state->id().Equals(ThreadId::Invalid()));
 }
 
 
@@ -326,7 +326,7 @@
   to = isolate_->stack_guard()->ArchiveStackGuard(to);
   to = isolate_->regexp_stack()->ArchiveStack(to);
   to = isolate_->bootstrapper()->ArchiveState(to);
-  lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
+  lazily_archived_thread_ = ThreadId::Invalid();
   lazily_archived_thread_state_ = NULL;
 }
 
@@ -373,16 +373,16 @@
 }
 
 
-int ThreadManager::CurrentId() {
-  return Thread::GetThreadLocalInt(Isolate::thread_id_key());
+ThreadId ThreadManager::CurrentId() {
+  return ThreadId::Current();
 }
 
 
-void ThreadManager::TerminateExecution(int thread_id) {
+void ThreadManager::TerminateExecution(ThreadId thread_id) {
   for (ThreadState* state = FirstThreadStateInUse();
        state != NULL;
        state = state->Next()) {
-    if (thread_id == state->id()) {
+    if (thread_id.Equals(state->id())) {
       state->set_terminate_on_restore(true);
     }
   }
diff --git a/src/v8threads.h b/src/v8threads.h
index 1266af7..d8a923e 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -43,8 +43,8 @@
   void Unlink();
 
   // Id of thread.
-  void set_id(int id) { id_ = id; }
-  int id() { return id_; }
+  void set_id(ThreadId id) { id_ = id; }
+  ThreadId id() { return id_; }
 
   // Should the thread be terminated when it is restored?
   bool terminate_on_restore() { return terminate_on_restore_; }
@@ -59,7 +59,7 @@
 
   void AllocateSpace();
 
-  int id_;
+  ThreadId id_;
   bool terminate_on_restore_;
   char* data_;
   ThreadState* next_;
@@ -97,17 +97,18 @@
 
   void Iterate(ObjectVisitor* v);
   void IterateArchivedThreads(ThreadVisitor* v);
-  bool IsLockedByCurrentThread() { return mutex_owner_.IsSelf(); }
+  bool IsLockedByCurrentThread() {
+    return mutex_owner_.Equals(ThreadId::Current());
+  }
 
-  int CurrentId();
+  ThreadId CurrentId();
 
-  void TerminateExecution(int thread_id);
+  void TerminateExecution(ThreadId thread_id);
 
   // Iterate over in-use states.
   ThreadState* FirstThreadStateInUse();
   ThreadState* GetFreeThreadState();
 
-  static const int kInvalidId = -1;
  private:
   ThreadManager();
   ~ThreadManager();
@@ -115,8 +116,8 @@
   void EagerlyArchiveThread();
 
   Mutex* mutex_;
-  ThreadHandle mutex_owner_;
-  ThreadHandle lazily_archived_thread_;
+  ThreadId mutex_owner_;
+  ThreadId lazily_archived_thread_;
   ThreadState* lazily_archived_thread_state_;
 
   // In the following two lists there is always at least one object on the list.
diff --git a/src/version.cc b/src/version.cc
index 120e564..c5ded6d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     2
-#define BUILD_NUMBER      9
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      10
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 0ab676f..9fe212e 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -99,7 +99,7 @@
   // ecx:edx. Temporarily enable CPUID support because we know it's
   // safe here.
   __ bind(&cpuid);
-  __ movq(rax, Immediate(1));
+  __ movl(rax, Immediate(1));
   supported_ = kDefaultCpuFeatures | (1 << CPUID);
   { Scope fscope(CPUID);
     __ cpuid();
@@ -1398,7 +1398,12 @@
 
 void Assembler::movb(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
-  emit_rex_32(dst, src);
+  if (dst.code() > 3) {
+    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
+    emit_rex_32(dst, src);
+  } else {
+    emit_optional_rex_32(dst, src);
+  }
   emit(0x8A);
   emit_operand(dst, src);
 }
@@ -1406,16 +1411,21 @@
 
 void Assembler::movb(Register dst, Immediate imm) {
   EnsureSpace ensure_space(this);
-  emit_rex_32(dst);
-  emit(0xC6);
-  emit_modrm(0x0, dst);
+  if (dst.code() > 3) {
+    emit_rex_32(dst);
+  }
+  emit(0xB0 + dst.low_bits());
   emit(imm.value_);
 }
 
 
 void Assembler::movb(const Operand& dst, Register src) {
   EnsureSpace ensure_space(this);
-  emit_rex_32(src, dst);
+  if (src.code() > 3) {
+    emit_rex_32(src, dst);
+  } else {
+    emit_optional_rex_32(src, dst);
+  }
   emit(0x88);
   emit_operand(src, dst);
 }
@@ -1465,16 +1475,15 @@
   emit_optional_rex_32(dst);
   emit(0xC7);
   emit_operand(0x0, dst);
-  emit(value);  // Only 32-bit immediates are possible, not 8-bit immediates.
+  emit(value);
 }
 
 
 void Assembler::movl(Register dst, Immediate value) {
   EnsureSpace ensure_space(this);
   emit_optional_rex_32(dst);
-  emit(0xC7);
-  emit_modrm(0x0, dst);
-  emit(value);  // Only 32-bit immediates are possible, not 8-bit immediates.
+  emit(0xB8 + dst.low_bits());
+  emit(value);
 }
 
 
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index fc3257d..a549633 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -96,7 +96,7 @@
   // rax: number of arguments
   __ bind(&non_function_call);
   // Set expected number of arguments to zero (not changing rax).
-  __ movq(rbx, Immediate(0));
+  __ Set(rbx, 0);
   __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
           RelocInfo::CODE_TARGET);
@@ -1372,7 +1372,7 @@
     // Copy receiver and all expected arguments.
     const int offset = StandardFrameConstants::kCallerSPOffset;
     __ lea(rax, Operand(rbp, rax, times_pointer_size, offset));
-    __ movq(rcx, Immediate(-1));  // account for receiver
+    __ Set(rcx, -1);  // account for receiver
 
     Label copy;
     __ bind(&copy);
@@ -1391,7 +1391,7 @@
     // Copy receiver and all actual arguments.
     const int offset = StandardFrameConstants::kCallerSPOffset;
     __ lea(rdi, Operand(rbp, rax, times_pointer_size, offset));
-    __ movq(rcx, Immediate(-1));  // account for receiver
+    __ Set(rcx, -1);  // account for receiver
 
     Label copy;
     __ bind(&copy);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index f2f0fc6..11727a0 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -273,7 +273,7 @@
 
   // Return 1/0 for true/false in rax.
   __ bind(&true_result);
-  __ movq(rax, Immediate(1));
+  __ Set(rax, 1);
   __ ret(1 * kPointerSize);
   __ bind(&false_result);
   __ Set(rax, 0);
@@ -1281,7 +1281,7 @@
   __ bind(&check_undefined_arg1);
   __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
   __ j(not_equal, conversion_failure);
-  __ movl(r8, Immediate(0));
+  __ Set(r8, 0);
   __ jmp(&load_arg2);
 
   __ bind(&arg1_is_object);
@@ -1301,7 +1301,7 @@
   __ bind(&check_undefined_arg2);
   __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
   __ j(not_equal, conversion_failure);
-  __ movl(rcx, Immediate(0));
+  __ Set(rcx, 0);
   __ jmp(&done);
 
   __ bind(&arg2_is_object);
@@ -1458,7 +1458,7 @@
     __ j(not_equal, &slow);
     // Operand is a float, negate its value by flipping sign bit.
     __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset));
-    __ movq(kScratchRegister, Immediate(0x01));
+    __ Set(kScratchRegister, 0x01);
     __ shl(kScratchRegister, Immediate(63));
     __ xor_(rdx, kScratchRegister);  // Flip sign.
     // rdx is value to store.
@@ -1530,7 +1530,7 @@
   __ movq(rax, Operand(rsp, 1 * kPointerSize));
 
   // Save 1 in xmm3 - we need this several times later on.
-  __ movl(rcx, Immediate(1));
+  __ Set(rcx, 1);
   __ cvtlsi2sd(xmm3, rcx);
 
   Label exponent_nonsmi;
@@ -3253,7 +3253,7 @@
       __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
       __ Assert(equal, "InstanceofStub unexpected call site cache (mov).");
     }
-    __ xorl(rax, rax);
+    __ Set(rax, 0);
   }
   __ ret(2 * kPointerSize + extra_stack_space);
 
@@ -4112,7 +4112,7 @@
   // if (hash == 0) hash = 27;
   Label hash_not_zero;
   __ j(not_zero, &hash_not_zero);
-  __ movl(hash, Immediate(27));
+  __ Set(hash, 27);
   __ bind(&hash_not_zero);
 }
 
@@ -4308,7 +4308,7 @@
     // Use scratch3 as loop index, min_length as limit and scratch2
     // for computation.
     const Register index = scratch3;
-    __ movl(index, Immediate(0));  // Index into strings.
+    __ Set(index, 0);  // Index into strings.
     __ bind(&loop);
     // Compare characters.
     // TODO(lrn): Could we load more than one character at a time?
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index ffd84ef..abac2b6 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -665,7 +665,7 @@
   __ PrepareCallCFunction(6);
   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
   __ movq(arg1, rax);
-  __ movq(arg2, Immediate(type()));
+  __ Set(arg2, type());
   // Args 3 and 4 are already in the right registers.
 
   // On windows put the arguments on the stack (PrepareCallCFunction
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index 189ee42..2b7b7b7 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -652,6 +652,9 @@
     case 2:
       mnem = "adc";
       break;
+    case 3:
+      mnem = "sbb";
+      break;
     case 4:
       mnem = "and";
       break;
@@ -1502,7 +1505,39 @@
         data++;
       }
         break;
-
+      case 0xB0:
+      case 0xB1:
+      case 0xB2:
+      case 0xB3:
+      case 0xB4:
+      case 0xB5:
+      case 0xB6:
+      case 0xB7:
+      case 0xB8:
+      case 0xB9:
+      case 0xBA:
+      case 0xBB:
+      case 0xBC:
+      case 0xBD:
+      case 0xBE:
+      case 0xBF: {
+        // mov reg8,imm8 or mov reg32,imm32
+        byte opcode = *data;
+        data++;
+        bool is_32bit = (opcode >= 0xB8);
+        int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
+        if (is_32bit) {
+          AppendToBuffer("mov%c %s, ",
+                         operand_size_code(),
+                         NameOfCPURegister(reg));
+          data += PrintImmediate(data, DOUBLEWORD_SIZE);
+        } else {
+          AppendToBuffer("movb %s, ",
+                         NameOfByteCPURegister(reg));
+          data += PrintImmediate(data, BYTE_SIZE);
+        }
+        break;
+      }
       case 0xFE: {
         data++;
         int mod, regop, rm;
@@ -1513,9 +1548,8 @@
         } else {
           UnimplementedInstruction();
         }
-      }
         break;
-
+      }
       case 0x68:
         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
         data += 5;
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 38c85f0..5ca56ac 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -1010,7 +1010,7 @@
 
   // Call the entry.
   CEntryStub stub(1);
-  __ movq(rax, Immediate(2));
+  __ Set(rax, 2);
   __ LoadAddress(rbx, ExternalReference(IC_Utility(id), masm->isolate()));
   __ CallStub(&stub);
 
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 56e6cc2..202e7a2 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -149,7 +149,7 @@
   int slots = StackSlotCount();
   if (slots > 0) {
     if (FLAG_debug_code) {
-      __ movl(rax, Immediate(slots));
+      __ Set(rax, slots);
       __ movq(kScratchRegister, kSlotsZapValue, RelocInfo::NONE);
       Label loop;
       __ bind(&loop);
@@ -1099,7 +1099,7 @@
 
 void LCodeGen::DoConstantI(LConstantI* instr) {
   ASSERT(instr->result()->IsRegister());
-  __ movl(ToRegister(instr->result()), Immediate(instr->value()));
+  __ Set(ToRegister(instr->result()), instr->value());
 }
 
 
@@ -1514,10 +1514,11 @@
 
   __ CompareRoot(reg, Heap::kNullValueRootIndex);
   if (instr->is_strict()) {
+    ASSERT(Heap::kTrueValueRootIndex >= 0);
     __ movl(result, Immediate(Heap::kTrueValueRootIndex));
     NearLabel load;
     __ j(equal, &load);
-    __ movl(result, Immediate(Heap::kFalseValueRootIndex));
+    __ Set(result, Heap::kFalseValueRootIndex);
     __ bind(&load);
     __ LoadRootIndexed(result, result, 0);
   } else {
@@ -1976,11 +1977,11 @@
     __ Push(instr->function());
 
     Register temp = ToRegister(instr->TempAt(0));
-    static const int kAdditionalDelta = 13;
+    static const int kAdditionalDelta = 10;
     int delta =
         masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
-    __ movq(temp, Immediate(delta));
-    __ push(temp);
+    ASSERT(delta >= 0);
+    __ push_imm32(delta);
 
     // We are pushing three values on the stack but recording a
     // safepoint with two arguments because stub is going to
@@ -1992,6 +1993,8 @@
                     RECORD_SAFEPOINT_WITH_REGISTERS,
                     2);
     ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check));
+    // Move result to a register that survives the end of the
+    // PushSafepointRegisterScope.
     __ movq(kScratchRegister, rax);
   }
   __ testq(kScratchRegister, kScratchRegister);
@@ -2426,14 +2429,14 @@
   } else {
     __ cmpq(rbp, ToOperand(instr->InputAt(0)));
   }
-  __ movq(result, Immediate(scope()->num_parameters()));
+  __ movl(result, Immediate(scope()->num_parameters()));
   __ j(equal, &done);
 
   // Arguments adaptor frame present. Get argument length from there.
   __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
-  __ movq(result, Operand(result,
-                          ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ SmiToInteger32(result, result);
+  __ SmiToInteger32(result,
+                    Operand(result,
+                            ArgumentsAdaptorFrameConstants::kLengthOffset));
 
   // Argument length is in result register.
   __ bind(&done);
@@ -3415,7 +3418,7 @@
     // conversions.
     __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
     DeoptimizeIf(not_equal, instr->environment());
-    __ movl(input_reg, Immediate(0));
+    __ Set(input_reg, 0);
     __ jmp(&done);
 
     __ bind(&heap_number);
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index b097166..7f027f7 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -788,10 +788,10 @@
 void MacroAssembler::Set(Register dst, int64_t x) {
   if (x == 0) {
     xorl(dst, dst);
-  } else if (is_int32(x)) {
-    movq(dst, Immediate(static_cast<int32_t>(x)));
   } else if (is_uint32(x)) {
     movl(dst, Immediate(static_cast<uint32_t>(x)));
+  } else if (is_int32(x)) {
+    movq(dst, Immediate(static_cast<int32_t>(x)));
   } else {
     movq(dst, x, RelocInfo::NONE);
   }
@@ -801,7 +801,7 @@
   if (is_int32(x)) {
     movq(dst, Immediate(static_cast<int32_t>(x)));
   } else {
-    movq(kScratchRegister, x, RelocInfo::NONE);
+    Set(kScratchRegister, x);
     movq(dst, kScratchRegister);
   }
 }
@@ -1814,7 +1814,7 @@
     // Set external caught exception to false.
     ExternalReference external_caught(
         Isolate::k_external_caught_exception_address, isolate());
-    movq(rax, Immediate(false));
+    Set(rax, static_cast<int64_t>(false));
     Store(external_caught, rax);
 
     // Set pending exception and rax to out of memory exception.
@@ -2002,7 +2002,7 @@
 void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
   if (FLAG_native_code_counters && counter->Enabled()) {
     Operand counter_operand = ExternalOperand(ExternalReference(counter));
-    movq(counter_operand, Immediate(value));
+    movl(counter_operand, Immediate(value));
   }
 }
 
@@ -2220,8 +2220,8 @@
   const int kFrameAlignment = OS::ActivationFrameAlignment();
   if (kFrameAlignment > 0) {
     ASSERT(IsPowerOf2(kFrameAlignment));
-    movq(kScratchRegister, Immediate(-kFrameAlignment));
-    and_(rsp, kScratchRegister);
+    ASSERT(is_int8(kFrameAlignment));
+    and_(rsp, Immediate(-kFrameAlignment));
   }
 
   // Patch the saved entry sp.
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 03f91fa..d4ccb0e 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -762,7 +762,7 @@
   __ j(above_equal, &stack_ok);
   // Exit with OutOfMemory exception. There is not enough space on the stack
   // for our working registers.
-  __ movq(rax, Immediate(EXCEPTION));
+  __ Set(rax, EXCEPTION);
   __ jmp(&exit_label_);
 
   __ bind(&stack_limit_hit);
@@ -799,7 +799,7 @@
     // Fill saved registers with initial value = start offset - 1
     // Fill in stack push order, to avoid accessing across an unwritten
     // page (a problem on Windows).
-    __ movq(rcx, Immediate(kRegisterZero));
+    __ Set(rcx, kRegisterZero);
     Label init_loop;
     __ bind(&init_loop);
     __ movq(Operand(rbp, rcx, times_1, 0), rax);
@@ -829,7 +829,7 @@
   LoadCurrentCharacterUnchecked(-1, 1);  // Load previous char.
   __ jmp(&start_label_);
   __ bind(&at_start);
-  __ movq(current_character(), Immediate('\n'));
+  __ Set(current_character(), '\n');
   __ jmp(&start_label_);
 
 
@@ -857,7 +857,7 @@
         __ movl(Operand(rbx, i * kIntSize), rax);
       }
     }
-    __ movq(rax, Immediate(SUCCESS));
+    __ Set(rax, SUCCESS);
   }
 
   // Exit and return rax
@@ -959,7 +959,7 @@
     // If any of the code above needed to exit with an exception.
     __ bind(&exit_with_exception);
     // Exit with Result EXCEPTION(-1) to signal thrown exception.
-    __ movq(rax, Immediate(EXCEPTION));
+    __ Set(rax, EXCEPTION);
     __ jmp(&exit_label_);
   }
 
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 26b20f4..c19d29d 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -399,7 +399,7 @@
   ExternalReference ref =
       ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
                         masm->isolate());
-  __ movq(rax, Immediate(5));
+  __ Set(rax, 5);
   __ LoadAddress(rbx, ref);
 
   CEntryStub stub(1);