Version 3.0.5

Fixed a couple of cast errors for gcc-3.4.3.

Performance improvements in GC and IA32 code generator.


git-svn-id: http://v8.googlecode.com/svn/trunk@6131 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index c81d7a7..d80638b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-01-03: Version 3.0.5
+
+        Fixed a couple of cast errors for gcc-3.4.3.
+
+        Performance improvements in GC and IA32 code generator.
+
+
 2010-12-21: Version 3.0.4
 
         Added Date::ResetCache() to the API so that the cached values in the
diff --git a/src/SConscript b/src/SConscript
index dfa099c..b1f9bb6 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -229,9 +229,10 @@
   'os:win32':   ['platform-win32.cc'],
   'mode:release': [],
   'mode:debug': [
-    'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
+    'objects-debug.cc', 'objects-printer.cc', 'prettyprinter.cc',
+    'regexp-macro-assembler-tracer.cc'
   ],
-  'objectprint:on': ['objects-debug.cc']
+  'objectprint:on': ['objects-printer.cc']
 }
 
 
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 5ec8584..7c3ea89 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -2894,45 +2894,45 @@
 
 
 // Uses registers r0 to r4. Expected input is
-// function in r0 (or at sp+1*ptrsz) and object in
+// object in r0 (or at sp+1*kPointerSize) and function in
 // r1 (or at sp), depending on whether or not
 // args_in_registers() is true.
 void InstanceofStub::Generate(MacroAssembler* masm) {
   // Fixed register usage throughout the stub:
-  const Register object = r1;  // Object (lhs).
+  const Register object = r0;  // Object (lhs).
   const Register map = r3;  // Map of the object.
-  const Register function = r0;  // Function (rhs).
+  const Register function = r1;  // Function (rhs).
   const Register prototype = r4;  // Prototype of the function.
   const Register scratch = r2;
   Label slow, loop, is_instance, is_not_instance, not_js_object;
   if (!args_in_registers()) {
-    __ ldr(function, MemOperand(sp, 1 * kPointerSize));
-    __ ldr(object, MemOperand(sp, 0));
+    __ ldr(object, MemOperand(sp, 1 * kPointerSize));
+    __ ldr(function, MemOperand(sp, 0));
   }
 
   // Check that the left hand is a JS object and load map.
-  __ BranchOnSmi(object, &slow);
-  __ IsObjectJSObjectType(object, map, scratch, &slow);
+  __ BranchOnSmi(object, &not_js_object);
+  __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
 
   // Look up the function and the map in the instanceof cache.
   Label miss;
   __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex);
-  __ cmp(object, ip);
+  __ cmp(function, ip);
   __ b(ne, &miss);
   __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex);
   __ cmp(map, ip);
   __ b(ne, &miss);
-  __ LoadRoot(function, Heap::kInstanceofCacheAnswerRootIndex);
+  __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
   __ Ret(args_in_registers() ? 0 : 2);
 
   __ bind(&miss);
-  __ TryGetFunctionPrototype(object, prototype, scratch, &slow);
+  __ TryGetFunctionPrototype(function, prototype, scratch, &slow);
 
   // Check that the function prototype is a JS object.
   __ BranchOnSmi(prototype, &slow);
   __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
 
-  __ StoreRoot(object, Heap::kInstanceofCacheFunctionRootIndex);
+  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
   __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
 
   // Register mapping: r3 is object map and r4 is function prototype.
@@ -2957,6 +2957,7 @@
 
   __ bind(&is_not_instance);
   __ mov(r0, Operand(Smi::FromInt(1)));
+  __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
   __ Ret(args_in_registers() ? 0 : 2);
 
   Label object_not_null, object_not_null_or_smi;
@@ -2986,6 +2987,9 @@
   __ Ret(args_in_registers() ? 0 : 2);
 
   // Slow-case.  Tail call builtin.
+  if (args_in_registers()) {
+    __ Push(r0, r1);
+  }
   __ bind(&slow);
   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS);
 }
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index e31d2e1..9c8e834 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1316,8 +1316,8 @@
 
 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
   LInstruction* result =
-      new LInstanceOf(UseFixed(instr->left(), r1),
-                      UseFixed(instr->right(), r0));
+      new LInstanceOf(UseFixed(instr->left(), r0),
+                      UseFixed(instr->right(), r1));
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1666,19 +1666,15 @@
 }
 
 
-LInstruction* LChunkBuilder::DoArrayLength(HArrayLength* instr) {
-  LOperand* array = NULL;
-  LOperand* temporary = NULL;
+LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
+  LOperand* array = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LJSArrayLength(array));
+}
 
-  if (instr->value()->IsLoadElements()) {
-    array = UseRegisterAtStart(instr->value());
-  } else {
-    array = UseRegister(instr->value());
-    temporary = TempRegister();
-  }
 
-  LInstruction* result = new LArrayLength(array, temporary);
-  return AssignEnvironment(DefineAsRegister(result));
+LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
+  LOperand* array = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LFixedArrayLength(array));
 }
 
 
@@ -1854,6 +1850,14 @@
 }
 
 
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+    HLoadFunctionPrototype* instr) {
+  return AssignEnvironment(DefineAsRegister(
+      new LLoadFunctionPrototype(UseRegister(instr->function()),
+                                 TempRegister())));
+}
+
+
 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
   LOperand* input = UseRegisterAtStart(instr->value());
   return DefineSameAsFirst(new LLoadElements(input));
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 41209c6..5b152ef 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -101,7 +101,8 @@
 //     LStoreNamedField
 //     LStoreNamedGeneric
 //   LUnaryOperation
-//     LArrayLength
+//     LJSArrayLength
+//     LFixedArrayLength
 //     LBitNotI
 //     LBranch
 //     LCallNew
@@ -127,6 +128,7 @@
 //     LIsSmiAndBranch
 //     LLoadNamedField
 //     LLoadNamedGeneric
+//     LLoadFunctionPrototype
 //     LNumberTagD
 //     LNumberTagI
 //     LPushArgument
@@ -161,7 +163,6 @@
   V(ArgumentsLength)                            \
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
-  V(ArrayLength)                                \
   V(ArrayLiteral)                               \
   V(BitI)                                       \
   V(BitNotI)                                    \
@@ -195,6 +196,7 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(FixedArrayLength)                           \
   V(FunctionLiteral)                            \
   V(Gap)                                        \
   V(GlobalObject)                               \
@@ -209,6 +211,7 @@
   V(IsObjectAndBranch)                          \
   V(IsSmi)                                      \
   V(IsSmiAndBranch)                             \
+  V(JSArrayLength)                              \
   V(HasInstanceType)                            \
   V(HasInstanceTypeAndBranch)                   \
   V(HasCachedArrayIndex)                        \
@@ -223,6 +226,7 @@
   V(LoadKeyedGeneric)                           \
   V(LoadNamedField)                             \
   V(LoadNamedGeneric)                           \
+  V(LoadFunctionPrototype)                      \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -1141,18 +1145,21 @@
 };
 
 
-class LArrayLength: public LUnaryOperation {
+class LJSArrayLength: public LUnaryOperation {
  public:
-  LArrayLength(LOperand* input, LOperand* temporary)
-      : LUnaryOperation(input), temporary_(temporary) { }
+  explicit LJSArrayLength(LOperand* input) : LUnaryOperation(input) { }
 
-  LOperand* temporary() const { return temporary_; }
+  DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
+};
 
-  DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array-length")
-  DECLARE_HYDROGEN_ACCESSOR(ArrayLength)
 
- private:
-  LOperand* temporary_;
+class LFixedArrayLength: public LUnaryOperation {
+ public:
+  explicit LFixedArrayLength(LOperand* input) : LUnaryOperation(input) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(FixedArrayLength)
 };
 
 
@@ -1256,6 +1263,22 @@
 };
 
 
+class LLoadFunctionPrototype: public LUnaryOperation {
+ public:
+  LLoadFunctionPrototype(LOperand* function, LOperand* temporary)
+      : LUnaryOperation(function), temporary_(temporary) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
+  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
+
+  LOperand* function() const { return input(); }
+  LOperand* temporary() const { return temporary_; }
+
+ private:
+  LOperand* temporary_;
+};
+
+
 class LLoadElements: public LUnaryOperation {
  public:
   explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index dfc4891..53a4325 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -898,24 +898,19 @@
 }
 
 
-void LCodeGen::DoArrayLength(LArrayLength* instr) {
+void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
   Register result = ToRegister(instr->result());
+  Register array = ToRegister(instr->input());
+  __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
+  Abort("DoJSArrayLength untested.");
+}
 
-  if (instr->hydrogen()->value()->IsLoadElements()) {
-    // We load the length directly from the elements array.
-    Register elements = ToRegister(instr->input());
-    __ ldr(result, FieldMemOperand(elements, FixedArray::kLengthOffset));
-  } else {
-    // Check that the receiver really is an array.
-    Register array = ToRegister(instr->input());
-    Register temporary = ToRegister(instr->temporary());
-    __ CompareObjectType(array, temporary, temporary, JS_ARRAY_TYPE);
-    DeoptimizeIf(ne, instr->environment());
 
-    // Load length directly from the array.
-    __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
-  }
-  Abort("DoArrayLength untested.");
+void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
+  Register result = ToRegister(instr->result());
+  Register array = ToRegister(instr->input());
+  __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
+  Abort("DoFixedArrayLength untested.");
 }
 
 
@@ -1337,14 +1332,16 @@
 
 
 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  // We expect object and function in registers r1 and r0.
+  ASSERT(ToRegister(instr->left()).is(r0));  // Object is in r0.
+  ASSERT(ToRegister(instr->right()).is(r1));  // Function is in r1.
+
   InstanceofStub stub(InstanceofStub::kArgsInRegisters);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 
   Label true_value, done;
   __ tst(r0, r0);
-  __ mov(r0, Operand(Factory::false_value()), LeaveCC, eq);
-  __ mov(r0, Operand(Factory::true_value()), LeaveCC, ne);
+  __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne);
+  __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq);
 }
 
 
@@ -1447,6 +1444,50 @@
 }
 
 
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+  Register function = ToRegister(instr->function());
+  Register temp = ToRegister(instr->temporary());
+  Register result = ToRegister(instr->result());
+
+  // Check that the function really is a function. Load map into the
+  // result register.
+  __ CompareObjectType(function, result, temp, JS_FUNCTION_TYPE);
+  DeoptimizeIf(ne, instr->environment());
+
+  // Make sure that the function has an instance prototype.
+  Label non_instance;
+  __ ldrb(temp, FieldMemOperand(result, Map::kBitFieldOffset));
+  __ tst(temp, Operand(1 << Map::kHasNonInstancePrototype));
+  __ b(ne, &non_instance);
+
+  // Get the prototype or initial map from the function.
+  __ ldr(result,
+         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // Check that the function has a prototype or an initial map.
+  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  __ cmp(result, ip);
+  DeoptimizeIf(eq, instr->environment());
+
+  // If the function does not have an initial map, we're done.
+  Label done;
+  __ CompareObjectType(result, temp, temp, MAP_TYPE);
+  __ b(ne, &done);
+
+  // Get the prototype from the initial map.
+  __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
+  __ jmp(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in initial map.
+  __ bind(&non_instance);
+  __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  __ bind(&done);
+}
+
+
 void LCodeGen::DoLoadElements(LLoadElements* instr) {
   Abort("DoLoadElements unimplemented.");
 }
diff --git a/src/ast.cc b/src/ast.cc
index 895ab67..1a6e768 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -517,6 +517,9 @@
   if (key()->IsPropertyName()) {
     if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) {
       is_array_length_ = true;
+    } else if (oracle->LoadIsBuiltin(this,
+                                     Builtins::LoadIC_FunctionPrototype)) {
+      is_function_prototype_ = true;
     } else {
       Literal* lit_key = key()->AsLiteral();
       ASSERT(lit_key != NULL && lit_key->handle()->IsString());
diff --git a/src/ast.h b/src/ast.h
index ed447e3..ba422fd 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1208,6 +1208,7 @@
         is_monomorphic_(false),
         receiver_types_(NULL),
         is_array_length_(false),
+        is_function_prototype_(false),
         is_arguments_access_(false) { }
 
   DECLARE_NODE_TYPE(Property)
@@ -1220,6 +1221,8 @@
   int position() const { return pos_; }
   bool is_synthetic() const { return type_ == SYNTHETIC; }
 
+  bool IsFunctionPrototype() const { return is_function_prototype_; }
+
   // Marks that this is actually an argument rewritten to a keyed property
   // accessing the argument through the arguments shadow object.
   void set_is_arguments_access(bool is_arguments_access) {
@@ -1249,6 +1252,7 @@
   bool is_monomorphic_;
   ZoneMapList* receiver_types_;
   bool is_array_length_;
+  bool is_function_prototype_;
   bool is_arguments_access_;
   Handle<Map> monomorphic_receiver_type_;
 
@@ -1391,7 +1395,7 @@
       : op_(op), left_(left), right_(right), pos_(pos), is_smi_only_(false) {
     ASSERT(Token::IsBinaryOp(op));
     right_id_ = (op == Token::AND || op == Token::OR)
-        ? GetNextId()
+        ? static_cast<int>(GetNextId())
         : AstNode::kNoNumber;
   }
 
diff --git a/src/builtins.cc b/src/builtins.cc
index 21381f1..0c76f69 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -380,7 +380,7 @@
     Object* receiver) {
   if (!receiver->IsJSArray()) return NULL;
   JSArray* array = JSArray::cast(receiver);
-  HeapObject* elms = HeapObject::cast(array->elements());
+  HeapObject* elms = array->elements();
   if (elms->map() == Heap::fixed_array_map()) return elms;
   if (elms->map() == Heap::fixed_cow_array_map()) {
     return array->EnsureWritableFastElements();
@@ -613,42 +613,38 @@
   Object* receiver = *args.receiver();
   FixedArray* elms;
   int len = -1;
-  { MaybeObject* maybe_elms_obj =
-        EnsureJSArrayWithWritableFastElements(receiver);
-    Object* elms_obj;
-    if (maybe_elms_obj != NULL && maybe_elms_obj->ToObject(&elms_obj)) {
-      if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
-        return CallJsBuiltin("ArraySlice", args);
-      }
-      elms = FixedArray::cast(elms_obj);
-      JSArray* array = JSArray::cast(receiver);
-      ASSERT(array->HasFastElements());
-
-      len = Smi::cast(array->length())->value();
-    } else {
-      // Array.slice(arguments, ...) is quite a common idiom (notably more
-      // than 50% of invocations in Web apps).  Treat it in C++ as well.
-      Map* arguments_map =
-          Top::context()->global_context()->arguments_boilerplate()->map();
-
-      bool is_arguments_object_with_fast_elements =
-          receiver->IsJSObject()
-          && JSObject::cast(receiver)->map() == arguments_map
-          && JSObject::cast(receiver)->HasFastElements();
-      if (!is_arguments_object_with_fast_elements) {
-        return CallJsBuiltin("ArraySlice", args);
-      }
-      elms = FixedArray::cast(JSObject::cast(receiver)->elements());
-      len = elms->length();
-#ifdef DEBUG
-      // Arguments object by construction should have no holes, check it.
-      if (FLAG_enable_slow_asserts) {
-        for (int i = 0; i < len; i++) {
-          ASSERT(elms->get(i) != Heap::the_hole_value());
-        }
-      }
-#endif
+  if (receiver->IsJSArray()) {
+    JSArray* array = JSArray::cast(receiver);
+    if (!array->HasFastElements() ||
+        !IsJSArrayFastElementMovingAllowed(array)) {
+      return CallJsBuiltin("ArraySlice", args);
     }
+
+    elms = FixedArray::cast(array->elements());
+    len = Smi::cast(array->length())->value();
+  } else {
+    // Array.slice(arguments, ...) is quite a common idiom (notably more
+    // than 50% of invocations in Web apps).  Treat it in C++ as well.
+    Map* arguments_map =
+        Top::context()->global_context()->arguments_boilerplate()->map();
+
+    bool is_arguments_object_with_fast_elements =
+        receiver->IsJSObject()
+        && JSObject::cast(receiver)->map() == arguments_map
+        && JSObject::cast(receiver)->HasFastElements();
+    if (!is_arguments_object_with_fast_elements) {
+      return CallJsBuiltin("ArraySlice", args);
+    }
+    elms = FixedArray::cast(JSObject::cast(receiver)->elements());
+    len = elms->length();
+#ifdef DEBUG
+    // Arguments object by construction should have no holes, check it.
+    if (FLAG_enable_slow_asserts) {
+      for (int i = 0; i < len; i++) {
+        ASSERT(elms->get(i) != Heap::the_hole_value());
+      }
+    }
+#endif
   }
   ASSERT(len >= 0);
   int n_arguments = args.length() - 1;
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index 5f3ed76..8a3886c 100644
--- a/src/d8-debug.cc
+++ b/src/d8-debug.cc
@@ -34,12 +34,21 @@
 
 namespace v8 {
 
-void PrintPrompt() {
-  printf("dbg> ");
+static bool was_running = true;
+
+void PrintPrompt(bool is_running) {
+  const char* prompt = is_running? "> " : "dbg> ";
+  was_running = is_running;
+  printf("%s", prompt);
   fflush(stdout);
 }
 
 
+void PrintPrompt() {
+  PrintPrompt(was_running);
+}
+
+
 void HandleDebugEvent(DebugEvent event,
                       Handle<Object> exec_state,
                       Handle<Object> event_data,
@@ -91,7 +100,7 @@
   bool running = false;
   while (!running) {
     char command[kBufferSize];
-    PrintPrompt();
+    PrintPrompt(running);
     char* str = fgets(command, kBufferSize, stdin);
     if (str == NULL) break;
 
@@ -284,7 +293,9 @@
   } else {
     printf("???\n");
   }
-  PrintPrompt();
+
+  bool is_running = details->Get(String::New("running"))->ToBoolean()->Value();
+  PrintPrompt(is_running);
 }
 
 
diff --git a/src/date.js b/src/date.js
index bc70327..9eb607c 100644
--- a/src/date.js
+++ b/src/date.js
@@ -1000,7 +1000,7 @@
 function DateToJSON(key) {
   var o = ToObject(this);
   var tv = DefaultNumber(o);
-  if (IS_NUMBER(tv) && !$isFinite(tv)) { 
+  if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) { 
     return null; 
   }
   return o.toISOString();
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index dd70baa..185ff92 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -309,9 +309,9 @@
 }
 
 
-unsigned Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
-                                    unsigned id,
-                                    SharedFunctionInfo* shared) {
+int Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
+                               unsigned id,
+                               SharedFunctionInfo* shared) {
   // TODO(kasperl): For now, we do a simple linear search for the PC
   // offset associated with the given node id. This should probably be
   // changed to a binary search.
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 2d7dfc8..f9bf280 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -145,9 +145,9 @@
 
   static Address GetDeoptimizationEntry(int id, BailoutType type);
   static int GetDeoptimizationId(Address addr, BailoutType type);
-  static unsigned GetOutputInfo(DeoptimizationOutputData* data,
-                                unsigned node_id,
-                                SharedFunctionInfo* shared);
+  static int GetOutputInfo(DeoptimizationOutputData* data,
+                           unsigned node_id,
+                           SharedFunctionInfo* shared);
 
   static void Setup();
   static void TearDown();
diff --git a/src/factory.cc b/src/factory.cc
index 83af447..2bc878c 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -99,6 +99,14 @@
   CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String);
 }
 
+Handle<String> Factory::LookupAsciiSymbol(Vector<const char> string) {
+  CALL_HEAP_FUNCTION(Heap::LookupAsciiSymbol(string), String);
+}
+
+Handle<String> Factory::LookupTwoByteSymbol(Vector<const uc16> string) {
+  CALL_HEAP_FUNCTION(Heap::LookupTwoByteSymbol(string), String);
+}
+
 
 Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
                                            PretenureFlag pretenure) {
diff --git a/src/factory.h b/src/factory.h
index b7a2882..a5e1591 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -61,6 +61,8 @@
       PretenureFlag pretenure);
 
   static Handle<String> LookupSymbol(Vector<const char> str);
+  static Handle<String> LookupAsciiSymbol(Vector<const char> str);
+  static Handle<String> LookupTwoByteSymbol(Vector<const uc16> str);
   static Handle<String> LookupAsciiSymbol(const char* str) {
     return LookupSymbol(CStrVector(str));
   }
diff --git a/src/globals.h b/src/globals.h
index 35156ae..9b24bf6 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -181,10 +181,6 @@
 #define USING_BSD_ABI
 #endif
 
-// Code-point values in Unicode 4.0 are 21 bits wide.
-typedef uint16_t uc16;
-typedef int32_t uc32;
-
 // -----------------------------------------------------------------------------
 // Constants
 
@@ -228,6 +224,15 @@
 const int kBinary32MantissaBits = 23;
 const int kBinary32ExponentShift = 23;
 
+// ASCII/UC16 constants
+// Code-point values in Unicode 4.0 are 21 bits wide.
+typedef uint16_t uc16;
+typedef int32_t uc32;
+const int kASCIISize    = kCharSize;
+const int kUC16Size     = sizeof(uc16);      // NOLINT
+const uc32 kMaxAsciiCharCode = 0x7f;
+const uint32_t kMaxAsciiCharCodeU = 0x7fu;
+
 
 // The expression OFFSET_OF(type, field) computes the byte-offset
 // of the specified field relative to the containing type. This
diff --git a/src/heap-inl.h b/src/heap-inl.h
index ef83998..7b91e87 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -40,6 +40,19 @@
 }
 
 
+MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> str,
+                                          PretenureFlag pretenure) {
+  // Check for ASCII first since this is the common case.
+  if (String::IsAscii(str.start(), str.length())) {
+    // If the string is ASCII, we do not need to convert the characters
+    // since UTF8 is backwards compatible with ASCII.
+    return AllocateStringFromAscii(str, pretenure);
+  }
+  // Non-ASCII and we need to decode.
+  return AllocateStringFromUtf8Slow(str, pretenure);
+}
+
+
 MaybeObject* Heap::AllocateSymbol(Vector<const char> str,
                                   int chars,
                                   uint32_t hash_field) {
@@ -49,6 +62,71 @@
 }
 
 
+MaybeObject* Heap::AllocateAsciiSymbol(Vector<const char> str,
+                                       uint32_t hash_field) {
+  if (str.length() > SeqAsciiString::kMaxLength) {
+    return Failure::OutOfMemoryException();
+  }
+  // Compute map and object size.
+  Map* map = ascii_symbol_map();
+  int size = SeqAsciiString::SizeFor(str.length());
+
+  // Allocate string.
+  Object* result;
+  { MaybeObject* maybe_result = (size > MaxObjectSizeInPagedSpace())
+                   ? lo_space_->AllocateRaw(size)
+                   : old_data_space_->AllocateRaw(size);
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
+
+  reinterpret_cast<HeapObject*>(result)->set_map(map);
+  // Set length and hash fields of the allocated string.
+  String* answer = String::cast(result);
+  answer->set_length(str.length());
+  answer->set_hash_field(hash_field);
+
+  ASSERT_EQ(size, answer->Size());
+
+  // Fill in the characters.
+  memcpy(answer->address() + SeqAsciiString::kHeaderSize,
+         str.start(), str.length());
+
+  return answer;
+}
+
+
+MaybeObject* Heap::AllocateTwoByteSymbol(Vector<const uc16> str,
+                                         uint32_t hash_field) {
+  if (str.length() > SeqTwoByteString::kMaxLength) {
+    return Failure::OutOfMemoryException();
+  }
+  // Compute map and object size.
+  Map* map = symbol_map();
+  int size = SeqTwoByteString::SizeFor(str.length());
+
+  // Allocate string.
+  Object* result;
+  { MaybeObject* maybe_result = (size > MaxObjectSizeInPagedSpace())
+                   ? lo_space_->AllocateRaw(size)
+                   : old_data_space_->AllocateRaw(size);
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
+
+  reinterpret_cast<HeapObject*>(result)->set_map(map);
+  // Set length and hash fields of the allocated string.
+  String* answer = String::cast(result);
+  answer->set_length(str.length());
+  answer->set_hash_field(hash_field);
+
+  ASSERT_EQ(size, answer->Size());
+
+  // Fill in the characters.
+  memcpy(answer->address() + SeqTwoByteString::kHeaderSize,
+         str.start(), str.length() * kUC16Size);
+
+  return answer;
+}
+
 MaybeObject* Heap::CopyFixedArray(FixedArray* src) {
   return CopyFixedArrayWithMap(src, src->map());
 }
diff --git a/src/heap.cc b/src/heap.cc
index 1e99991..44229f0 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2549,20 +2549,10 @@
   }
 
   // For small strings we check whether the resource contains only
-  // ascii characters.  If yes, we use a different string map.
-  bool is_ascii = true;
-  if (length >= static_cast<size_t>(String::kMinNonFlatLength)) {
-    is_ascii = false;
-  } else {
-    const uc16* data = resource->data();
-    for (size_t i = 0; i < length; i++) {
-      if (data[i] > String::kMaxAsciiCharCode) {
-        is_ascii = false;
-        break;
-      }
-    }
-  }
-
+  // ASCII characters.  If yes, we use a different string map.
+  static const size_t kAsciiCheckLengthLimit = 32;
+  bool is_ascii = length <= kAsciiCheckLengthLimit &&
+      String::IsAscii(resource->data(), static_cast<int>(length));
   Map* map = is_ascii ?
       Heap::external_string_with_ascii_data_map() : Heap::external_string_map();
   Object* result;
@@ -3307,8 +3297,8 @@
 }
 
 
-MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string,
-                                          PretenureFlag pretenure) {
+MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string,
+                                              PretenureFlag pretenure) {
   // V8 only supports characters in the Basic Multilingual Plane.
   const uc32 kMaxSupportedChar = 0xFFFF;
   // Count the number of characters in the UTF-8 string and check if
@@ -3317,17 +3307,11 @@
       decoder(ScannerConstants::utf8_decoder());
   decoder->Reset(string.start(), string.length());
   int chars = 0;
-  bool is_ascii = true;
   while (decoder->has_more()) {
-    uc32 r = decoder->GetNext();
-    if (r > String::kMaxAsciiCharCode) is_ascii = false;
+    decoder->GetNext();
     chars++;
   }
 
-  // If the string is ascii, we do not need to convert the characters
-  // since UTF8 is backwards compatible with ascii.
-  if (is_ascii) return AllocateStringFromAscii(string, pretenure);
-
   Object* result;
   { MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure);
     if (!maybe_result->ToObject(&result)) return maybe_result;
@@ -3348,11 +3332,8 @@
 MaybeObject* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
                                              PretenureFlag pretenure) {
   // Check if the string is an ASCII string.
-  int i = 0;
-  while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++;
-
   MaybeObject* maybe_result;
-  if (i == string.length()) {  // It's an ASCII string.
+  if (String::IsAscii(string.start(), string.length())) {
     maybe_result = AllocateRawAsciiString(string.length(), pretenure);
   } else {  // It's not an ASCII string.
     maybe_result = AllocateRawTwoByteString(string.length(), pretenure);
@@ -4032,6 +4013,36 @@
 }
 
 
+MaybeObject* Heap::LookupAsciiSymbol(Vector<const char> string) {
+  Object* symbol = NULL;
+  Object* new_table;
+  { MaybeObject* maybe_new_table =
+        symbol_table()->LookupAsciiSymbol(string, &symbol);
+    if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
+  }
+  // Can't use set_symbol_table because SymbolTable::cast knows that
+  // SymbolTable is a singleton and checks for identity.
+  roots_[kSymbolTableRootIndex] = new_table;
+  ASSERT(symbol != NULL);
+  return symbol;
+}
+
+
+MaybeObject* Heap::LookupTwoByteSymbol(Vector<const uc16> string) {
+  Object* symbol = NULL;
+  Object* new_table;
+  { MaybeObject* maybe_new_table =
+        symbol_table()->LookupTwoByteSymbol(string, &symbol);
+    if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
+  }
+  // Can't use set_symbol_table because SymbolTable::cast knows that
+  // SymbolTable is a singleton and checks for identity.
+  roots_[kSymbolTableRootIndex] = new_table;
+  ASSERT(symbol != NULL);
+  return symbol;
+}
+
+
 MaybeObject* Heap::LookupSymbol(String* string) {
   if (string->IsSymbol()) return string;
   Object* symbol = NULL;
diff --git a/src/heap.h b/src/heap.h
index 18a4afb..3ceefd8 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -412,7 +412,10 @@
   MUST_USE_RESULT static MaybeObject* AllocateStringFromAscii(
       Vector<const char> str,
       PretenureFlag pretenure = NOT_TENURED);
-  MUST_USE_RESULT static MaybeObject* AllocateStringFromUtf8(
+  MUST_USE_RESULT static inline MaybeObject* AllocateStringFromUtf8(
+      Vector<const char> str,
+      PretenureFlag pretenure = NOT_TENURED);
+  MUST_USE_RESULT static MaybeObject* AllocateStringFromUtf8Slow(
       Vector<const char> str,
       PretenureFlag pretenure = NOT_TENURED);
   MUST_USE_RESULT static MaybeObject* AllocateStringFromTwoByte(
@@ -428,6 +431,14 @@
       int chars,
       uint32_t hash_field);
 
+  MUST_USE_RESULT static inline MaybeObject* AllocateAsciiSymbol(
+        Vector<const char> str,
+        uint32_t hash_field);
+
+  MUST_USE_RESULT static inline MaybeObject* AllocateTwoByteSymbol(
+        Vector<const uc16> str,
+        uint32_t hash_field);
+
   MUST_USE_RESULT static MaybeObject* AllocateInternalSymbol(
       unibrow::CharacterStream* buffer, int chars, uint32_t hash_field);
 
@@ -683,6 +694,9 @@
   // failed.
   // Please note this function does not perform a garbage collection.
   MUST_USE_RESULT static MaybeObject* LookupSymbol(Vector<const char> str);
+  MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(Vector<const char> str);
+  MUST_USE_RESULT static MaybeObject* LookupTwoByteSymbol(
+      Vector<const uc16> str);
   MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(const char* str) {
     return LookupSymbol(CStrVector(str));
   }
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index cbbe8fc..e9c437f 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -76,7 +76,6 @@
 //       HLoadKeyed
 //         HLoadKeyedFastElement
 //         HLoadKeyedGeneric
-//       HLoadNamedGeneric
 //       HPower
 //       HStoreNamed
 //         HStoreNamedField
@@ -119,7 +118,6 @@
 //       HStoreKeyedFastElement
 //       HStoreKeyedGeneric
 //     HUnaryOperation
-//       HArrayLength
 //       HBitNot
 //       HChange
 //       HCheckFunction
@@ -129,9 +127,13 @@
 //       HCheckPrototypeMaps
 //       HCheckSmi
 //       HDeleteProperty
+//       HFixedArrayLength
+//       HJSArrayLength
 //       HLoadElements
 //         HTypeofIs
 //       HLoadNamedField
+//       HLoadNamedGeneric
+//       HLoadFunctionPrototype
 //       HPushArgument
 //       HTypeof
 //       HUnaryMathOperation
@@ -170,7 +172,6 @@
   V(ArgumentsElements)                         \
   V(ArgumentsLength)                           \
   V(ArgumentsObject)                           \
-  V(ArrayLength)                               \
   V(ArrayLiteral)                              \
   V(BitAnd)                                    \
   V(BitNot)                                    \
@@ -203,6 +204,7 @@
   V(Deoptimize)                                \
   V(Div)                                       \
   V(EnterInlined)                              \
+  V(FixedArrayLength)                          \
   V(FunctionLiteral)                           \
   V(GlobalObject)                              \
   V(GlobalReceiver)                            \
@@ -213,6 +215,7 @@
   V(IsSmi)                                     \
   V(HasInstanceType)                           \
   V(HasCachedArrayIndex)                       \
+  V(JSArrayLength)                             \
   V(ClassOfTest)                               \
   V(LeaveInlined)                              \
   V(LoadElements)                              \
@@ -221,6 +224,7 @@
   V(LoadKeyedGeneric)                          \
   V(LoadNamedField)                            \
   V(LoadNamedGeneric)                          \
+  V(LoadFunctionPrototype)                     \
   V(Mod)                                       \
   V(Mul)                                       \
   V(ObjectLiteral)                             \
@@ -256,6 +260,7 @@
   V(GlobalVars)                                \
   V(Maps)                                      \
   V(ArrayLengths)                              \
+  V(FunctionPrototypes)                        \
   V(OsrEntries)
 
 #define DECLARE_INSTRUCTION(type)                   \
@@ -1336,9 +1341,9 @@
 };
 
 
-class HArrayLength: public HUnaryOperation {
+class HJSArrayLength: public HUnaryOperation {
  public:
-  explicit HArrayLength(HValue* value) : HUnaryOperation(value) {
+  explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
     // The length of an array is stored as a tagged value in the array
     // object. It is guaranteed to be 32 bit integer, but it can be
     // represented as either a smi or heap number.
@@ -1351,7 +1356,23 @@
     return Representation::Tagged();
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array_length")
+  DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
+};
+
+
+class HFixedArrayLength: public HUnaryOperation {
+ public:
+  explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
+    set_representation(Representation::Tagged());
+    SetFlag(kDependsOnArrayLengths);
+    SetFlag(kUseGVN);
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
 };
 
 
@@ -1766,6 +1787,8 @@
 
   Handle<Object> handle() const { return handle_; }
 
+  bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
+
   virtual bool EmitAtUses() const { return !representation().IsDouble(); }
   virtual void PrintDataTo(StringStream* stream) const;
   virtual HType CalculateInferredType() const;
@@ -2617,6 +2640,27 @@
 };
 
 
+class HLoadFunctionPrototype: public HUnaryOperation {
+ public:
+  explicit HLoadFunctionPrototype(HValue* function)
+      : HUnaryOperation(function) {
+    set_representation(Representation::Tagged());
+    SetFlagMask(kDependsOnFunctionPrototypes);
+  }
+
+  HValue* function() const { return OperandAt(0); }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
+
+ protected:
+  virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
 class HLoadKeyed: public HBinaryOperation {
  public:
   HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
@@ -2663,6 +2707,12 @@
 };
 
 
+static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
+  return !value->type().IsSmi() &&
+      !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
+}
+
+
 class HStoreNamed: public HBinaryOperation {
  public:
   HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
@@ -2680,6 +2730,10 @@
   HValue* value() const { return OperandAt(1); }
   void set_value(HValue* value) { SetOperandAt(1, value); }
 
+  bool NeedsWriteBarrier() const {
+    return StoringValueNeedsWriteBarrier(value());
+  }
+
   DECLARE_INSTRUCTION(StoreNamed)
 
  protected:
@@ -2760,6 +2814,10 @@
   HValue* key() const { return OperandAt(1); }
   HValue* value() const { return OperandAt(2); }
 
+  bool NeedsWriteBarrier() const {
+    return StoringValueNeedsWriteBarrier(value());
+  }
+
   DECLARE_INSTRUCTION(StoreKeyed)
 
  protected:
@@ -2779,10 +2837,6 @@
     SetFlag(kChangesArrayElements);
   }
 
-  bool NeedsWriteBarrier() const {
-    return !value()->type().IsSmi();
-  }
-
   virtual Representation RequiredInputRepresentation(int index) const {
     // The key is supposed to be Integer32.
     return (index == 1) ? Representation::Integer32()
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index e34acd6..03ce5b3 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3643,9 +3643,18 @@
   Handle<Map> map = expr->GetMonomorphicReceiverType();
   ASSERT(map->has_fast_elements());
   AddInstruction(new HCheckMap(object, map));
-  HInstruction* elements = AddInstruction(new HLoadElements(object));
-  HInstruction* length = AddInstruction(new HArrayLength(elements));
-  AddInstruction(new HBoundsCheck(key, length));
+  bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
+  HLoadElements* elements = new HLoadElements(object);
+  HInstruction* length = NULL;
+  if (is_array) {
+    length = AddInstruction(new HJSArrayLength(object));
+    AddInstruction(new HBoundsCheck(key, length));
+    AddInstruction(elements);
+  } else {
+    AddInstruction(elements);
+    length = AddInstruction(new HFixedArrayLength(elements));
+    AddInstruction(new HBoundsCheck(key, length));
+  }
   return new HLoadKeyedFastElement(elements, key);
 }
 
@@ -3671,9 +3680,9 @@
   bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
   HInstruction* length = NULL;
   if (is_array) {
-    length = AddInstruction(new HArrayLength(object));
+    length = AddInstruction(new HJSArrayLength(object));
   } else {
-    length = AddInstruction(new HArrayLength(elements));
+    length = AddInstruction(new HFixedArrayLength(elements));
   }
   AddInstruction(new HBoundsCheck(key, length));
   return new HStoreKeyedFastElement(elements, key, val);
@@ -3720,7 +3729,13 @@
   if (expr->IsArrayLength()) {
     HValue* array = Pop();
     AddInstruction(new HCheckNonSmi(array));
-    instr = new HArrayLength(array);
+    AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE));
+    instr = new HJSArrayLength(array);
+
+  } else if (expr->IsFunctionPrototype()) {
+    HValue* function = Pop();
+    AddInstruction(new HCheckNonSmi(function));
+    instr = new HLoadFunctionPrototype(function);
 
   } else if (expr->key()->IsPropertyName()) {
     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
@@ -4854,7 +4869,9 @@
     switch (op) {
       case Token::EQ:
       case Token::EQ_STRICT: {
+        AddInstruction(new HCheckNonSmi(left));
         AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
+        AddInstruction(new HCheckNonSmi(right));
         AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
         instr = new HCompareJSObjectEq(left, right);
         break;
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 13a1177..5beec0d 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -379,7 +379,7 @@
 
 void FullCodeGenerator::AccumulatorValueContext::Plug(
     Handle<Object> lit) const {
-  __ mov(result_register(), lit);
+  __ Set(result_register(), Immediate(lit));
 }
 
 
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index d64f528..9569ac8 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -940,7 +940,7 @@
 
 void LCodeGen::DoConstantI(LConstantI* instr) {
   ASSERT(instr->result()->IsRegister());
-  __ mov(ToRegister(instr->result()), instr->value());
+  __ Set(ToRegister(instr->result()), Immediate(instr->value()));
 }
 
 
@@ -973,27 +973,21 @@
 
 void LCodeGen::DoConstantT(LConstantT* instr) {
   ASSERT(instr->result()->IsRegister());
-  __ mov(ToRegister(instr->result()), Immediate(instr->value()));
+  __ Set(ToRegister(instr->result()), Immediate(instr->value()));
 }
 
 
-void LCodeGen::DoArrayLength(LArrayLength* instr) {
+void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
   Register result = ToRegister(instr->result());
+  Register array = ToRegister(instr->input());
+  __ mov(result, FieldOperand(array, JSArray::kLengthOffset));
+}
 
-  if (instr->hydrogen()->value()->IsLoadElements()) {
-    // We load the length directly from the elements array.
-    Register elements = ToRegister(instr->input());
-    __ mov(result, FieldOperand(elements, FixedArray::kLengthOffset));
-  } else {
-    // Check that the receiver really is an array.
-    Register array = ToRegister(instr->input());
-    Register temporary = ToRegister(instr->temporary());
-    __ CmpObjectType(array, JS_ARRAY_TYPE, temporary);
-    DeoptimizeIf(not_equal, instr->environment());
 
-    // Load length directly from the array.
-    __ mov(result, FieldOperand(array, JSArray::kLengthOffset));
-  }
+void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
+  Register result = ToRegister(instr->result());
+  Register array = ToRegister(instr->input());
+  __ mov(result, FieldOperand(array, FixedArray::kLengthOffset));
 }
 
 
@@ -1837,6 +1831,48 @@
 }
 
 
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+  Register function = ToRegister(instr->function());
+  Register temp = ToRegister(instr->temporary());
+  Register result = ToRegister(instr->result());
+
+  // Check that the function really is a function.
+  __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
+  DeoptimizeIf(not_equal, instr->environment());
+
+  // Check whether the function has an instance prototype.
+  NearLabel non_instance;
+  __ test_b(FieldOperand(result, Map::kBitFieldOffset),
+            1 << Map::kHasNonInstancePrototype);
+  __ j(not_zero, &non_instance);
+
+  // Get the prototype or initial map from the function.
+  __ mov(result,
+         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // Check that the function has a prototype or an initial map.
+  __ cmp(Operand(result), Immediate(Factory::the_hole_value()));
+  DeoptimizeIf(equal, instr->environment());
+
+  // If the function does not have an initial map, we're done.
+  NearLabel done;
+  __ CmpObjectType(result, MAP_TYPE, temp);
+  __ j(not_equal, &done);
+
+  // Get the prototype from the initial map.
+  __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
+  __ jmp(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in the function's map.
+  __ bind(&non_instance);
+  __ mov(result, FieldOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  __ bind(&done);
+}
+
+
 void LCodeGen::DoLoadElements(LLoadElements* instr) {
   ASSERT(instr->result()->Equals(instr->input()));
   Register reg = ToRegister(instr->input());
@@ -2891,9 +2927,6 @@
   InstanceType first = instr->hydrogen()->first();
   InstanceType last = instr->hydrogen()->last();
 
-  __ test(input, Immediate(kSmiTagMask));
-  DeoptimizeIf(zero, instr->environment());
-
   __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
   __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
           static_cast<int8_t>(first));
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 3b272d0..8c003a5 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1677,19 +1677,15 @@
 }
 
 
-LInstruction* LChunkBuilder::DoArrayLength(HArrayLength* instr) {
-  LOperand* array = NULL;
-  LOperand* temporary = NULL;
+LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
+  LOperand* array = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LJSArrayLength(array));
+}
 
-  if (instr->value()->IsLoadElements()) {
-    array = UseRegisterAtStart(instr->value());
-  } else {
-    array = UseRegister(instr->value());
-    temporary = TempRegister();
-  }
 
-  LInstruction* result = new LArrayLength(array, temporary);
-  return AssignEnvironment(DefineAsRegister(result));
+LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
+  LOperand* array = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LFixedArrayLength(array));
 }
 
 
@@ -1860,6 +1856,14 @@
 }
 
 
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+    HLoadFunctionPrototype* instr) {
+  return AssignEnvironment(DefineAsRegister(
+      new LLoadFunctionPrototype(UseRegister(instr->function()),
+                                 TempRegister())));
+}
+
+
 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
   LOperand* input = UseRegisterAtStart(instr->value());
   return DefineSameAsFirst(new LLoadElements(input));
@@ -1931,7 +1935,7 @@
 
 
 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
-  bool needs_write_barrier = !instr->value()->type().IsSmi();
+  bool needs_write_barrier = instr->NeedsWriteBarrier();
 
   LOperand* obj = needs_write_barrier
       ? UseTempRegister(instr->object())
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 3f48e50..94bf8fd 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -104,7 +104,6 @@
 //     LStoreNamedField
 //     LStoreNamedGeneric
 //   LUnaryOperation
-//     LArrayLength
 //     LBitNotI
 //     LBranch
 //     LCallNew
@@ -117,6 +116,7 @@
 //     LClassOfTestAndBranch
 //     LDeleteProperty
 //     LDoubleToI
+//     LFixedArrayLength
 //     LHasCachedArrayIndex
 //     LHasCachedArrayIndexAndBranch
 //     LHasInstanceType
@@ -128,8 +128,10 @@
 //     LIsObjectAndBranch
 //     LIsSmi
 //     LIsSmiAndBranch
+//     LJSArrayLength
 //     LLoadNamedField
 //     LLoadNamedGeneric
+//     LLoadFunctionPrototype
 //     LNumberTagD
 //     LNumberTagI
 //     LPushArgument
@@ -164,7 +166,6 @@
   V(ArgumentsLength)                            \
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
-  V(ArrayLength)                                \
   V(ArrayLiteral)                               \
   V(BitI)                                       \
   V(BitNotI)                                    \
@@ -203,6 +204,7 @@
   V(GlobalObject)                               \
   V(GlobalReceiver)                             \
   V(Goto)                                       \
+  V(FixedArrayLength)                           \
   V(InstanceOf)                                 \
   V(InstanceOfAndBranch)                        \
   V(Integer32ToDouble)                          \
@@ -212,6 +214,7 @@
   V(IsObjectAndBranch)                          \
   V(IsSmi)                                      \
   V(IsSmiAndBranch)                             \
+  V(JSArrayLength)                              \
   V(HasInstanceType)                            \
   V(HasInstanceTypeAndBranch)                   \
   V(HasCachedArrayIndex)                        \
@@ -226,6 +229,7 @@
   V(LoadKeyedGeneric)                           \
   V(LoadNamedField)                             \
   V(LoadNamedGeneric)                           \
+  V(LoadFunctionPrototype)                      \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -1146,18 +1150,21 @@
 };
 
 
-class LArrayLength: public LUnaryOperation {
+class LJSArrayLength: public LUnaryOperation {
  public:
-  LArrayLength(LOperand* input, LOperand* temporary)
-      : LUnaryOperation(input), temporary_(temporary) { }
+  explicit LJSArrayLength(LOperand* input) : LUnaryOperation(input) { }
 
-  LOperand* temporary() const { return temporary_; }
+  DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
+};
 
-  DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array-length")
-  DECLARE_HYDROGEN_ACCESSOR(ArrayLength)
 
- private:
-  LOperand* temporary_;
+class LFixedArrayLength: public LUnaryOperation {
+ public:
+  explicit LFixedArrayLength(LOperand* input) : LUnaryOperation(input) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(FixedArrayLength)
 };
 
 
@@ -1271,6 +1278,22 @@
 };
 
 
+class LLoadFunctionPrototype: public LUnaryOperation {
+ public:
+  LLoadFunctionPrototype(LOperand* function, LOperand* temporary)
+      : LUnaryOperation(function), temporary_(temporary) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
+  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
+
+  LOperand* function() const { return input(); }
+  LOperand* temporary() const { return temporary_; }
+
+ private:
+  LOperand* temporary_;
+};
+
+
 class LLoadElements: public LUnaryOperation {
  public:
   explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index d435a70..cc2f30d 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -211,9 +211,7 @@
   // If input is ASCII, don't even bother calling here if the string to
   // match contains a non-ascii character.
   if (mode_ == ASCII) {
-    for (int i = 0; i < str.length(); i++) {
-      ASSERT(str[i] <= String::kMaxAsciiCharCodeU);
-    }
+    ASSERT(String::IsAscii(str.start(), str.length()));
   }
 #endif
   int byte_length = str.length() * char_size();
diff --git a/src/json.js b/src/json.js
index 89009a9..0034176 100644
--- a/src/json.js
+++ b/src/json.js
@@ -27,11 +27,6 @@
 
 var $JSON = global.JSON;
 
-function ParseJSONUnfiltered(text) {
-  var s = $String(text);
-  return %ParseJson(s);
-}
-
 function Revive(holder, name, reviver) {
   var val = holder[name];
   if (IS_OBJECT(val)) {
@@ -58,7 +53,7 @@
 }
 
 function JSONParse(text, reviver) {
-  var unfiltered = ParseJSONUnfiltered(text);
+  var unfiltered = %ParseJson(TO_STRING_INLINE(text));
   if (IS_FUNCTION(reviver)) {
     return Revive({'': unfiltered}, '', reviver);
   } else {
@@ -158,7 +153,7 @@
   if (IS_STRING(value)) {
     return %QuoteJSONString(value);
   } else if (IS_NUMBER(value)) {
-    return $isFinite(value) ? $String(value) : "null";
+    return NUMBER_IS_FINITE(value) ? $String(value) : "null";
   } else if (IS_BOOLEAN(value)) {
     return value ? "true" : "false";
   } else if (IS_NULL(value)) {
@@ -169,7 +164,7 @@
       return SerializeArray(value, replacer, stack, indent, gap);
     } else if (IS_NUMBER_WRAPPER(value)) {
       value = ToNumber(value);
-      return $isFinite(value) ? ToString(value) : "null";
+      return NUMBER_IS_FINITE(value) ? ToString(value) : "null";
     } else if (IS_STRING_WRAPPER(value)) {
       return %QuoteJSONString(ToString(value));
     } else if (IS_BOOLEAN_WRAPPER(value)) {
@@ -244,7 +239,7 @@
   if (IS_STRING(value)) {
     builder.push(%QuoteJSONString(value));
   } else if (IS_NUMBER(value)) {
-    builder.push(($isFinite(value) ? %_NumberToString(value) : "null"));
+    builder.push(NUMBER_IS_FINITE(value) ? %_NumberToString(value) : "null");
   } else if (IS_BOOLEAN(value)) {
     builder.push(value ? "true" : "false");
   } else if (IS_NULL(value)) {
@@ -254,7 +249,7 @@
     // Unwrap value if necessary
     if (IS_NUMBER_WRAPPER(value)) {
       value = ToNumber(value);
-      builder.push(($isFinite(value) ? %_NumberToString(value) : "null"));
+      builder.push(NUMBER_IS_FINITE(value) ? %_NumberToString(value) : "null");
     } else if (IS_STRING_WRAPPER(value)) {
       builder.push(%QuoteJSONString(ToString(value)));
     } else if (IS_BOOLEAN_WRAPPER(value)) {
diff --git a/src/liveedit-debugger.js b/src/liveedit-debugger.js
index 0f7c12d..7ed22c8 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -144,8 +144,8 @@
           replace_code_list[i].live_shared_function_infos;
 
       if (live_shared_function_infos) {
-        for (var i = 0; i < live_shared_function_infos.length; i++) {
-          replaced_function_infos.push(live_shared_function_infos[i]);
+        for (var j = 0; j < live_shared_function_infos.length; j++) {
+          replaced_function_infos.push(live_shared_function_infos[j]);
         }
       }
     }
diff --git a/src/macros.py b/src/macros.py
index 6d66def..01512e4 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -120,6 +120,7 @@
 
 # Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
 macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
+macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || arg - arg == 0);
 macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToInteger(ToNumber(arg)));
 macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(ToNumber(arg)));
 macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 55836ce..9177a6b 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -2369,7 +2369,7 @@
   if (isNaN(value)) {
     return 'NaN';
   }
-  if (!isFinite(value)) {
+  if (!NUMBER_IS_FINITE(value)) {
     if (value > 0) {
       return 'Infinity';
     } else {
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 53296d9..0b83182 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2010 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,34 +35,8 @@
 namespace v8 {
 namespace internal {
 
-#ifdef OBJECT_PRINT
-
-static const char* TypeToString(InstanceType type);
-
-
-void MaybeObject::Print(FILE* out) {
-  Object* this_as_object;
-  if (ToObject(&this_as_object)) {
-    if (this_as_object->IsSmi()) {
-      Smi::cast(this_as_object)->SmiPrint(out);
-    } else {
-      HeapObject::cast(this_as_object)->HeapObjectPrint(out);
-    }
-  } else {
-    Failure::cast(this)->FailurePrint(out);
-  }
-  Flush(out);
-}
-
-
-void MaybeObject::PrintLn(FILE* out) {
-  Print(out);
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
 #ifdef DEBUG
+
 void MaybeObject::Verify() {
   Object* this_as_object;
   if (ToObject(&this_as_object)) {
@@ -94,120 +68,8 @@
 void Failure::FailureVerify() {
   ASSERT(IsFailure());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void HeapObject::PrintHeader(FILE* out, const char* id) {
-  PrintF(out, "%p: [%s]\n", reinterpret_cast<void*>(this), id);
-}
-
-
-void HeapObject::HeapObjectPrint(FILE* out) {
-  InstanceType instance_type = map()->instance_type();
-
-  HandleScope scope;
-  if (instance_type < FIRST_NONSTRING_TYPE) {
-    String::cast(this)->StringPrint(out);
-    return;
-  }
-
-  switch (instance_type) {
-    case MAP_TYPE:
-      Map::cast(this)->MapPrint(out);
-      break;
-    case HEAP_NUMBER_TYPE:
-      HeapNumber::cast(this)->HeapNumberPrint(out);
-      break;
-    case FIXED_ARRAY_TYPE:
-      FixedArray::cast(this)->FixedArrayPrint(out);
-      break;
-    case BYTE_ARRAY_TYPE:
-      ByteArray::cast(this)->ByteArrayPrint(out);
-      break;
-    case PIXEL_ARRAY_TYPE:
-      PixelArray::cast(this)->PixelArrayPrint(out);
-      break;
-    case EXTERNAL_BYTE_ARRAY_TYPE:
-      ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
-      break;
-    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
-      ExternalUnsignedByteArray::cast(this)
-          ->ExternalUnsignedByteArrayPrint(out);
-      break;
-    case EXTERNAL_SHORT_ARRAY_TYPE:
-      ExternalShortArray::cast(this)->ExternalShortArrayPrint(out);
-      break;
-    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
-      ExternalUnsignedShortArray::cast(this)
-          ->ExternalUnsignedShortArrayPrint(out);
-      break;
-    case EXTERNAL_INT_ARRAY_TYPE:
-      ExternalIntArray::cast(this)->ExternalIntArrayPrint(out);
-      break;
-    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
-      ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint(out);
-      break;
-    case EXTERNAL_FLOAT_ARRAY_TYPE:
-      ExternalFloatArray::cast(this)->ExternalFloatArrayPrint(out);
-      break;
-    case FILLER_TYPE:
-      PrintF(out, "filler");
-      break;
-    case JS_OBJECT_TYPE:  // fall through
-    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
-    case JS_ARRAY_TYPE:
-    case JS_REGEXP_TYPE:
-      JSObject::cast(this)->JSObjectPrint(out);
-      break;
-    case ODDBALL_TYPE:
-      Oddball::cast(this)->to_string()->Print(out);
-      break;
-    case JS_FUNCTION_TYPE:
-      JSFunction::cast(this)->JSFunctionPrint(out);
-      break;
-    case JS_GLOBAL_PROXY_TYPE:
-      JSGlobalProxy::cast(this)->JSGlobalProxyPrint(out);
-      break;
-    case JS_GLOBAL_OBJECT_TYPE:
-      JSGlobalObject::cast(this)->JSGlobalObjectPrint(out);
-      break;
-    case JS_BUILTINS_OBJECT_TYPE:
-      JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(out);
-      break;
-    case JS_VALUE_TYPE:
-      PrintF(out, "Value wrapper around:");
-      JSValue::cast(this)->value()->Print(out);
-      break;
-    case CODE_TYPE:
-      Code::cast(this)->CodePrint(out);
-      break;
-    case PROXY_TYPE:
-      Proxy::cast(this)->ProxyPrint(out);
-      break;
-    case SHARED_FUNCTION_INFO_TYPE:
-      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
-      break;
-    case JS_GLOBAL_PROPERTY_CELL_TYPE:
-      JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
-      break;
-#define MAKE_STRUCT_CASE(NAME, Name, name) \
-  case NAME##_TYPE:                        \
-    Name::cast(this)->Name##Print(out);    \
-    break;
-  STRUCT_LIST(MAKE_STRUCT_CASE)
-#undef MAKE_STRUCT_CASE
-
-    default:
-      PrintF(out, "UNKNOWN TYPE %d", map()->instance_type());
-      UNREACHABLE();
-      break;
-  }
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void HeapObject::HeapObjectVerify() {
   InstanceType instance_type = map()->instance_type();
 
@@ -320,57 +182,8 @@
 void HeapNumber::HeapNumberVerify() {
   ASSERT(IsHeapNumber());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void ByteArray::ByteArrayPrint(FILE* out) {
-  PrintF(out, "byte array, data starts at %p", GetDataStartAddress());
-}
-
-
-void PixelArray::PixelArrayPrint(FILE* out) {
-  PrintF(out, "pixel array");
-}
-
-
-void ExternalByteArray::ExternalByteArrayPrint(FILE* out) {
-  PrintF(out, "external byte array");
-}
-
-
-void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint(FILE* out) {
-  PrintF(out, "external unsigned byte array");
-}
-
-
-void ExternalShortArray::ExternalShortArrayPrint(FILE* out) {
-  PrintF(out, "external short array");
-}
-
-
-void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint(FILE* out) {
-  PrintF(out, "external unsigned short array");
-}
-
-
-void ExternalIntArray::ExternalIntArrayPrint(FILE* out) {
-  PrintF(out, "external int array");
-}
-
-
-void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint(FILE* out) {
-  PrintF(out, "external unsigned int array");
-}
-
-
-void ExternalFloatArray::ExternalFloatArrayPrint(FILE* out) {
-  PrintF(out, "external float array");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void ByteArray::ByteArrayVerify() {
   ASSERT(IsByteArray());
 }
@@ -414,146 +227,8 @@
 void ExternalFloatArray::ExternalFloatArrayVerify() {
   ASSERT(IsExternalFloatArray());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void JSObject::PrintProperties(FILE* out) {
-  if (HasFastProperties()) {
-    DescriptorArray* descs = map()->instance_descriptors();
-    for (int i = 0; i < descs->number_of_descriptors(); i++) {
-      PrintF(out, "   ");
-      descs->GetKey(i)->StringPrint(out);
-      PrintF(out, ": ");
-      switch (descs->GetType(i)) {
-        case FIELD: {
-          int index = descs->GetFieldIndex(i);
-          FastPropertyAt(index)->ShortPrint(out);
-          PrintF(out, " (field at offset %d)\n", index);
-          break;
-        }
-        case CONSTANT_FUNCTION:
-          descs->GetConstantFunction(i)->ShortPrint(out);
-          PrintF(out, " (constant function)\n");
-          break;
-        case CALLBACKS:
-          descs->GetCallbacksObject(i)->ShortPrint(out);
-          PrintF(out, " (callback)\n");
-          break;
-        case MAP_TRANSITION:
-          PrintF(out, " (map transition)\n");
-          break;
-        case CONSTANT_TRANSITION:
-          PrintF(out, " (constant transition)\n");
-          break;
-        case NULL_DESCRIPTOR:
-          PrintF(out, " (null descriptor)\n");
-          break;
-        default:
-          UNREACHABLE();
-          break;
-      }
-    }
-  } else {
-    property_dictionary()->Print(out);
-  }
-}
-
-
-void JSObject::PrintElements(FILE* out) {
-  switch (GetElementsKind()) {
-    case FAST_ELEMENTS: {
-      // Print in array notation for non-sparse arrays.
-      FixedArray* p = FixedArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: ", i);
-        p->get(i)->ShortPrint(out);
-        PrintF(out, "\n");
-      }
-      break;
-    }
-    case PIXEL_ELEMENTS: {
-      PixelArray* p = PixelArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, p->get(i));
-      }
-      break;
-    }
-    case EXTERNAL_BYTE_ELEMENTS: {
-      ExternalByteArray* p = ExternalByteArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
-      }
-      break;
-    }
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
-      ExternalUnsignedByteArray* p =
-          ExternalUnsignedByteArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
-      }
-      break;
-    }
-    case EXTERNAL_SHORT_ELEMENTS: {
-      ExternalShortArray* p = ExternalShortArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
-      }
-      break;
-    }
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
-      ExternalUnsignedShortArray* p =
-          ExternalUnsignedShortArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
-      }
-      break;
-    }
-    case EXTERNAL_INT_ELEMENTS: {
-      ExternalIntArray* p = ExternalIntArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
-      }
-      break;
-    }
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
-      ExternalUnsignedIntArray* p =
-          ExternalUnsignedIntArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
-      }
-      break;
-    }
-    case EXTERNAL_FLOAT_ELEMENTS: {
-      ExternalFloatArray* p = ExternalFloatArray::cast(elements());
-      for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %f\n", i, p->get(i));
-      }
-      break;
-    }
-    case DICTIONARY_ELEMENTS:
-      elements()->Print(out);
-      break;
-    default:
-      UNREACHABLE();
-      break;
-  }
-}
-
-
-void JSObject::JSObjectPrint(FILE* out) {
-  PrintF(out, "%p: [JSObject]\n", reinterpret_cast<void*>(this));
-  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
-  PrintF(out, " - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
-  PrintF(out, " {\n");
-  PrintProperties(out);
-  PrintElements(out);
-  PrintF(out, " }\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void JSObject::JSObjectVerify() {
   VerifyHeapPointer(properties());
   VerifyHeapPointer(elements());
@@ -567,103 +242,8 @@
           elements()->map() == Heap::fixed_cow_array_map()));
   ASSERT(map()->has_fast_elements() == HasFastElements());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-static const char* TypeToString(InstanceType type) {
-  switch (type) {
-    case INVALID_TYPE: return "INVALID";
-    case MAP_TYPE: return "MAP";
-    case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
-    case SYMBOL_TYPE: return "SYMBOL";
-    case ASCII_SYMBOL_TYPE: return "ASCII_SYMBOL";
-    case CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
-    case CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
-    case EXTERNAL_ASCII_SYMBOL_TYPE:
-    case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
-    case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
-    case ASCII_STRING_TYPE: return "ASCII_STRING";
-    case STRING_TYPE: return "TWO_BYTE_STRING";
-    case CONS_STRING_TYPE:
-    case CONS_ASCII_STRING_TYPE: return "CONS_STRING";
-    case EXTERNAL_ASCII_STRING_TYPE:
-    case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
-    case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
-    case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
-    case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
-    case PIXEL_ARRAY_TYPE: return "PIXEL_ARRAY";
-    case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
-    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
-      return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
-    case EXTERNAL_SHORT_ARRAY_TYPE: return "EXTERNAL_SHORT_ARRAY";
-    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
-      return "EXTERNAL_UNSIGNED_SHORT_ARRAY";
-    case EXTERNAL_INT_ARRAY_TYPE: return "EXTERNAL_INT_ARRAY";
-    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
-      return "EXTERNAL_UNSIGNED_INT_ARRAY";
-    case EXTERNAL_FLOAT_ARRAY_TYPE: return "EXTERNAL_FLOAT_ARRAY";
-    case FILLER_TYPE: return "FILLER";
-    case JS_OBJECT_TYPE: return "JS_OBJECT";
-    case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
-    case ODDBALL_TYPE: return "ODDBALL";
-    case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
-    case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
-    case JS_FUNCTION_TYPE: return "JS_FUNCTION";
-    case CODE_TYPE: return "CODE";
-    case JS_ARRAY_TYPE: return "JS_ARRAY";
-    case JS_REGEXP_TYPE: return "JS_REGEXP";
-    case JS_VALUE_TYPE: return "JS_VALUE";
-    case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
-    case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
-    case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
-    case PROXY_TYPE: return "PROXY";
-#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
-  STRUCT_LIST(MAKE_STRUCT_CASE)
-#undef MAKE_STRUCT_CASE
-  }
-  return "UNKNOWN";
-}
-
-
-void Map::MapPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "Map");
-  PrintF(out, " - type: %s\n", TypeToString(instance_type()));
-  PrintF(out, " - instance size: %d\n", instance_size());
-  PrintF(out, " - inobject properties: %d\n", inobject_properties());
-  PrintF(out, " - pre-allocated property fields: %d\n",
-      pre_allocated_property_fields());
-  PrintF(out, " - unused property fields: %d\n", unused_property_fields());
-  if (is_hidden_prototype()) {
-    PrintF(out, " - hidden_prototype\n");
-  }
-  if (has_named_interceptor()) {
-    PrintF(out, " - named_interceptor\n");
-  }
-  if (has_indexed_interceptor()) {
-    PrintF(out, " - indexed_interceptor\n");
-  }
-  if (is_undetectable()) {
-    PrintF(out, " - undetectable\n");
-  }
-  if (has_instance_call_handler()) {
-    PrintF(out, " - instance_call_handler\n");
-  }
-  if (is_access_check_needed()) {
-    PrintF(out, " - access_check_needed\n");
-  }
-  PrintF(out, " - instance descriptors: ");
-  instance_descriptors()->ShortPrint(out);
-  PrintF(out, "\n - prototype: ");
-  prototype()->ShortPrint(out);
-  PrintF(out, "\n - constructor: ");
-  constructor()->ShortPrint(out);
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void Map::MapVerify() {
   ASSERT(!Heap::InNewSpace(this));
   ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
@@ -685,21 +265,8 @@
   ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
       visitor_id());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void CodeCache::CodeCachePrint(FILE* out) {
-  HeapObject::PrintHeader(out, "CodeCache");
-  PrintF(out, "\n - default_cache: ");
-  default_cache()->ShortPrint(out);
-  PrintF(out, "\n - normal_type_cache: ");
-  normal_type_cache()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void CodeCache::CodeCacheVerify() {
   VerifyHeapPointer(default_cache());
   VerifyHeapPointer(normal_type_cache());
@@ -707,23 +274,8 @@
   ASSERT(normal_type_cache()->IsUndefined()
          || normal_type_cache()->IsCodeCacheHashTable());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void FixedArray::FixedArrayPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "FixedArray");
-  PrintF(out, " - length: %d", length());
-  for (int i = 0; i < length(); i++) {
-    PrintF(out, "\n  [%d]: ", i);
-    get(i)->ShortPrint(out);
-  }
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void FixedArray::FixedArrayVerify() {
   for (int i = 0; i < length(); i++) {
     Object* e = get(i);
@@ -734,57 +286,16 @@
     }
   }
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void JSValue::JSValuePrint(FILE* out) {
-  HeapObject::PrintHeader(out, "ValueObject");
-  value()->Print(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void JSValue::JSValueVerify() {
   Object* v = value();
   if (v->IsHeapObject()) {
     VerifyHeapPointer(v);
   }
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void String::StringPrint(FILE* out) {
-  if (StringShape(this).IsSymbol()) {
-    PrintF(out, "#");
-  } else if (StringShape(this).IsCons()) {
-    PrintF(out, "c\"");
-  } else {
-    PrintF(out, "\"");
-  }
-
-  const char truncated_epilogue[] = "...<truncated>";
-  int len = length();
-  if (!FLAG_use_verbose_printer) {
-    if (len > 100) {
-      len = 100 - sizeof(truncated_epilogue);
-    }
-  }
-  for (int i = 0; i < len; i++) {
-    PrintF(out, "%c", Get(i));
-  }
-  if (len != length()) {
-    PrintF(out, "%s", truncated_epilogue);
-  }
-
-  if (!StringShape(this).IsSymbol()) PrintF(out, "\"");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void String::StringVerify() {
   CHECK(IsString());
   CHECK(length() >= 0 && length() <= Smi::kMaxValue);
@@ -792,36 +303,8 @@
     CHECK(!Heap::InNewSpace(this));
   }
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void JSFunction::JSFunctionPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "Function");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
-  PrintF(out, " - initial_map = ");
-  if (has_initial_map()) {
-    initial_map()->ShortPrint(out);
-  }
-  PrintF(out, "\n - shared_info = ");
-  shared()->ShortPrint(out);
-  PrintF(out, "\n   - name = ");
-  shared()->name()->Print(out);
-  PrintF(out, "\n - context = ");
-  unchecked_context()->ShortPrint(out);
-  PrintF(out, "\n - code = ");
-  code()->ShortPrint(out);
-  PrintF(out, "\n");
-
-  PrintProperties(out);
-  PrintElements(out);
-
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void JSFunction::JSFunctionVerify() {
   CHECK(IsJSFunction());
   VerifyObjectField(kPrototypeOrInitialMapOffset);
@@ -829,41 +312,8 @@
   CHECK(next_function_link()->IsUndefined() ||
         next_function_link()->IsJSFunction());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "SharedFunctionInfo");
-  PrintF(out, " - name: ");
-  name()->ShortPrint(out);
-  PrintF(out, "\n - expected_nof_properties: %d", expected_nof_properties());
-  PrintF(out, "\n - instance class name = ");
-  instance_class_name()->Print(out);
-  PrintF(out, "\n - code = ");
-  code()->ShortPrint(out);
-  PrintF(out, "\n - source code = ");
-  GetSourceCode()->ShortPrint(out);
-  // Script files are often large, hard to read.
-  // PrintF(out, "\n - script =");
-  // script()->Print(out);
-  PrintF(out, "\n - function token position = %d", function_token_position());
-  PrintF(out, "\n - start position = %d", start_position());
-  PrintF(out, "\n - end position = %d", end_position());
-  PrintF(out, "\n - is expression = %d", is_expression());
-  PrintF(out, "\n - debug info = ");
-  debug_info()->ShortPrint(out);
-  PrintF(out, "\n - length = %d", length());
-  PrintF(out, "\n - has_only_simple_this_property_assignments = %d",
-         has_only_simple_this_property_assignments());
-  PrintF(out, "\n - this_property_assignments = ");
-  this_property_assignments()->ShortPrint(out);
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void SharedFunctionInfo::SharedFunctionInfoVerify() {
   CHECK(IsSharedFunctionInfo());
   VerifyObjectField(kNameOffset);
@@ -874,21 +324,8 @@
   VerifyObjectField(kScriptOffset);
   VerifyObjectField(kDebugInfoOffset);
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void JSGlobalProxy::JSGlobalProxyPrint(FILE* out) {
-  PrintF(out, "global_proxy");
-  JSObjectPrint(out);
-  PrintF(out, "context : ");
-  context()->ShortPrint(out);
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void JSGlobalProxy::JSGlobalProxyVerify() {
   CHECK(IsJSGlobalProxy());
   JSObjectVerify();
@@ -898,21 +335,8 @@
   CHECK(HasFastElements());
   CHECK_EQ(0, FixedArray::cast(elements())->length());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void JSGlobalObject::JSGlobalObjectPrint(FILE* out) {
-  PrintF(out, "global ");
-  JSObjectPrint(out);
-  PrintF(out, "global context : ");
-  global_context()->ShortPrint(out);
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void JSGlobalObject::JSGlobalObjectVerify() {
   CHECK(IsJSGlobalObject());
   JSObjectVerify();
@@ -922,18 +346,8 @@
     VerifyObjectField(i);
   }
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void JSBuiltinsObject::JSBuiltinsObjectPrint(FILE* out) {
-  PrintF(out, "builtins ");
-  JSObjectPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void JSBuiltinsObject::JSBuiltinsObjectVerify() {
   CHECK(IsJSBuiltinsObject());
   JSObjectVerify();
@@ -964,27 +378,8 @@
   CHECK(IsJSGlobalPropertyCell());
   VerifyObjectField(kValueOffset);
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
-}
-
-
-void Code::CodePrint(FILE* out) {
-  HeapObject::PrintHeader(out, "Code");
-#ifdef ENABLE_DISASSEMBLER
-  if (FLAG_use_verbose_printer) {
-    Disassemble(NULL, out);
-  }
-#endif
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void Code::CodeVerify() {
   CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
                   kCodeAlignment));
@@ -1039,17 +434,8 @@
       break;
   }
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void Proxy::ProxyPrint(FILE* out) {
-  PrintF(out, "proxy to %p", proxy());
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void Proxy::ProxyVerify() {
   ASSERT(IsProxy());
 }
@@ -1063,50 +449,16 @@
   VerifyPointer(data());
   VerifyPointer(flag());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void AccessorInfo::AccessorInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "AccessorInfo");
-  PrintF(out, "\n - getter: ");
-  getter()->ShortPrint(out);
-  PrintF(out, "\n - setter: ");
-  setter()->ShortPrint(out);
-  PrintF(out, "\n - name: ");
-  name()->ShortPrint(out);
-  PrintF(out, "\n - data: ");
-  data()->ShortPrint(out);
-  PrintF(out, "\n - flag: ");
-  flag()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void AccessCheckInfo::AccessCheckInfoVerify() {
   CHECK(IsAccessCheckInfo());
   VerifyPointer(named_callback());
   VerifyPointer(indexed_callback());
   VerifyPointer(data());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "AccessCheckInfo");
-  PrintF(out, "\n - named_callback: ");
-  named_callback()->ShortPrint(out);
-  PrintF(out, "\n - indexed_callback: ");
-  indexed_callback()->ShortPrint(out);
-  PrintF(out, "\n - data: ");
-  data()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void InterceptorInfo::InterceptorInfoVerify() {
   CHECK(IsInterceptorInfo());
   VerifyPointer(getter());
@@ -1116,50 +468,15 @@
   VerifyPointer(enumerator());
   VerifyPointer(data());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void InterceptorInfo::InterceptorInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "InterceptorInfo");
-  PrintF(out, "\n - getter: ");
-  getter()->ShortPrint(out);
-  PrintF(out, "\n - setter: ");
-  setter()->ShortPrint(out);
-  PrintF(out, "\n - query: ");
-  query()->ShortPrint(out);
-  PrintF(out, "\n - deleter: ");
-  deleter()->ShortPrint(out);
-  PrintF(out, "\n - enumerator: ");
-  enumerator()->ShortPrint(out);
-  PrintF(out, "\n - data: ");
-  data()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void CallHandlerInfo::CallHandlerInfoVerify() {
   CHECK(IsCallHandlerInfo());
   VerifyPointer(callback());
   VerifyPointer(data());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void CallHandlerInfo::CallHandlerInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "CallHandlerInfo");
-  PrintF(out, "\n - callback: ");
-  callback()->ShortPrint(out);
-  PrintF(out, "\n - data: ");
-  data()->ShortPrint(out);
-  PrintF(out, "\n - call_stub_cache: ");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void TemplateInfo::TemplateInfoVerify() {
   VerifyPointer(tag());
   VerifyPointer(property_list());
@@ -1179,106 +496,29 @@
   VerifyPointer(signature());
   VerifyPointer(access_check_info());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void FunctionTemplateInfo::FunctionTemplateInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "FunctionTemplateInfo");
-  PrintF(out, "\n - class name: ");
-  class_name()->ShortPrint(out);
-  PrintF(out, "\n - tag: ");
-  tag()->ShortPrint(out);
-  PrintF(out, "\n - property_list: ");
-  property_list()->ShortPrint(out);
-  PrintF(out, "\n - serial_number: ");
-  serial_number()->ShortPrint(out);
-  PrintF(out, "\n - call_code: ");
-  call_code()->ShortPrint(out);
-  PrintF(out, "\n - property_accessors: ");
-  property_accessors()->ShortPrint(out);
-  PrintF(out, "\n - prototype_template: ");
-  prototype_template()->ShortPrint(out);
-  PrintF(out, "\n - parent_template: ");
-  parent_template()->ShortPrint(out);
-  PrintF(out, "\n - named_property_handler: ");
-  named_property_handler()->ShortPrint(out);
-  PrintF(out, "\n - indexed_property_handler: ");
-  indexed_property_handler()->ShortPrint(out);
-  PrintF(out, "\n - instance_template: ");
-  instance_template()->ShortPrint(out);
-  PrintF(out, "\n - signature: ");
-  signature()->ShortPrint(out);
-  PrintF(out, "\n - access_check_info: ");
-  access_check_info()->ShortPrint(out);
-  PrintF(out, "\n - hidden_prototype: %s",
-         hidden_prototype() ? "true" : "false");
-  PrintF(out, "\n - undetectable: %s", undetectable() ? "true" : "false");
-  PrintF(out, "\n - need_access_check: %s",
-         needs_access_check() ? "true" : "false");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
   CHECK(IsObjectTemplateInfo());
   TemplateInfoVerify();
   VerifyPointer(constructor());
   VerifyPointer(internal_field_count());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void ObjectTemplateInfo::ObjectTemplateInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "ObjectTemplateInfo");
-  PrintF(out, "\n - constructor: ");
-  constructor()->ShortPrint(out);
-  PrintF(out, "\n - internal_field_count: ");
-  internal_field_count()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void SignatureInfo::SignatureInfoVerify() {
   CHECK(IsSignatureInfo());
   VerifyPointer(receiver());
   VerifyPointer(args());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void SignatureInfo::SignatureInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "SignatureInfo");
-  PrintF(out, "\n - receiver: ");
-  receiver()->ShortPrint(out);
-  PrintF(out, "\n - args: ");
-  args()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void TypeSwitchInfo::TypeSwitchInfoVerify() {
   CHECK(IsTypeSwitchInfo());
   VerifyPointer(types());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void TypeSwitchInfo::TypeSwitchInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "TypeSwitchInfo");
-  PrintF(out, "\n - types: ");
-  types()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void Script::ScriptVerify() {
   CHECK(IsScript());
   VerifyPointer(source());
@@ -1291,45 +531,9 @@
   VerifyPointer(line_ends());
   VerifyPointer(id());
 }
-#endif  // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void Script::ScriptPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "Script");
-  PrintF(out, "\n - source: ");
-  source()->ShortPrint(out);
-  PrintF(out, "\n - name: ");
-  name()->ShortPrint(out);
-  PrintF(out, "\n - line_offset: ");
-  line_offset()->ShortPrint(out);
-  PrintF(out, "\n - column_offset: ");
-  column_offset()->ShortPrint(out);
-  PrintF(out, "\n - type: ");
-  type()->ShortPrint(out);
-  PrintF(out, "\n - id: ");
-  id()->ShortPrint(out);
-  PrintF(out, "\n - data: ");
-  data()->ShortPrint(out);
-  PrintF(out, "\n - context data: ");
-  context_data()->ShortPrint(out);
-  PrintF(out, "\n - wrapper: ");
-  wrapper()->ShortPrint(out);
-  PrintF(out, "\n - compilation type: ");
-  compilation_type()->ShortPrint(out);
-  PrintF(out, "\n - line ends: ");
-  line_ends()->ShortPrint(out);
-  PrintF(out, "\n - eval from shared: ");
-  eval_from_shared()->ShortPrint(out);
-  PrintF(out, "\n - eval from instructions offset: ");
-  eval_from_instructions_offset()->ShortPrint(out);
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-#ifdef DEBUG
 void DebugInfo::DebugInfoVerify() {
   CHECK(IsDebugInfo());
   VerifyPointer(shared());
@@ -1337,25 +541,8 @@
   VerifyPointer(code());
   VerifyPointer(break_points());
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void DebugInfo::DebugInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "DebugInfo");
-  PrintF(out, "\n - shared: ");
-  shared()->ShortPrint(out);
-  PrintF(out, "\n - original_code: ");
-  original_code()->ShortPrint(out);
-  PrintF(out, "\n - code: ");
-  code()->ShortPrint(out);
-  PrintF(out, "\n - break_points: ");
-  break_points()->Print(out);
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 void BreakPointInfo::BreakPointInfoVerify() {
   CHECK(IsBreakPointInfo());
   code_position()->SmiVerify();
@@ -1363,23 +550,9 @@
   statement_position()->SmiVerify();
   VerifyPointer(break_point_objects());
 }
-#endif  // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void BreakPointInfo::BreakPointInfoPrint(FILE* out) {
-  HeapObject::PrintHeader(out, "BreakPointInfo");
-  PrintF(out, "\n - code_position: %d", code_position()->value());
-  PrintF(out, "\n - source_position: %d", source_position()->value());
-  PrintF(out, "\n - statement_position: %d", statement_position()->value());
-  PrintF(out, "\n - break_point_objects: ");
-  break_point_objects()->ShortPrint(out);
-}
-#endif  // OBJECT_PRINT
 #endif  // ENABLE_DEBUGGER_SUPPORT
 
 
-#ifdef DEBUG
 void JSObject::IncrementSpillStatistics(SpillInformation* info) {
   info->number_of_objects_++;
   // Named properties
@@ -1462,24 +635,8 @@
 
   PrintF("\n");
 }
-#endif  // DEBUG
 
 
-#ifdef OBJECT_PRINT
-void DescriptorArray::PrintDescriptors(FILE* out) {
-  PrintF(out, "Descriptor array  %d\n", number_of_descriptors());
-  for (int i = 0; i < number_of_descriptors(); i++) {
-    PrintF(out, " %d: ", i);
-    Descriptor desc;
-    Get(i, &desc);
-    desc.Print(out);
-  }
-  PrintF(out, "\n");
-}
-#endif  // OBJECT_PRINT
-
-
-#ifdef DEBUG
 bool DescriptorArray::IsSortedNoDuplicates() {
   String* current_key = NULL;
   uint32_t current = 0;
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
new file mode 100644
index 0000000..9879da2
--- /dev/null
+++ b/src/objects-printer.cc
@@ -0,0 +1,778 @@
+// Copyright 2010 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.
+
+#include "v8.h"
+
+#include "disassembler.h"
+#include "disasm.h"
+#include "jsregexp.h"
+#include "objects-visiting.h"
+
+namespace v8 {
+namespace internal {
+
+#ifdef OBJECT_PRINT
+
+static const char* TypeToString(InstanceType type);
+
+
+void MaybeObject::Print(FILE* out) {
+  Object* this_as_object;
+  if (ToObject(&this_as_object)) {
+    if (this_as_object->IsSmi()) {
+      Smi::cast(this_as_object)->SmiPrint(out);
+    } else {
+      HeapObject::cast(this_as_object)->HeapObjectPrint(out);
+    }
+  } else {
+    Failure::cast(this)->FailurePrint(out);
+  }
+  Flush(out);
+}
+
+
+void MaybeObject::PrintLn(FILE* out) {
+  Print(out);
+  PrintF(out, "\n");
+}
+
+
+void HeapObject::PrintHeader(FILE* out, const char* id) {
+  PrintF(out, "%p: [%s]\n", reinterpret_cast<void*>(this), id);
+}
+
+
+void HeapObject::HeapObjectPrint(FILE* out) {
+  InstanceType instance_type = map()->instance_type();
+
+  HandleScope scope;
+  if (instance_type < FIRST_NONSTRING_TYPE) {
+    String::cast(this)->StringPrint(out);
+    return;
+  }
+
+  switch (instance_type) {
+    case MAP_TYPE:
+      Map::cast(this)->MapPrint(out);
+      break;
+    case HEAP_NUMBER_TYPE:
+      HeapNumber::cast(this)->HeapNumberPrint(out);
+      break;
+    case FIXED_ARRAY_TYPE:
+      FixedArray::cast(this)->FixedArrayPrint(out);
+      break;
+    case BYTE_ARRAY_TYPE:
+      ByteArray::cast(this)->ByteArrayPrint(out);
+      break;
+    case PIXEL_ARRAY_TYPE:
+      PixelArray::cast(this)->PixelArrayPrint(out);
+      break;
+    case EXTERNAL_BYTE_ARRAY_TYPE:
+      ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
+      break;
+    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
+      ExternalUnsignedByteArray::cast(this)
+          ->ExternalUnsignedByteArrayPrint(out);
+      break;
+    case EXTERNAL_SHORT_ARRAY_TYPE:
+      ExternalShortArray::cast(this)->ExternalShortArrayPrint(out);
+      break;
+    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
+      ExternalUnsignedShortArray::cast(this)
+          ->ExternalUnsignedShortArrayPrint(out);
+      break;
+    case EXTERNAL_INT_ARRAY_TYPE:
+      ExternalIntArray::cast(this)->ExternalIntArrayPrint(out);
+      break;
+    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
+      ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint(out);
+      break;
+    case EXTERNAL_FLOAT_ARRAY_TYPE:
+      ExternalFloatArray::cast(this)->ExternalFloatArrayPrint(out);
+      break;
+    case FILLER_TYPE:
+      PrintF(out, "filler");
+      break;
+    case JS_OBJECT_TYPE:  // fall through
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
+    case JS_ARRAY_TYPE:
+    case JS_REGEXP_TYPE:
+      JSObject::cast(this)->JSObjectPrint(out);
+      break;
+    case ODDBALL_TYPE:
+      Oddball::cast(this)->to_string()->Print(out);
+      break;
+    case JS_FUNCTION_TYPE:
+      JSFunction::cast(this)->JSFunctionPrint(out);
+      break;
+    case JS_GLOBAL_PROXY_TYPE:
+      JSGlobalProxy::cast(this)->JSGlobalProxyPrint(out);
+      break;
+    case JS_GLOBAL_OBJECT_TYPE:
+      JSGlobalObject::cast(this)->JSGlobalObjectPrint(out);
+      break;
+    case JS_BUILTINS_OBJECT_TYPE:
+      JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(out);
+      break;
+    case JS_VALUE_TYPE:
+      PrintF(out, "Value wrapper around:");
+      JSValue::cast(this)->value()->Print(out);
+      break;
+    case CODE_TYPE:
+      Code::cast(this)->CodePrint(out);
+      break;
+    case PROXY_TYPE:
+      Proxy::cast(this)->ProxyPrint(out);
+      break;
+    case SHARED_FUNCTION_INFO_TYPE:
+      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
+      break;
+    case JS_GLOBAL_PROPERTY_CELL_TYPE:
+      JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
+      break;
+#define MAKE_STRUCT_CASE(NAME, Name, name) \
+  case NAME##_TYPE:                        \
+    Name::cast(this)->Name##Print(out);    \
+    break;
+  STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+
+    default:
+      PrintF(out, "UNKNOWN TYPE %d", map()->instance_type());
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void ByteArray::ByteArrayPrint(FILE* out) {
+  PrintF(out, "byte array, data starts at %p", GetDataStartAddress());
+}
+
+
+void PixelArray::PixelArrayPrint(FILE* out) {
+  PrintF(out, "pixel array");
+}
+
+
+void ExternalByteArray::ExternalByteArrayPrint(FILE* out) {
+  PrintF(out, "external byte array");
+}
+
+
+void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint(FILE* out) {
+  PrintF(out, "external unsigned byte array");
+}
+
+
+void ExternalShortArray::ExternalShortArrayPrint(FILE* out) {
+  PrintF(out, "external short array");
+}
+
+
+void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint(FILE* out) {
+  PrintF(out, "external unsigned short array");
+}
+
+
+void ExternalIntArray::ExternalIntArrayPrint(FILE* out) {
+  PrintF(out, "external int array");
+}
+
+
+void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint(FILE* out) {
+  PrintF(out, "external unsigned int array");
+}
+
+
+void ExternalFloatArray::ExternalFloatArrayPrint(FILE* out) {
+  PrintF(out, "external float array");
+}
+
+
+void JSObject::PrintProperties(FILE* out) {
+  if (HasFastProperties()) {
+    DescriptorArray* descs = map()->instance_descriptors();
+    for (int i = 0; i < descs->number_of_descriptors(); i++) {
+      PrintF(out, "   ");
+      descs->GetKey(i)->StringPrint(out);
+      PrintF(out, ": ");
+      switch (descs->GetType(i)) {
+        case FIELD: {
+          int index = descs->GetFieldIndex(i);
+          FastPropertyAt(index)->ShortPrint(out);
+          PrintF(out, " (field at offset %d)\n", index);
+          break;
+        }
+        case CONSTANT_FUNCTION:
+          descs->GetConstantFunction(i)->ShortPrint(out);
+          PrintF(out, " (constant function)\n");
+          break;
+        case CALLBACKS:
+          descs->GetCallbacksObject(i)->ShortPrint(out);
+          PrintF(out, " (callback)\n");
+          break;
+        case MAP_TRANSITION:
+          PrintF(out, " (map transition)\n");
+          break;
+        case CONSTANT_TRANSITION:
+          PrintF(out, " (constant transition)\n");
+          break;
+        case NULL_DESCRIPTOR:
+          PrintF(out, " (null descriptor)\n");
+          break;
+        default:
+          UNREACHABLE();
+          break;
+      }
+    }
+  } else {
+    property_dictionary()->Print(out);
+  }
+}
+
+
+void JSObject::PrintElements(FILE* out) {
+  switch (GetElementsKind()) {
+    case FAST_ELEMENTS: {
+      // Print in array notation for non-sparse arrays.
+      FixedArray* p = FixedArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: ", i);
+        p->get(i)->ShortPrint(out);
+        PrintF(out, "\n");
+      }
+      break;
+    }
+    case PIXEL_ELEMENTS: {
+      PixelArray* p = PixelArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %d\n", i, p->get(i));
+      }
+      break;
+    }
+    case EXTERNAL_BYTE_ELEMENTS: {
+      ExternalByteArray* p = ExternalByteArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+      }
+      break;
+    }
+    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
+      ExternalUnsignedByteArray* p =
+          ExternalUnsignedByteArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+      }
+      break;
+    }
+    case EXTERNAL_SHORT_ELEMENTS: {
+      ExternalShortArray* p = ExternalShortArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+      }
+      break;
+    }
+    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
+      ExternalUnsignedShortArray* p =
+          ExternalUnsignedShortArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+      }
+      break;
+    }
+    case EXTERNAL_INT_ELEMENTS: {
+      ExternalIntArray* p = ExternalIntArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+      }
+      break;
+    }
+    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
+      ExternalUnsignedIntArray* p =
+          ExternalUnsignedIntArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+      }
+      break;
+    }
+    case EXTERNAL_FLOAT_ELEMENTS: {
+      ExternalFloatArray* p = ExternalFloatArray::cast(elements());
+      for (int i = 0; i < p->length(); i++) {
+        PrintF(out, "   %d: %f\n", i, p->get(i));
+      }
+      break;
+    }
+    case DICTIONARY_ELEMENTS:
+      elements()->Print(out);
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void JSObject::JSObjectPrint(FILE* out) {
+  PrintF(out, "%p: [JSObject]\n", reinterpret_cast<void*>(this));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
+  PrintF(out, " {\n");
+  PrintProperties(out);
+  PrintElements(out);
+  PrintF(out, " }\n");
+}
+
+
+static const char* TypeToString(InstanceType type) {
+  switch (type) {
+    case INVALID_TYPE: return "INVALID";
+    case MAP_TYPE: return "MAP";
+    case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
+    case SYMBOL_TYPE: return "SYMBOL";
+    case ASCII_SYMBOL_TYPE: return "ASCII_SYMBOL";
+    case CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
+    case CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
+    case EXTERNAL_ASCII_SYMBOL_TYPE:
+    case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
+    case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
+    case ASCII_STRING_TYPE: return "ASCII_STRING";
+    case STRING_TYPE: return "TWO_BYTE_STRING";
+    case CONS_STRING_TYPE:
+    case CONS_ASCII_STRING_TYPE: return "CONS_STRING";
+    case EXTERNAL_ASCII_STRING_TYPE:
+    case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
+    case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
+    case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
+    case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
+    case PIXEL_ARRAY_TYPE: return "PIXEL_ARRAY";
+    case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
+    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
+      return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
+    case EXTERNAL_SHORT_ARRAY_TYPE: return "EXTERNAL_SHORT_ARRAY";
+    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
+      return "EXTERNAL_UNSIGNED_SHORT_ARRAY";
+    case EXTERNAL_INT_ARRAY_TYPE: return "EXTERNAL_INT_ARRAY";
+    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
+      return "EXTERNAL_UNSIGNED_INT_ARRAY";
+    case EXTERNAL_FLOAT_ARRAY_TYPE: return "EXTERNAL_FLOAT_ARRAY";
+    case FILLER_TYPE: return "FILLER";
+    case JS_OBJECT_TYPE: return "JS_OBJECT";
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
+    case ODDBALL_TYPE: return "ODDBALL";
+    case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
+    case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
+    case JS_FUNCTION_TYPE: return "JS_FUNCTION";
+    case CODE_TYPE: return "CODE";
+    case JS_ARRAY_TYPE: return "JS_ARRAY";
+    case JS_REGEXP_TYPE: return "JS_REGEXP";
+    case JS_VALUE_TYPE: return "JS_VALUE";
+    case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
+    case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
+    case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
+    case PROXY_TYPE: return "PROXY";
+#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
+  STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+  }
+  return "UNKNOWN";
+}
+
+
+void Map::MapPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Map");
+  PrintF(out, " - type: %s\n", TypeToString(instance_type()));
+  PrintF(out, " - instance size: %d\n", instance_size());
+  PrintF(out, " - inobject properties: %d\n", inobject_properties());
+  PrintF(out, " - pre-allocated property fields: %d\n",
+      pre_allocated_property_fields());
+  PrintF(out, " - unused property fields: %d\n", unused_property_fields());
+  if (is_hidden_prototype()) {
+    PrintF(out, " - hidden_prototype\n");
+  }
+  if (has_named_interceptor()) {
+    PrintF(out, " - named_interceptor\n");
+  }
+  if (has_indexed_interceptor()) {
+    PrintF(out, " - indexed_interceptor\n");
+  }
+  if (is_undetectable()) {
+    PrintF(out, " - undetectable\n");
+  }
+  if (has_instance_call_handler()) {
+    PrintF(out, " - instance_call_handler\n");
+  }
+  if (is_access_check_needed()) {
+    PrintF(out, " - access_check_needed\n");
+  }
+  PrintF(out, " - instance descriptors: ");
+  instance_descriptors()->ShortPrint(out);
+  PrintF(out, "\n - prototype: ");
+  prototype()->ShortPrint(out);
+  PrintF(out, "\n - constructor: ");
+  constructor()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
+void CodeCache::CodeCachePrint(FILE* out) {
+  HeapObject::PrintHeader(out, "CodeCache");
+  PrintF(out, "\n - default_cache: ");
+  default_cache()->ShortPrint(out);
+  PrintF(out, "\n - normal_type_cache: ");
+  normal_type_cache()->ShortPrint(out);
+}
+
+
+void FixedArray::FixedArrayPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "FixedArray");
+  PrintF(out, " - length: %d", length());
+  for (int i = 0; i < length(); i++) {
+    PrintF(out, "\n  [%d]: ", i);
+    get(i)->ShortPrint(out);
+  }
+  PrintF(out, "\n");
+}
+
+
+void JSValue::JSValuePrint(FILE* out) {
+  HeapObject::PrintHeader(out, "ValueObject");
+  value()->Print(out);
+}
+
+
+void String::StringPrint(FILE* out) {
+  if (StringShape(this).IsSymbol()) {
+    PrintF(out, "#");
+  } else if (StringShape(this).IsCons()) {
+    PrintF(out, "c\"");
+  } else {
+    PrintF(out, "\"");
+  }
+
+  const char truncated_epilogue[] = "...<truncated>";
+  int len = length();
+  if (!FLAG_use_verbose_printer) {
+    if (len > 100) {
+      len = 100 - sizeof(truncated_epilogue);
+    }
+  }
+  for (int i = 0; i < len; i++) {
+    PrintF(out, "%c", Get(i));
+  }
+  if (len != length()) {
+    PrintF(out, "%s", truncated_epilogue);
+  }
+
+  if (!StringShape(this).IsSymbol()) PrintF(out, "\"");
+}
+
+
+void JSFunction::JSFunctionPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Function");
+  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - initial_map = ");
+  if (has_initial_map()) {
+    initial_map()->ShortPrint(out);
+  }
+  PrintF(out, "\n - shared_info = ");
+  shared()->ShortPrint(out);
+  PrintF(out, "\n   - name = ");
+  shared()->name()->Print(out);
+  PrintF(out, "\n - context = ");
+  unchecked_context()->ShortPrint(out);
+  PrintF(out, "\n - code = ");
+  code()->ShortPrint(out);
+  PrintF(out, "\n");
+
+  PrintProperties(out);
+  PrintElements(out);
+
+  PrintF(out, "\n");
+}
+
+
+void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "SharedFunctionInfo");
+  PrintF(out, " - name: ");
+  name()->ShortPrint(out);
+  PrintF(out, "\n - expected_nof_properties: %d", expected_nof_properties());
+  PrintF(out, "\n - instance class name = ");
+  instance_class_name()->Print(out);
+  PrintF(out, "\n - code = ");
+  code()->ShortPrint(out);
+  PrintF(out, "\n - source code = ");
+  GetSourceCode()->ShortPrint(out);
+  // Script files are often large, hard to read.
+  // PrintF(out, "\n - script =");
+  // script()->Print(out);
+  PrintF(out, "\n - function token position = %d", function_token_position());
+  PrintF(out, "\n - start position = %d", start_position());
+  PrintF(out, "\n - end position = %d", end_position());
+  PrintF(out, "\n - is expression = %d", is_expression());
+  PrintF(out, "\n - debug info = ");
+  debug_info()->ShortPrint(out);
+  PrintF(out, "\n - length = %d", length());
+  PrintF(out, "\n - has_only_simple_this_property_assignments = %d",
+         has_only_simple_this_property_assignments());
+  PrintF(out, "\n - this_property_assignments = ");
+  this_property_assignments()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
+void JSGlobalProxy::JSGlobalProxyPrint(FILE* out) {
+  PrintF(out, "global_proxy");
+  JSObjectPrint(out);
+  PrintF(out, "context : ");
+  context()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
+void JSGlobalObject::JSGlobalObjectPrint(FILE* out) {
+  PrintF(out, "global ");
+  JSObjectPrint(out);
+  PrintF(out, "global context : ");
+  global_context()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
+void JSBuiltinsObject::JSBuiltinsObjectPrint(FILE* out) {
+  PrintF(out, "builtins ");
+  JSObjectPrint(out);
+}
+
+
+void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
+}
+
+
+void Code::CodePrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Code");
+#ifdef ENABLE_DISASSEMBLER
+  if (FLAG_use_verbose_printer) {
+    Disassemble(NULL, out);
+  }
+#endif
+}
+
+
+void Proxy::ProxyPrint(FILE* out) {
+  PrintF(out, "proxy to %p", proxy());
+}
+
+
+void AccessorInfo::AccessorInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "AccessorInfo");
+  PrintF(out, "\n - getter: ");
+  getter()->ShortPrint(out);
+  PrintF(out, "\n - setter: ");
+  setter()->ShortPrint(out);
+  PrintF(out, "\n - name: ");
+  name()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+  PrintF(out, "\n - flag: ");
+  flag()->ShortPrint(out);
+}
+
+
+void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "AccessCheckInfo");
+  PrintF(out, "\n - named_callback: ");
+  named_callback()->ShortPrint(out);
+  PrintF(out, "\n - indexed_callback: ");
+  indexed_callback()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+}
+
+
+void InterceptorInfo::InterceptorInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "InterceptorInfo");
+  PrintF(out, "\n - getter: ");
+  getter()->ShortPrint(out);
+  PrintF(out, "\n - setter: ");
+  setter()->ShortPrint(out);
+  PrintF(out, "\n - query: ");
+  query()->ShortPrint(out);
+  PrintF(out, "\n - deleter: ");
+  deleter()->ShortPrint(out);
+  PrintF(out, "\n - enumerator: ");
+  enumerator()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+}
+
+
+void CallHandlerInfo::CallHandlerInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "CallHandlerInfo");
+  PrintF(out, "\n - callback: ");
+  callback()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+  PrintF(out, "\n - call_stub_cache: ");
+}
+
+
+void FunctionTemplateInfo::FunctionTemplateInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "FunctionTemplateInfo");
+  PrintF(out, "\n - class name: ");
+  class_name()->ShortPrint(out);
+  PrintF(out, "\n - tag: ");
+  tag()->ShortPrint(out);
+  PrintF(out, "\n - property_list: ");
+  property_list()->ShortPrint(out);
+  PrintF(out, "\n - serial_number: ");
+  serial_number()->ShortPrint(out);
+  PrintF(out, "\n - call_code: ");
+  call_code()->ShortPrint(out);
+  PrintF(out, "\n - property_accessors: ");
+  property_accessors()->ShortPrint(out);
+  PrintF(out, "\n - prototype_template: ");
+  prototype_template()->ShortPrint(out);
+  PrintF(out, "\n - parent_template: ");
+  parent_template()->ShortPrint(out);
+  PrintF(out, "\n - named_property_handler: ");
+  named_property_handler()->ShortPrint(out);
+  PrintF(out, "\n - indexed_property_handler: ");
+  indexed_property_handler()->ShortPrint(out);
+  PrintF(out, "\n - instance_template: ");
+  instance_template()->ShortPrint(out);
+  PrintF(out, "\n - signature: ");
+  signature()->ShortPrint(out);
+  PrintF(out, "\n - access_check_info: ");
+  access_check_info()->ShortPrint(out);
+  PrintF(out, "\n - hidden_prototype: %s",
+         hidden_prototype() ? "true" : "false");
+  PrintF(out, "\n - undetectable: %s", undetectable() ? "true" : "false");
+  PrintF(out, "\n - need_access_check: %s",
+         needs_access_check() ? "true" : "false");
+}
+
+
+void ObjectTemplateInfo::ObjectTemplateInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "ObjectTemplateInfo");
+  PrintF(out, "\n - constructor: ");
+  constructor()->ShortPrint(out);
+  PrintF(out, "\n - internal_field_count: ");
+  internal_field_count()->ShortPrint(out);
+}
+
+
+void SignatureInfo::SignatureInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "SignatureInfo");
+  PrintF(out, "\n - receiver: ");
+  receiver()->ShortPrint(out);
+  PrintF(out, "\n - args: ");
+  args()->ShortPrint(out);
+}
+
+
+void TypeSwitchInfo::TypeSwitchInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "TypeSwitchInfo");
+  PrintF(out, "\n - types: ");
+  types()->ShortPrint(out);
+}
+
+
+void Script::ScriptPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Script");
+  PrintF(out, "\n - source: ");
+  source()->ShortPrint(out);
+  PrintF(out, "\n - name: ");
+  name()->ShortPrint(out);
+  PrintF(out, "\n - line_offset: ");
+  line_offset()->ShortPrint(out);
+  PrintF(out, "\n - column_offset: ");
+  column_offset()->ShortPrint(out);
+  PrintF(out, "\n - type: ");
+  type()->ShortPrint(out);
+  PrintF(out, "\n - id: ");
+  id()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+  PrintF(out, "\n - context data: ");
+  context_data()->ShortPrint(out);
+  PrintF(out, "\n - wrapper: ");
+  wrapper()->ShortPrint(out);
+  PrintF(out, "\n - compilation type: ");
+  compilation_type()->ShortPrint(out);
+  PrintF(out, "\n - line ends: ");
+  line_ends()->ShortPrint(out);
+  PrintF(out, "\n - eval from shared: ");
+  eval_from_shared()->ShortPrint(out);
+  PrintF(out, "\n - eval from instructions offset: ");
+  eval_from_instructions_offset()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+void DebugInfo::DebugInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "DebugInfo");
+  PrintF(out, "\n - shared: ");
+  shared()->ShortPrint(out);
+  PrintF(out, "\n - original_code: ");
+  original_code()->ShortPrint(out);
+  PrintF(out, "\n - code: ");
+  code()->ShortPrint(out);
+  PrintF(out, "\n - break_points: ");
+  break_points()->Print(out);
+}
+
+
+void BreakPointInfo::BreakPointInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "BreakPointInfo");
+  PrintF(out, "\n - code_position: %d", code_position()->value());
+  PrintF(out, "\n - source_position: %d", source_position()->value());
+  PrintF(out, "\n - statement_position: %d", statement_position()->value());
+  PrintF(out, "\n - break_point_objects: ");
+  break_point_objects()->ShortPrint(out);
+}
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
+
+void DescriptorArray::PrintDescriptors(FILE* out) {
+  PrintF(out, "Descriptor array  %d\n", number_of_descriptors());
+  for (int i = 0; i < number_of_descriptors(); i++) {
+    PrintF(out, " %d: ", i);
+    Descriptor desc;
+    Get(i, &desc);
+    desc.Print(out);
+  }
+  PrintF(out, "\n");
+}
+
+
+#endif  // OBJECT_PRINT
+
+
+} }  // namespace v8::internal
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index 55a0a53..6510ca8 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -186,9 +186,9 @@
 template<typename StaticVisitor>
 class BodyVisitorBase : public AllStatic {
  public:
-  static inline void IteratePointers(HeapObject* object,
+  INLINE(static void IteratePointers(HeapObject* object,
                                      int start_offset,
-                                     int end_offset) {
+                                     int end_offset)) {
     Object** start_slot = reinterpret_cast<Object**>(object->address() +
                                                      start_offset);
     Object** end_slot = reinterpret_cast<Object**>(object->address() +
diff --git a/src/objects.cc b/src/objects.cc
index ab2f964..8c8b6e0 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5143,6 +5143,26 @@
 }
 
 
+bool String::IsAsciiEqualTo(Vector<const char> str) {
+  int slen = length();
+  if (str.length() != slen) return false;
+  for (int i = 0; i < slen; i++) {
+    if (Get(i) != static_cast<uint16_t>(str[i])) return false;
+  }
+  return true;
+}
+
+
+bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
+  int slen = length();
+  if (str.length() != slen) return false;
+  for (int i = 0; i < slen; i++) {
+    if (Get(i) != str[i]) return false;
+  }
+  return true;
+}
+
+
 template <typename schar>
 static inline uint32_t HashSequentialString(const schar* chars, int length) {
   StringHasher hasher(length);
@@ -8086,6 +8106,85 @@
 };
 
 
+template <typename Char>
+class SequentialSymbolKey : public HashTableKey {
+ public:
+  explicit SequentialSymbolKey(Vector<const Char> string)
+      : string_(string), hash_field_(0) { }
+
+  uint32_t Hash() {
+    StringHasher hasher(string_.length());
+
+    // Very long strings have a trivial hash that doesn't inspect the
+    // string contents.
+    if (hasher.has_trivial_hash()) {
+      hash_field_ = hasher.GetHashField();
+    } else {
+      int i = 0;
+      // Do the iterative array index computation as long as there is a
+      // chance this is an array index.
+      while (i < string_.length() && hasher.is_array_index()) {
+        hasher.AddCharacter(static_cast<uc32>(string_[i]));
+        i++;
+      }
+
+      // Process the remaining characters without updating the array
+      // index.
+      while (i < string_.length()) {
+        hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
+        i++;
+      }
+      hash_field_ = hasher.GetHashField();
+    }
+
+    uint32_t result = hash_field_ >> String::kHashShift;
+    ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
+    return result;
+  }
+
+
+  uint32_t HashForObject(Object* other) {
+    return String::cast(other)->Hash();
+  }
+
+  Vector<const Char> string_;
+  uint32_t hash_field_;
+};
+
+
+
+class AsciiSymbolKey : public SequentialSymbolKey<char> {
+ public:
+  explicit AsciiSymbolKey(Vector<const char> str)
+      : SequentialSymbolKey<char>(str) { }
+
+  bool IsMatch(Object* string) {
+    return String::cast(string)->IsAsciiEqualTo(string_);
+  }
+
+  MaybeObject* AsObject() {
+    if (hash_field_ == 0) Hash();
+    return Heap::AllocateAsciiSymbol(string_, hash_field_);
+  }
+};
+
+
+class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
+ public:
+  explicit TwoByteSymbolKey(Vector<const uc16> str)
+      : SequentialSymbolKey<uc16>(str) { }
+
+  bool IsMatch(Object* string) {
+    return String::cast(string)->IsTwoByteEqualTo(string_);
+  }
+
+  MaybeObject* AsObject() {
+    if (hash_field_ == 0) Hash();
+    return Heap::AllocateTwoByteSymbol(string_, hash_field_);
+  }
+};
+
+
 // SymbolKey carries a string/symbol object as key.
 class SymbolKey : public HashTableKey {
  public:
@@ -8830,6 +8929,19 @@
 }
 
 
+MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
+                                            Object** s) {
+  AsciiSymbolKey key(str);
+  return LookupKey(&key, s);
+}
+
+
+MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
+                                              Object** s) {
+  TwoByteSymbolKey key(str);
+  return LookupKey(&key, s);
+}
+
 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
   int entry = FindEntry(key);
 
diff --git a/src/objects.h b/src/objects.h
index c5fda7d..163b713 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2327,6 +2327,10 @@
   // been enlarged.  If the return value is not a failure, the symbol
   // pointer *s is set to the symbol found.
   MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
+  MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
+                                                 Object** s);
+  MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
+                                                   Object** s);
   MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
 
   // Looks up a symbol that is equal to the given string and returns
@@ -5074,6 +5078,8 @@
   // String equality operations.
   inline bool Equals(String* other);
   bool IsEqualTo(Vector<const char> str);
+  bool IsAsciiEqualTo(Vector<const char> str);
+  bool IsTwoByteEqualTo(Vector<const uc16> str);
 
   // Return a UTF8 representation of the string.  The string is null
   // terminated but may optionally contain nulls.  Length is returned
@@ -5245,6 +5251,34 @@
                           int from,
                           int to);
 
+  static inline bool IsAscii(const char* chars, int length) {
+    const char* limit = chars + length;
+#ifdef V8_HOST_CAN_READ_UNALIGNED
+    ASSERT(kMaxAsciiCharCode == 0x7F);
+    const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
+    while (chars <= limit - sizeof(uintptr_t)) {
+      if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
+        return false;
+      }
+      chars += sizeof(uintptr_t);
+    }
+#endif
+    while (chars < limit) {
+      if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) return false;
+      ++chars;
+    }
+    return true;
+  }
+
+  static inline bool IsAscii(const uc16* chars, int length) {
+    const uc16* limit = chars + length;
+    while (chars < limit) {
+      if (*chars > kMaxAsciiCharCodeU) return false;
+      ++chars;
+    }
+    return true;
+  }
+
  protected:
   class ReadBlockBuffer {
    public:
diff --git a/src/parser.cc b/src/parser.cc
index 08f77b8..03819ee 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -323,22 +323,24 @@
 }
 
 
-Handle<String> Parser::LookupSymbol(int symbol_id,
-                                    Vector<const char> string) {
+Handle<String> Parser::LookupSymbol(int symbol_id) {
   // Length of symbol cache is the number of identified symbols.
   // If we are larger than that, or negative, it's not a cached symbol.
   // This might also happen if there is no preparser symbol data, even
   // if there is some preparser data.
   if (static_cast<unsigned>(symbol_id)
       >= static_cast<unsigned>(symbol_cache_.length())) {
-    return Factory::LookupSymbol(string);
+    if (scanner().is_literal_ascii()) {
+      return Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
+    } else {
+      return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
+    }
   }
-  return LookupCachedSymbol(symbol_id, string);
+  return LookupCachedSymbol(symbol_id);
 }
 
 
-Handle<String> Parser::LookupCachedSymbol(int symbol_id,
-                                          Vector<const char> string) {
+Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
   // Make sure the cache is large enough to hold the symbol identifier.
   if (symbol_cache_.length() <= symbol_id) {
     // Increase length to index + 1.
@@ -347,7 +349,11 @@
   }
   Handle<String> result = symbol_cache_.at(symbol_id);
   if (result.is_null()) {
-    result = Factory::LookupSymbol(string);
+    if (scanner().is_literal_ascii()) {
+      result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
+    } else {
+      result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
+    }
     symbol_cache_.at(symbol_id) = result;
     return result;
   }
@@ -615,11 +621,11 @@
     // identical calls.
     ExternalTwoByteStringUC16CharacterStream stream(
         Handle<ExternalTwoByteString>::cast(source), 0, source->length());
-    scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
+    scanner_.Initialize(&stream);
     return DoParseProgram(source, in_global_context, &zone_scope);
   } else {
     GenericStringUC16CharacterStream stream(source, 0, source->length());
-    scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
+    scanner_.Initialize(&stream);
     return DoParseProgram(source, in_global_context, &zone_scope);
   }
 }
@@ -705,7 +711,7 @@
 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
                                    UC16CharacterStream* source,
                                    ZoneScope* zone_scope) {
-  scanner_.Initialize(source, JavaScriptScanner::kAllLiterals);
+  scanner_.Initialize(source);
   ASSERT(target_stack_ == NULL);
 
   Handle<String> name(String::cast(info->name()));
@@ -757,7 +763,7 @@
   if (pre_data() != NULL) {
     symbol_id = pre_data()->GetSymbolIdentifier();
   }
-  return LookupSymbol(symbol_id, scanner().literal());
+  return LookupSymbol(symbol_id);
 }
 
 
@@ -2715,8 +2721,9 @@
 
     case Token::NUMBER: {
       Consume(Token::NUMBER);
-      double value =
-        StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
+      ASSERT(scanner().is_literal_ascii());
+      double value = StringToDouble(scanner().literal_ascii_string(),
+                                    ALLOW_HEX | ALLOW_OCTALS);
       result = NewNumberLiteral(value);
       break;
     }
@@ -3066,8 +3073,9 @@
       }
       case Token::NUMBER: {
         Consume(Token::NUMBER);
-        double value =
-          StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
+        ASSERT(scanner().is_literal_ascii());
+        double value = StringToDouble(scanner().literal_ascii_string(),
+                                      ALLOW_HEX | ALLOW_OCTALS);
         key = NewNumberLiteral(value);
         break;
       }
@@ -3137,11 +3145,9 @@
 
   int literal_index = temp_scope_->NextMaterializedLiteralIndex();
 
-  Handle<String> js_pattern =
-      Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
+  Handle<String> js_pattern = NextLiteralString(TENURED);
   scanner().ScanRegExpFlags();
-  Handle<String> js_flags =
-      Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
+  Handle<String> js_flags = NextLiteralString(TENURED);
   Next();
 
   return new RegExpLiteral(js_pattern, js_flags, literal_index);
@@ -3423,10 +3429,10 @@
                                                  bool* ok) {
   Expect(Token::IDENTIFIER, ok);
   if (!*ok) return Handle<String>();
-  if (scanner().literal_length() == 3) {
-    const char* token = scanner().literal_string();
-    *is_get = strcmp(token, "get") == 0;
-    *is_set = !*is_get && strcmp(token, "set") == 0;
+  if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
+    const char* token = scanner().literal_ascii_string().start();
+    *is_get = strncmp(token, "get", 3) == 0;
+    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
   }
   return GetSymbol(ok);
 }
@@ -3604,9 +3610,11 @@
   if (literal_length == 0) {
     return Factory::empty_string();
   }
-  const char* literal_string = scanner_.literal_string();
-  Vector<const char> literal(literal_string, literal_length);
-  return Factory::NewStringFromUtf8(literal);
+  if (scanner_.is_literal_ascii()) {
+    return Factory::NewStringFromAscii(scanner_.literal_ascii_string());
+  } else {
+    return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string());
+  }
 }
 
 
@@ -3618,7 +3626,8 @@
       return GetString();
     }
     case Token::NUMBER: {
-      double value = StringToDouble(scanner_.literal(),
+      ASSERT(scanner_.is_literal_ascii());
+      double value = StringToDouble(scanner_.literal_ascii_string(),
                                     NO_FLAGS,  // Hex, octal or trailing junk.
                                     OS::nan_value());
       return Factory::NewNumber(value);
@@ -4597,10 +4606,9 @@
 // Create a Scanner for the preparser to use as input, and preparse the source.
 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
                                   bool allow_lazy,
-                                  ParserRecorder* recorder,
-                                  int literal_flags) {
+                                  ParserRecorder* recorder) {
   V8JavaScriptScanner scanner;
-  scanner.Initialize(source, literal_flags);
+  scanner.Initialize(source);
   intptr_t stack_limit = StackGuard::real_climit();
   if (!preparser::PreParser::PreParseProgram(&scanner,
                                              recorder,
@@ -4628,8 +4636,7 @@
     return NULL;
   }
   PartialParserRecorder recorder;
-  return DoPreParse(source, allow_lazy, &recorder,
-                    JavaScriptScanner::kNoLiterals);
+  return DoPreParse(source, allow_lazy, &recorder);
 }
 
 
@@ -4638,9 +4645,7 @@
   Handle<Script> no_script;
   bool allow_lazy = FLAG_lazy && (extension == NULL);
   CompleteParserRecorder recorder;
-  int kPreParseLiteralsFlags =
-      JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier;
-  return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags);
+  return DoPreParse(source, allow_lazy, &recorder);
 }
 
 
diff --git a/src/parser.h b/src/parser.h
index 70d0e18..8623f38 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -578,6 +578,26 @@
   bool Check(Token::Value token);
   void ExpectSemicolon(bool* ok);
 
+  Handle<String> LiteralString(PretenureFlag tenured) {
+    if (scanner().is_literal_ascii()) {
+      return Factory::NewStringFromAscii(scanner().literal_ascii_string(),
+                                         tenured);
+    } else {
+      return Factory::NewStringFromTwoByte(scanner().literal_uc16_string(),
+                                           tenured);
+    }
+  }
+
+  Handle<String> NextLiteralString(PretenureFlag tenured) {
+    if (scanner().is_next_literal_ascii()) {
+      return Factory::NewStringFromAscii(scanner().next_literal_ascii_string(),
+                                         tenured);
+    } else {
+      return Factory::NewStringFromTwoByte(scanner().next_literal_uc16_string(),
+                                           tenured);
+    }
+  }
+
   Handle<String> GetSymbol(bool* ok);
 
   // Get odd-ball literals.
@@ -612,11 +632,9 @@
 
   Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
 
-  Handle<String> LookupSymbol(int symbol_id,
-                              Vector<const char> string);
+  Handle<String> LookupSymbol(int symbol_id);
 
-  Handle<String> LookupCachedSymbol(int symbol_id,
-                                    Vector<const char> string);
+  Handle<String> LookupCachedSymbol(int symbol_id);
 
   Expression* NewCall(Expression* expression,
                       ZoneList<Expression*>* arguments,
diff --git a/src/preparse-data.cc b/src/preparse-data.cc
index 9a36771..7c9d8a6 100644
--- a/src/preparse-data.cc
+++ b/src/preparse-data.cc
@@ -110,26 +110,29 @@
 
 CompleteParserRecorder::CompleteParserRecorder()
     : FunctionLoggingParserRecorder(),
+      literal_chars_(0),
       symbol_store_(0),
-      symbol_entries_(0),
+      symbol_keys_(0),
       symbol_table_(vector_compare),
       symbol_id_(0) {
 }
 
 
-void CompleteParserRecorder::LogSymbol(
-    int start, const char* literal_chars, int length) {
-  if (!is_recording_) return;
-
-  Vector<const char> literal(literal_chars, length);
-  int hash = vector_hash(literal);
-  HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
+void CompleteParserRecorder::LogSymbol(int start,
+                                       int hash,
+                                       bool is_ascii,
+                                       Vector<const byte> literal_bytes) {
+  Key key = { is_ascii, literal_bytes };
+  HashMap::Entry* entry = symbol_table_.Lookup(&key, hash, true);
   int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
   if (id == 0) {
+    // Copy literal contents for later comparison.
+    key.literal_bytes =
+        Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
     // Put (symbol_id_ + 1) into entry and increment it.
     id = ++symbol_id_;
     entry->value = reinterpret_cast<void*>(id);
-    Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
+    Vector<Key> symbol = symbol_keys_.AddBlock(1, key);
     entry->key = &symbol[0];
   }
   WriteNumber(id - 1);
diff --git a/src/preparse-data.h b/src/preparse-data.h
index a96e50f..cc82bcc 100644
--- a/src/preparse-data.h
+++ b/src/preparse-data.h
@@ -75,7 +75,8 @@
                            int properties) = 0;
 
   // Logs a symbol creation of a literal or identifier.
-  virtual void LogSymbol(int start, const char* symbol, int length) = 0;
+  virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
+  virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
 
   // Logs an error message and marks the log as containing an error.
   // Further logging will be ignored, and ExtractData will return a vector
@@ -165,7 +166,8 @@
 class PartialParserRecorder : public FunctionLoggingParserRecorder {
  public:
   PartialParserRecorder() : FunctionLoggingParserRecorder() { }
-  virtual void LogSymbol(int start, const char* symbol, int length) { }
+  virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
+  virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
   virtual ~PartialParserRecorder() { }
   virtual Vector<unsigned> ExtractData();
   virtual int symbol_position() { return 0; }
@@ -181,7 +183,17 @@
   CompleteParserRecorder();
   virtual ~CompleteParserRecorder() { }
 
-  virtual void LogSymbol(int start, const char* symbol, int length);
+  virtual void LogAsciiSymbol(int start, Vector<const char> literal) {
+    if (!is_recording_) return;
+    int hash = vector_hash(literal);
+    LogSymbol(start, hash, true, Vector<const byte>::cast(literal));
+  }
+
+  virtual void LogUC16Symbol(int start, Vector<const uc16> literal) {
+    if (!is_recording_) return;
+    int hash = vector_hash(literal);
+    LogSymbol(start, hash, false, Vector<const byte>::cast(literal));
+  }
 
   virtual Vector<unsigned> ExtractData();
 
@@ -189,10 +201,21 @@
   virtual int symbol_ids() { return symbol_id_; }
 
  private:
-  static int vector_hash(Vector<const char> string) {
+  struct Key {
+    bool is_ascii;
+    Vector<const byte> literal_bytes;
+  };
+
+  virtual void LogSymbol(int start,
+                         int hash,
+                         bool is_ascii,
+                         Vector<const byte> literal);
+
+  template <typename Char>
+  static int vector_hash(Vector<const Char> string) {
     int hash = 0;
     for (int i = 0; i < string.length(); i++) {
-      int c = string[i];
+      int c = static_cast<int>(string[i]);
       hash += c;
       hash += (hash << 10);
       hash ^= (hash >> 6);
@@ -201,18 +224,21 @@
   }
 
   static bool vector_compare(void* a, void* b) {
-    Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
-    Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b);
-    int length = string1->length();
-    if (string2->length() != length) return false;
-    return memcmp(string1->start(), string2->start(), length) == 0;
+    Key* string1 = reinterpret_cast<Key*>(a);
+    Key* string2 = reinterpret_cast<Key*>(b);
+    if (string1->is_ascii != string2->is_ascii) return false;
+    int length = string1->literal_bytes.length();
+    if (string2->literal_bytes.length() != length) return false;
+    return memcmp(string1->literal_bytes.start(),
+                  string2->literal_bytes.start(), length) == 0;
   }
 
   // Write a non-negative number to the symbol store.
   void WriteNumber(int number);
 
+  Collector<byte> literal_chars_;
   Collector<byte> symbol_store_;
-  Collector<Vector<const char> > symbol_entries_;
+  Collector<Key> symbol_keys_;
   HashMap symbol_table_;
   int symbol_id_;
 };
diff --git a/src/preparser.cc b/src/preparser.cc
index 7cce685..157fbea 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -1121,23 +1121,23 @@
 
 
 PreParser::Identifier PreParser::GetIdentifierSymbol() {
-  const char* literal_chars = scanner_->literal_string();
-  int literal_length = scanner_->literal_length();
   int identifier_pos = scanner_->location().beg_pos;
-
-  log_->LogSymbol(identifier_pos, literal_chars, literal_length);
-
-  return kUnknownExpression;
+  if (scanner_->is_literal_ascii()) {
+    log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
+  } else {
+    log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
+  }
+  return kUnknownIdentifier;
 }
 
 
 PreParser::Expression PreParser::GetStringSymbol() {
-  const char* literal_chars = scanner_->literal_string();
-  int literal_length = scanner_->literal_length();
-
-  int literal_position = scanner_->location().beg_pos;
-  log_->LogSymbol(literal_position, literal_chars, literal_length);
-
+  int identifier_pos = scanner_->location().beg_pos;
+  if (scanner_->is_literal_ascii()) {
+    log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
+  } else {
+    log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
+  }
   return kUnknownExpression;
 }
 
@@ -1154,7 +1154,8 @@
   if (i::Token::IsKeyword(next)) {
     int pos = scanner_->location().beg_pos;
     const char* keyword = i::Token::String(next);
-    log_->LogSymbol(pos, keyword, i::StrLength(keyword));
+    log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
+                                                    i::StrLength(keyword)));
     return kUnknownExpression;
   }
   if (next == i::Token::IDENTIFIER) {
@@ -1173,8 +1174,8 @@
                                                            bool* is_set,
                                                            bool* ok) {
   Expect(i::Token::IDENTIFIER, CHECK_OK);
-  if (scanner_->literal_length() == 3) {
-    const char* token = scanner_->literal_string();
+  if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) {
+    const char* token = scanner_->literal_ascii_string().start();
     *is_get = strncmp(token, "get", 3) == 0;
     *is_set = !*is_get && strncmp(token, "set", 3) == 0;
   }
diff --git a/src/scanner-base.cc b/src/scanner-base.cc
index b26fee0..1babaeb 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -35,28 +35,6 @@
 namespace internal {
 
 // ----------------------------------------------------------------------------
-// LiteralCollector
-
-LiteralCollector::LiteralCollector()
-    : buffer_(kInitialCapacity), recording_(false) { }
-
-
-LiteralCollector::~LiteralCollector() {}
-
-
-void LiteralCollector::AddCharSlow(uc32 c) {
-  ASSERT(static_cast<unsigned>(c) > unibrow::Utf8::kMaxOneByteChar);
-  int length = unibrow::Utf8::Length(c);
-  Vector<char> block = buffer_.AddBlock(length, '\0');
-#ifdef DEBUG
-  int written_length = unibrow::Utf8::Encode(block.start(), c);
-  CHECK_EQ(length, written_length);
-#else
-  unibrow::Utf8::Encode(block.start(), c);
-#endif
-}
-
-// ----------------------------------------------------------------------------
 // Character predicates
 
 unibrow::Predicate<IdentifierStart, 128> ScannerConstants::kIsIdentifierStart;
@@ -256,7 +234,7 @@
 
 
 void JavaScriptScanner::Scan() {
-  next_.literal_chars = Vector<const char>();
+  next_.literal_chars = NULL;
   Token::Value token;
   do {
     // Remember the position of the next token
@@ -561,7 +539,7 @@
   uc32 quote = c0_;
   Advance();  // consume quote
 
-  LiteralScope literal(this, kLiteralString);
+  LiteralScope literal(this);
   while (c0_ != quote && c0_ >= 0
          && !ScannerConstants::kIsLineTerminator.get(c0_)) {
     uc32 c = c0_;
@@ -592,7 +570,7 @@
 
   enum { DECIMAL, HEX, OCTAL } kind = DECIMAL;
 
-  LiteralScope literal(this, kLiteralNumber);
+  LiteralScope literal(this);
   if (seen_period) {
     // we have already seen a decimal point of the float
     AddLiteralChar('.');
@@ -681,7 +659,7 @@
 
 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
   ASSERT(ScannerConstants::kIsIdentifierStart.get(c0_));
-  LiteralScope literal(this, kLiteralIdentifier);
+  LiteralScope literal(this);
   KeywordMatcher keyword_match;
   // Scan identifier start character.
   if (c0_ == '\\') {
@@ -747,7 +725,7 @@
   // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
   // the scanner should pass uninterpreted bodies to the RegExp
   // constructor.
-  LiteralScope literal(this, kLiteralRegExp);
+  LiteralScope literal(this);
   if (seen_equal)
     AddLiteralChar('=');
 
@@ -773,7 +751,7 @@
 
 bool JavaScriptScanner::ScanRegExpFlags() {
   // Scan regular expression flags.
-  LiteralScope literal(this, kLiteralRegExpFlags);
+  LiteralScope literal(this);
   while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
     if (c0_ == '\\') {
       uc32 c = ScanIdentifierUnicodeEscape();
diff --git a/src/scanner-base.h b/src/scanner-base.h
index c50b8f3..e773586 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -141,61 +141,103 @@
 };
 
 // ----------------------------------------------------------------------------
-// LiteralCollector -  Collector of chars of literals.
+// LiteralBuffer -  Collector of chars of literals.
 
-class LiteralCollector {
+class LiteralBuffer {
  public:
-  LiteralCollector();
-  ~LiteralCollector();
+  LiteralBuffer() : is_ascii_(true), position_(0), backing_store_() { }
 
-  inline void AddChar(uc32 c) {
-    if (recording_) {
-      if (static_cast<unsigned>(c) <= unibrow::Utf8::kMaxOneByteChar) {
-        buffer_.Add(static_cast<char>(c));
-      } else {
-        AddCharSlow(c);
+  ~LiteralBuffer() {
+    if (backing_store_.length() > 0) {
+      backing_store_.Dispose();
+    }
+  }
+
+  inline void AddChar(uc16 character) {
+    if (position_ >= backing_store_.length()) ExpandBuffer();
+    if (is_ascii_) {
+      if (character < kMaxAsciiCharCodeU) {
+        backing_store_[position_] = static_cast<byte>(character);
+        position_ += kASCIISize;
+        return;
       }
+      ConvertToUC16();
     }
+    *reinterpret_cast<uc16*>(&backing_store_[position_]) = character;
+    position_ += kUC16Size;
   }
 
-  void StartLiteral() {
-    buffer_.StartSequence();
-    recording_ = true;
+  bool is_ascii() { return is_ascii_; }
+
+  Vector<const uc16> uc16_literal() {
+    ASSERT(!is_ascii_);
+    ASSERT((position_ & 0x1) == 0);
+    return Vector<const uc16>(
+        reinterpret_cast<const uc16*>(backing_store_.start()),
+        position_ >> 1);
   }
 
-  Vector<const char> EndLiteral() {
-    if (recording_) {
-      recording_ = false;
-      buffer_.Add(kEndMarker);
-      Vector<char> sequence = buffer_.EndSequence();
-      return Vector<const char>(sequence.start(), sequence.length());
-    }
-    return Vector<const char>();
+  Vector<const char> ascii_literal() {
+    ASSERT(is_ascii_);
+    return Vector<const char>(
+        reinterpret_cast<const char*>(backing_store_.start()),
+        position_);
   }
 
-  void DropLiteral() {
-    if (recording_) {
-      recording_ = false;
-      buffer_.DropSequence();
-    }
+  int length() {
+    return is_ascii_ ? position_ : (position_ >> 1);
   }
 
   void Reset() {
-    buffer_.Reset();
+    position_ = 0;
+    is_ascii_ = true;
+  }
+ private:
+  static const int kInitialCapacity = 16;
+  static const int kGrowthFactory = 4;
+  static const int kMinConversionSlack = 256;
+  static const int kMaxGrowth = 1 * MB;
+  inline int NewCapacity(int min_capacity) {
+    int capacity = Max(min_capacity, backing_store_.length());
+    int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
+    return new_capacity;
   }
 
-  // The end marker added after a parsed literal.
-  // Using zero allows the usage of strlen and similar functions on
-  // identifiers and numbers (but not strings, since they may contain zero
-  // bytes).
-  static const char kEndMarker = '\x00';
- private:
-  static const int kInitialCapacity = 256;
-  SequenceCollector<char, 4> buffer_;
-  bool recording_;
-  void AddCharSlow(uc32 c);
+  void ExpandBuffer() {
+    Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
+    memcpy(new_store.start(), backing_store_.start(), position_);
+    backing_store_.Dispose();
+    backing_store_ = new_store;
+  }
+
+  void ConvertToUC16() {
+    ASSERT(is_ascii_);
+    Vector<byte> new_store;
+    int new_content_size = position_ * kUC16Size;
+    if (new_content_size > backing_store_.length()) {
+      new_store = Vector<byte>::New(NewCapacity(new_content_size));
+    } else {
+      new_store = backing_store_;
+    }
+    char* src = reinterpret_cast<char*>(backing_store_.start());
+    uc16* dst = reinterpret_cast<uc16*>(new_store.start());
+    for (int i = position_ - 1; i >= 0; i--) {
+      dst[i] = src[i];
+    }
+    if (new_store.start() != backing_store_.start()) {
+      backing_store_.Dispose();
+      backing_store_ = new_store;
+    }
+    position_ = new_content_size;
+    is_ascii_ = false;
+  }
+
+  bool is_ascii_;
+  int position_;
+  Vector<byte> backing_store_;
 };
 
+
 // ----------------------------------------------------------------------------
 // Scanner base-class.
 
@@ -241,35 +283,40 @@
   // collected for identifiers, strings, and numbers.
   // These functions only give the correct result if the literal
   // was scanned between calls to StartLiteral() and TerminateLiteral().
-  const char* literal_string() const {
-    return current_.literal_chars.start();
+  bool is_literal_ascii() {
+    ASSERT_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->is_ascii();
   }
-
+  Vector<const char> literal_ascii_string() {
+    ASSERT_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->ascii_literal();
+  }
+  Vector<const uc16> literal_uc16_string() {
+    ASSERT_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->uc16_literal();
+  }
   int literal_length() const {
-    // Excluding terminal '\x00' added by TerminateLiteral().
-    return current_.literal_chars.length() - 1;
-  }
-
-  Vector<const char> literal() const {
-    return Vector<const char>(literal_string(), literal_length());
+    ASSERT_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->length();
   }
 
   // Returns the literal string for the next token (the token that
   // would be returned if Next() were called).
-  const char* next_literal_string() const {
-    return next_.literal_chars.start();
+  bool is_next_literal_ascii() {
+    ASSERT_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->is_ascii();
   }
-
-
-  // Returns the length of the next token (that would be returned if
-  // Next() were called).
+  Vector<const char> next_literal_ascii_string() {
+    ASSERT_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->ascii_literal();
+  }
+  Vector<const uc16> next_literal_uc16_string() {
+    ASSERT_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->uc16_literal();
+  }
   int next_literal_length() const {
-    // Excluding terminal '\x00' added by TerminateLiteral().
-    return next_.literal_chars.length() - 1;
-  }
-
-  Vector<const char> next_literal() const {
-    return Vector<const char>(next_literal_string(), next_literal_length());
+    ASSERT_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->length();
   }
 
   static const int kCharacterLookaheadBufferSize = 1;
@@ -279,7 +326,7 @@
   struct TokenDesc {
     Token::Value token;
     Location location;
-    Vector<const char> literal_chars;
+    LiteralBuffer* literal_chars;
   };
 
   // Call this after setting source_ to the input.
@@ -288,29 +335,31 @@
     ASSERT(kCharacterLookaheadBufferSize == 1);
     Advance();
     // Initialize current_ to not refer to a literal.
-    current_.literal_chars = Vector<const char>();
-    // Reset literal buffer.
-    literal_buffer_.Reset();
+    current_.literal_chars = NULL;
   }
 
   // Literal buffer support
   inline void StartLiteral() {
-    literal_buffer_.StartLiteral();
+    LiteralBuffer* free_buffer = (current_.literal_chars == &literal_buffer1_) ?
+            &literal_buffer2_ : &literal_buffer1_;
+    free_buffer->Reset();
+    next_.literal_chars = free_buffer;
   }
 
   inline void AddLiteralChar(uc32 c) {
-    literal_buffer_.AddChar(c);
+    ASSERT_NOT_NULL(next_.literal_chars);
+    next_.literal_chars->AddChar(c);
   }
 
   // Complete scanning of a literal.
   inline void TerminateLiteral() {
-    next_.literal_chars = literal_buffer_.EndLiteral();
+    // Does nothing in the current implementation.
   }
 
   // Stops scanning of a literal and drop the collected characters,
   // e.g., due to an encountered error.
   inline void DropLiteral() {
-    literal_buffer_.DropLiteral();
+    next_.literal_chars = NULL;
   }
 
   inline void AddLiteralCharAdvance() {
@@ -348,15 +397,16 @@
     return source_->pos() - kCharacterLookaheadBufferSize;
   }
 
+  // Buffers collecting literal strings, numbers, etc.
+  LiteralBuffer literal_buffer1_;
+  LiteralBuffer literal_buffer2_;
+
   TokenDesc current_;  // desc for current token (as returned by Next())
   TokenDesc next_;     // desc for next token (one token look-ahead)
 
   // Input stream. Must be initialized to an UC16CharacterStream.
   UC16CharacterStream* source_;
 
-  // Buffer to hold literal values (identifiers, strings, numbers)
-  // using '\x00'-terminated UTF-8 encoding. Handles allocation internally.
-  LiteralCollector literal_buffer_;
 
   // One Unicode character look-ahead; c0_ < 0 at the end of the input.
   uc32 c0_;
@@ -367,28 +417,14 @@
 
 class JavaScriptScanner : public Scanner {
  public:
-
-  // Bit vector representing set of types of literals.
-  enum LiteralType {
-    kNoLiterals = 0,
-    kLiteralNumber = 1,
-    kLiteralIdentifier = 2,
-    kLiteralString = 4,
-    kLiteralRegExp = 8,
-    kLiteralRegExpFlags = 16,
-    kAllLiterals = 31
-  };
-
   // A LiteralScope that disables recording of some types of JavaScript
   // literals. If the scanner is configured to not record the specific
   // type of literal, the scope will not call StartLiteral.
   class LiteralScope {
    public:
-    LiteralScope(JavaScriptScanner* self, LiteralType type)
+    explicit LiteralScope(JavaScriptScanner* self)
         : scanner_(self), complete_(false) {
-      if (scanner_->RecordsLiteral(type)) {
-        scanner_->StartLiteral();
-      }
+      scanner_->StartLiteral();
     }
      ~LiteralScope() {
        if (!complete_) scanner_->DropLiteral();
@@ -430,11 +466,6 @@
   // tokens, which is what it is used for.
   void SeekForward(int pos);
 
-  // Whether this scanner records the given literal type or not.
-  bool RecordsLiteral(LiteralType type) {
-    return (literal_flags_ & type) != 0;
-  }
-
  protected:
   bool SkipWhiteSpace();
   Token::Value SkipSingleLineComment();
@@ -458,7 +489,6 @@
   // If the escape sequence cannot be decoded the result is kBadChar.
   uc32 ScanIdentifierUnicodeEscape();
 
-  int literal_flags_;
   bool has_line_terminator_before_next_;
 };
 
diff --git a/src/scanner.cc b/src/scanner.cc
index 47e9895..38d0b1c 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -324,10 +324,8 @@
 V8JavaScriptScanner::V8JavaScriptScanner() : JavaScriptScanner() { }
 
 
-void V8JavaScriptScanner::Initialize(UC16CharacterStream* source,
-                                     int literal_flags) {
+void V8JavaScriptScanner::Initialize(UC16CharacterStream* source) {
   source_ = source;
-  literal_flags_ = literal_flags | kLiteralIdentifier;
   // Need to capture identifiers in order to recognize "get" and "set"
   // in object literals.
   Init();
@@ -377,7 +375,7 @@
 
 
 void JsonScanner::ScanJson() {
-  next_.literal_chars = Vector<const char>();
+  next_.literal_chars = NULL;
   Token::Value token;
   do {
     // Remember the position of the next token
diff --git a/src/scanner.h b/src/scanner.h
index 572778f..bdf899b 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -134,8 +134,7 @@
 class V8JavaScriptScanner : public JavaScriptScanner {
  public:
   V8JavaScriptScanner();
-  void Initialize(UC16CharacterStream* source,
-                  int literal_flags = kAllLiterals);
+  void Initialize(UC16CharacterStream* source);
 };
 
 
diff --git a/src/string-search.h b/src/string-search.h
index eac8475..5de3c09 100644
--- a/src/string-search.h
+++ b/src/string-search.h
@@ -66,12 +66,7 @@
   }
 
   static inline bool IsAsciiString(Vector<const uc16> string) {
-    for (int i = 0, n = string.length(); i < n; i++) {
-      if (static_cast<unsigned>(string[i]) > String::kMaxAsciiCharCodeU) {
-        return false;
-      }
-    }
-    return true;
+    return String::IsAscii(string.start(), string.length());
   }
 
   // The following tables are shared by all searches.
diff --git a/src/string.js b/src/string.js
index 9527599..ab0ab54 100644
--- a/src/string.js
+++ b/src/string.js
@@ -127,7 +127,7 @@
   var index = subLength - patLength;
   if (%_ArgumentsLength() > 1) {
     var position = ToNumber(%_Arguments(1));
-    if (!$isNaN(position)) {
+    if (!NUMBER_IS_NAN(position)) {
       position = TO_INTEGER(position);
       if (position < 0) {
         position = 0;
diff --git a/src/utils.h b/src/utils.h
index 62b8726..21e70d7 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -530,6 +530,24 @@
   }
 
 
+  // Add a contiguous block of elements and return a vector backed
+  // by the added block.
+  // A basic Collector will keep this vector valid as long as the Collector
+  // is alive.
+  inline Vector<T> AddBlock(Vector<const T> source) {
+    if (source.length() > current_chunk_.length() - index_) {
+      Grow(source.length());
+    }
+    T* position = current_chunk_.start() + index_;
+    index_ += source.length();
+    size_ += source.length();
+    for (int i = 0; i < source.length(); i++) {
+      position[i] = source[i];
+    }
+    return Vector<T>(position, source.length());
+  }
+
+
   // Write the contents of the collector into the provided vector.
   void WriteTo(Vector<T> destination) {
     ASSERT(size_ <= destination.length());
diff --git a/src/version.cc b/src/version.cc
index d2c0960..e362148 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     0
-#define BUILD_NUMBER      4
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      5
+#define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 2cf85f1..0838ddd 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -223,9 +223,7 @@
   // If input is ASCII, don't even bother calling here if the string to
   // match contains a non-ascii character.
   if (mode_ == ASCII) {
-    for (int i = 0; i < str.length(); i++) {
-      ASSERT(str[i] <= String::kMaxAsciiCharCodeU);
-    }
+    ASSERT(String::IsAscii(str.start(), str.length()));
   }
 #endif
   int byte_length = str.length() * char_size();
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index 40232ef..14692ff 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -74,7 +74,7 @@
                                   Handle<Object>(Heap::undefined_value()))->
       ToObjectChecked();
   CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   Code::cast(code)->Print();
 #endif
   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
@@ -112,7 +112,7 @@
                                   Handle<Object>(Heap::undefined_value()))->
       ToObjectChecked();
   CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   Code::cast(code)->Print();
 #endif
   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
@@ -155,7 +155,7 @@
       Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
 
   CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   Code::cast(code)->Print();
 #endif
   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
@@ -329,7 +329,7 @@
       Code::ComputeFlags(Code::STUB),
       Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
   CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   Code::cast(code)->Print();
 #endif
   F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
@@ -384,7 +384,7 @@
       Code::ComputeFlags(Code::STUB),
       Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
   CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   Code::cast(code)->Print();
 #endif
 
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 5cd56ac..b563f8f 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -443,7 +443,7 @@
       Code::ComputeFlags(Code::STUB),
       Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   Code::cast(code)->Print();
   byte* begin = Code::cast(code)->instruction_start();
   byte* end = begin + Code::cast(code)->instruction_size();
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index e642d1b..da5d771 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -573,7 +573,7 @@
                        int skip_pos = 0,  // Zero means not skipping.
                        int skip_to = 0) {
   i::V8JavaScriptScanner scanner;
-  scanner.Initialize(stream, i::JavaScriptScanner::kAllLiterals);
+  scanner.Initialize(stream);
 
   int i = 0;
   do {
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 6af6611..a274a48 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -438,6 +438,7 @@
         '../../src/messages.h',
         '../../src/natives.h',
         '../../src/objects-debug.cc',
+        '../../src/objects-printer.cc',
         '../../src/objects-inl.h',
         '../../src/objects-visiting.cc',
         '../../src/objects-visiting.h',
diff --git a/tools/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj
index 5254c6e..80a845c 100644
--- a/tools/v8.xcodeproj/project.pbxproj
+++ b/tools/v8.xcodeproj/project.pbxproj
@@ -59,7 +59,6 @@
 		893E24AD12B14B3D0083370F /* hydrogen.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E248F12B14B3D0083370F /* hydrogen.cc */; };
 		893E24AE12B14B3D0083370F /* lithium-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249312B14B3D0083370F /* lithium-allocator.cc */; };
 		893E24AF12B14B3D0083370F /* preparse-data.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249512B14B3D0083370F /* preparse-data.cc */; };
-		893E24B012B14B3D0083370F /* preparser-api.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249712B14B3D0083370F /* preparser-api.cc */; };
 		893E24B112B14B3D0083370F /* preparser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249812B14B3D0083370F /* preparser.cc */; };
 		893E24B212B14B3D0083370F /* runtime-profiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249A12B14B3D0083370F /* runtime-profiler.cc */; };
 		893E24B312B14B3D0083370F /* safepoint-table.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249C12B14B3D0083370F /* safepoint-table.cc */; };
@@ -74,7 +73,6 @@
 		893E24BC12B14B3D0083370F /* hydrogen.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E248F12B14B3D0083370F /* hydrogen.cc */; };
 		893E24BD12B14B3D0083370F /* lithium-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249312B14B3D0083370F /* lithium-allocator.cc */; };
 		893E24BE12B14B3D0083370F /* preparse-data.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249512B14B3D0083370F /* preparse-data.cc */; };
-		893E24BF12B14B3D0083370F /* preparser-api.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249712B14B3D0083370F /* preparser-api.cc */; };
 		893E24C012B14B3D0083370F /* preparser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249812B14B3D0083370F /* preparser.cc */; };
 		893E24C112B14B3D0083370F /* runtime-profiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249A12B14B3D0083370F /* runtime-profiler.cc */; };
 		893E24C212B14B3D0083370F /* safepoint-table.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249C12B14B3D0083370F /* safepoint-table.cc */; };
@@ -94,6 +92,8 @@
 		8944AD100F1D4D500028D560 /* regexp-stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */; };
 		8944AD110F1D4D570028D560 /* regexp-stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */; };
 		894599A30F5D8729008DA8FB /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
+		8946827512C26EB700C914BC /* objects-printer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8946827412C26EB700C914BC /* objects-printer.cc */; };
+		8946827612C26EB700C914BC /* objects-printer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8946827412C26EB700C914BC /* objects-printer.cc */; };
 		89495E480E79FC23001F68C3 /* compilation-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89495E460E79FC23001F68C3 /* compilation-cache.cc */; };
 		89495E490E79FC23001F68C3 /* compilation-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89495E460E79FC23001F68C3 /* compilation-cache.cc */; };
 		8956B6CF0F5D86730033B5A2 /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
@@ -412,7 +412,6 @@
 		893E249412B14B3D0083370F /* lithium-allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "lithium-allocator.h"; sourceTree = "<group>"; };
 		893E249512B14B3D0083370F /* preparse-data.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "preparse-data.cc"; sourceTree = "<group>"; };
 		893E249612B14B3D0083370F /* preparse-data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "preparse-data.h"; sourceTree = "<group>"; };
-		893E249712B14B3D0083370F /* preparser-api.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "preparser-api.cc"; sourceTree = "<group>"; };
 		893E249812B14B3D0083370F /* preparser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = preparser.cc; sourceTree = "<group>"; };
 		893E249912B14B3D0083370F /* preparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = preparser.h; sourceTree = "<group>"; };
 		893E249A12B14B3D0083370F /* runtime-profiler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "runtime-profiler.cc"; sourceTree = "<group>"; };
@@ -447,6 +446,7 @@
 		893E24DB12B14B9F0083370F /* gc-extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "gc-extension.h"; path = "extensions/gc-extension.h"; sourceTree = "<group>"; };
 		8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-stack.cc"; sourceTree = "<group>"; };
 		8944AD0F0F1D4D3A0028D560 /* regexp-stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-stack.h"; sourceTree = "<group>"; };
+		8946827412C26EB700C914BC /* objects-printer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "objects-printer.cc"; sourceTree = "<group>"; };
 		89471C7F0EB23EE400B6874B /* flag-definitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "flag-definitions.h"; sourceTree = "<group>"; };
 		89495E460E79FC23001F68C3 /* compilation-cache.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "compilation-cache.cc"; sourceTree = "<group>"; };
 		89495E470E79FC23001F68C3 /* compilation-cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "compilation-cache.h"; sourceTree = "<group>"; };
@@ -467,8 +467,6 @@
 		897F767A0E71B4CC007ACF34 /* v8_shell */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = v8_shell; sourceTree = BUILT_PRODUCTS_DIR; };
 		897FF0D40E719A8500D62E90 /* v8-debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "v8-debug.h"; sourceTree = "<group>"; };
 		897FF0D50E719A8500D62E90 /* v8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v8.h; sourceTree = "<group>"; };
-		897FF0E00E719B3500D62E90 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
-		897FF0E10E719B3500D62E90 /* dtoa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dtoa.c; sourceTree = "<group>"; };
 		897FF0F60E719B8F00D62E90 /* accessors.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = accessors.cc; sourceTree = "<group>"; };
 		897FF0F70E719B8F00D62E90 /* accessors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = accessors.h; sourceTree = "<group>"; };
 		897FF0F80E719B8F00D62E90 /* allocation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = allocation.cc; sourceTree = "<group>"; };
@@ -1003,6 +1001,7 @@
 				897FF15F0E719B8F00D62E90 /* natives.h */,
 				897FF1600E719B8F00D62E90 /* objects-debug.cc */,
 				897FF1610E719B8F00D62E90 /* objects-inl.h */,
+				8946827412C26EB700C914BC /* objects-printer.cc */,
 				C2D1E9711212F27B00187A52 /* objects-visiting.cc */,
 				C2D1E9721212F27B00187A52 /* objects-visiting.h */,
 				897FF1620E719B8F00D62E90 /* objects.cc */,
@@ -1020,7 +1019,6 @@
 				897FF16A0E719B8F00D62E90 /* platform.h */,
 				893E249512B14B3D0083370F /* preparse-data.cc */,
 				893E249612B14B3D0083370F /* preparse-data.h */,
-				893E249712B14B3D0083370F /* preparser-api.cc */,
 				893E249812B14B3D0083370F /* preparser.cc */,
 				893E249912B14B3D0083370F /* preparser.h */,
 				897FF16B0E719B8F00D62E90 /* prettyprinter.cc */,
@@ -1161,7 +1159,6 @@
 				893E24E212B14BD20083370F /* C++ */,
 				89A9C1630E71C8E300BE6CCA /* generated */,
 				897FF0D80E719ABA00D62E90 /* js */,
-				897FF0DE0E719B3400D62E90 /* third_party */,
 			);
 			path = src;
 			sourceTree = "<group>";
@@ -1194,23 +1191,6 @@
 			name = js;
 			sourceTree = "<group>";
 		};
-		897FF0DE0E719B3400D62E90 /* third_party */ = {
-			isa = PBXGroup;
-			children = (
-				897FF0DF0E719B3400D62E90 /* dtoa */,
-			);
-			path = third_party;
-			sourceTree = "<group>";
-		};
-		897FF0DF0E719B3400D62E90 /* dtoa */ = {
-			isa = PBXGroup;
-			children = (
-				897FF0E00E719B3500D62E90 /* COPYING */,
-				897FF0E10E719B3500D62E90 /* dtoa.c */,
-			);
-			path = dtoa;
-			sourceTree = "<group>";
-		};
 		897FF1B30E719BCE00D62E90 /* samples */ = {
 			isa = PBXGroup;
 			children = (
@@ -1583,7 +1563,6 @@
 				893E24BC12B14B3D0083370F /* hydrogen.cc in Sources */,
 				893E24BD12B14B3D0083370F /* lithium-allocator.cc in Sources */,
 				893E24BE12B14B3D0083370F /* preparse-data.cc in Sources */,
-				893E24BF12B14B3D0083370F /* preparser-api.cc in Sources */,
 				893E24C012B14B3D0083370F /* preparser.cc in Sources */,
 				893E24C112B14B3D0083370F /* runtime-profiler.cc in Sources */,
 				893E24C212B14B3D0083370F /* safepoint-table.cc in Sources */,
@@ -1595,6 +1574,7 @@
 				893E24D712B14B8A0083370F /* lithium-ia32.cc in Sources */,
 				893E24DC12B14B9F0083370F /* externalize-string-extension.cc in Sources */,
 				893E24DD12B14B9F0083370F /* gc-extension.cc in Sources */,
+				8946827512C26EB700C914BC /* objects-printer.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1738,7 +1718,6 @@
 				893E24AD12B14B3D0083370F /* hydrogen.cc in Sources */,
 				893E24AE12B14B3D0083370F /* lithium-allocator.cc in Sources */,
 				893E24AF12B14B3D0083370F /* preparse-data.cc in Sources */,
-				893E24B012B14B3D0083370F /* preparser-api.cc in Sources */,
 				893E24B112B14B3D0083370F /* preparser.cc in Sources */,
 				893E24B212B14B3D0083370F /* runtime-profiler.cc in Sources */,
 				893E24B312B14B3D0083370F /* safepoint-table.cc in Sources */,
@@ -1750,6 +1729,7 @@
 				893E24CE12B14B520083370F /* lithium-codegen-arm.cc in Sources */,
 				893E24DE12B14B9F0083370F /* externalize-string-extension.cc in Sources */,
 				893E24DF12B14B9F0083370F /* gc-extension.cc in Sources */,
+				8946827612C26EB700C914BC /* objects-printer.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1850,7 +1830,7 @@
 					DEBUG,
 					ENABLE_LOGGING_AND_PROFILING,
 					V8_ENABLE_CHECKS,
-                                        OBJECT_PRINT,
+					OBJECT_PRINT,
 					ENABLE_VMSTATE_TRACKING,
 				);
 				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
@@ -1915,7 +1895,7 @@
 					V8_TARGET_ARCH_IA32,
 					DEBUG,
 					V8_ENABLE_CHECKS,
-                                        OBJECT_PRINT,
+					OBJECT_PRINT,
 					ENABLE_DEBUGGER_SUPPORT,
 				);
 				HEADER_SEARCH_PATHS = ../src;
@@ -1978,7 +1958,7 @@
 					V8_TARGET_ARCH_IA32,
 					DEBUG,
 					V8_ENABLE_CHECKS,
-                                        OBJECT_PRINT,
+					OBJECT_PRINT,
 					ENABLE_DEBUGGER_SUPPORT,
 				);
 				HEADER_SEARCH_PATHS = ../src;
diff --git a/tools/visual_studio/v8_base.vcproj b/tools/visual_studio/v8_base.vcproj
index e53b3fc..ceeebf9 100644
--- a/tools/visual_studio/v8_base.vcproj
+++ b/tools/visual_studio/v8_base.vcproj
@@ -793,6 +793,10 @@
         >
       </File>
       <File
+        RelativePath="..\..\src\objects-printer.cc"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\objects-visiting.cc"
         >
       </File>
diff --git a/tools/visual_studio/v8_base_arm.vcproj b/tools/visual_studio/v8_base_arm.vcproj
index 1054958..cd4c52e 100644
--- a/tools/visual_studio/v8_base_arm.vcproj
+++ b/tools/visual_studio/v8_base_arm.vcproj
@@ -793,6 +793,10 @@
         >
       </File>
       <File
+        RelativePath="..\..\src\objects-printer.cc"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\objects-visiting.cc"
         >
       </File>
diff --git a/tools/visual_studio/v8_base_x64.vcproj b/tools/visual_studio/v8_base_x64.vcproj
index 28f299e..2c7bf5e 100644
--- a/tools/visual_studio/v8_base_x64.vcproj
+++ b/tools/visual_studio/v8_base_x64.vcproj
@@ -770,6 +770,10 @@
         >
       </File>
       <File
+        RelativePath="..\..\src\objects-printer.cc"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\objects-visiting.cc"
         >
       </File>