Push version 1.2.1 to trunk.

Added EcmaScript 5 JSON object.

Fix bug in preemption support on ARM.


git-svn-id: http://v8.googlecode.com/svn/trunk@1797 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/SConscript b/src/SConscript
index 97fb7d6..b0a2933 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -53,20 +53,22 @@
     'v8.cc', 'v8threads.cc', 'variables.cc', 'virtual-frame.cc', 'zone.cc'
   ],
   'arch:arm': [
-    'assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc', 'cpu-arm.cc',
-    'disasm-arm.cc', 'debug-arm.cc', 'frames-arm.cc', 'ic-arm.cc',
-    'jump-target-arm.cc', 'macro-assembler-arm.cc',
-    'regexp-macro-assembler-arm.cc', 'register-allocator-arm.cc',
-    'stub-cache-arm.cc', 'virtual-frame-arm.cc'
+    'arm/assembler-arm.cc', 'arm/builtins-arm.cc',
+    'arm/codegen-arm.cc', 'arm/cpu-arm.cc', 'arm/disasm-arm.cc',
+    'arm/debug-arm.cc', 'arm/frames-arm.cc', 'arm/ic-arm.cc',
+    'arm/jump-target-arm.cc', 'arm/macro-assembler-arm.cc',
+    'arm/register-allocator-arm.cc', 'arm/stub-cache-arm.cc',
+    'arm/regexp-macro-assembler-arm.cc', 'arm/virtual-frame-arm.cc'
   ],
   'arch:ia32': [
-    'assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc',
-    'cpu-ia32.cc', 'disasm-ia32.cc', 'debug-ia32.cc', 'frames-ia32.cc',
-    'ic-ia32.cc', 'jump-target-ia32.cc', 'macro-assembler-ia32.cc',
-    'regexp-macro-assembler-ia32.cc', 'register-allocator-ia32.cc',
-    'stub-cache-ia32.cc', 'virtual-frame-ia32.cc'
+    'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc',
+    'ia32/codegen-ia32.cc', 'ia32/cpu-ia32.cc', 'ia32/disasm-ia32.cc',
+    'ia32/debug-ia32.cc', 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc',
+    'ia32/jump-target-ia32.cc', 'ia32/macro-assembler-ia32.cc',
+    'ia32/register-allocator-ia32.cc', 'ia32/stub-cache-ia32.cc',
+    'ia32/regexp-macro-assembler-ia32.cc', 'ia32/virtual-frame-ia32.cc'
   ],
-  'simulator:arm': ['simulator-arm.cc'],
+  'simulator:arm': ['arm/simulator-arm.cc'],
   'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
   'os:linux':   ['platform-linux.cc', 'platform-posix.cc'],
   'os:android': ['platform-linux.cc', 'platform-posix.cc'],
@@ -121,6 +123,7 @@
 mirror-delay.js
 date-delay.js
 regexp-delay.js
+json-delay.js
 '''.split()
 
 
diff --git a/src/api.cc b/src/api.cc
index 449926c..860317d 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2422,7 +2422,7 @@
 
 
 const char* v8::V8::GetVersion() {
-  return "1.2.0";
+  return "1.2.1";
 }
 
 
@@ -3264,7 +3264,10 @@
                               bool message_handler_thread) {
   EnsureInitialized("v8::Debug::SetMessageHandler");
   ENTER_V8;
-  i::Debugger::SetMessageHandler(handler, message_handler_thread);
+  // Message handler thread not supported any more. Parameter temporally left in
+  // the API for client compatability reasons.
+  CHECK(!message_handler_thread);
+  i::Debugger::SetMessageHandler(handler);
 }
 
 
diff --git a/src/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
similarity index 99%
rename from src/assembler-arm-inl.h
rename to src/arm/assembler-arm-inl.h
index 315605e..65757e7 100644
--- a/src/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -37,7 +37,7 @@
 #ifndef V8_ASSEMBLER_ARM_INL_H_
 #define V8_ASSEMBLER_ARM_INL_H_
 
-#include "assembler-arm.h"
+#include "arm/assembler-arm.h"
 #include "cpu.h"
 
 
diff --git a/src/assembler-arm.cc b/src/arm/assembler-arm.cc
similarity index 99%
rename from src/assembler-arm.cc
rename to src/arm/assembler-arm.cc
index ba7638e..191c865 100644
--- a/src/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -36,7 +36,7 @@
 
 #include "v8.h"
 
-#include "assembler-arm-inl.h"
+#include "arm/assembler-arm-inl.h"
 #include "serialize.h"
 
 namespace v8 { namespace internal {
diff --git a/src/assembler-arm.h b/src/arm/assembler-arm.h
similarity index 96%
rename from src/assembler-arm.h
rename to src/arm/assembler-arm.h
index f965ebd..5edccbc 100644
--- a/src/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -164,23 +164,23 @@
 
 // Condition field in instructions
 enum Condition {
-  eq =  0 << 28,
-  ne =  1 << 28,
-  cs =  2 << 28,
-  hs =  2 << 28,
-  cc =  3 << 28,
-  lo =  3 << 28,
-  mi =  4 << 28,
-  pl =  5 << 28,
-  vs =  6 << 28,
-  vc =  7 << 28,
-  hi =  8 << 28,
-  ls =  9 << 28,
-  ge = 10 << 28,
-  lt = 11 << 28,
-  gt = 12 << 28,
-  le = 13 << 28,
-  al = 14 << 28
+  eq =  0 << 28,  // Z set            equal.
+  ne =  1 << 28,  // Z clear          not equal.
+  cs =  2 << 28,  // C set            unsigned higher or same.
+  hs =  2 << 28,  // C set            unsigned higher or same.
+  cc =  3 << 28,  // C clear          unsigned lower.
+  lo =  3 << 28,  // C clear          unsigned lower.
+  mi =  4 << 28,  // N set            negative.
+  pl =  5 << 28,  // N clear          positive or zero.
+  vs =  6 << 28,  // V set            overflow.
+  vc =  7 << 28,  // V clear          no overflow.
+  hi =  8 << 28,  // C set, Z clear   unsigned higher.
+  ls =  9 << 28,  // C clear or Z set unsigned lower or same.
+  ge = 10 << 28,  // N == V           greater or equal.
+  lt = 11 << 28,  // N != V           less than.
+  gt = 12 << 28,  // Z clear, N == V  greater than.
+  le = 13 << 28,  // Z set or N != V  less then or equal
+  al = 14 << 28   //                  always.
 };
 
 
diff --git a/src/builtins-arm.cc b/src/arm/builtins-arm.cc
similarity index 96%
rename from src/builtins-arm.cc
rename to src/arm/builtins-arm.cc
index 58eeca8..519c04a 100644
--- a/src/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -417,15 +417,35 @@
   __ push(r0);
   __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);
 
-  // Eagerly check for stack-overflow before starting to push the arguments.
-  // r0: number of arguments
-  Label okay;
+  Label no_preemption, retry_preemption;
+  __ bind(&retry_preemption);
   ExternalReference stack_guard_limit_address =
       ExternalReference::address_of_stack_guard_limit();
   __ mov(r2, Operand(stack_guard_limit_address));
   __ ldr(r2, MemOperand(r2));
+  __ cmp(sp, r2);
+  __ b(hi, &no_preemption);
+
+  // We have encountered a preemption or stack overflow already before we push
+  // the array contents.  Save r0 which is the Smi-tagged length of the array.
+  __ push(r0);
+
+  // Runtime routines expect at least one argument, so give it a Smi.
+  __ mov(r0, Operand(Smi::FromInt(0)));
+  __ push(r0);
+  __ CallRuntime(Runtime::kStackGuard, 1);
+
+  // Since we returned, it wasn't a stack overflow.  Restore r0 and try again.
+  __ pop(r0);
+  __ b(&retry_preemption);
+
+  __ bind(&no_preemption);
+
+  // Eagerly check for stack-overflow before starting to push the arguments.
+  // r0: number of arguments.
+  // r2: stack limit.
+  Label okay;
   __ sub(r2, sp, r2);
-  __ sub(r2, r2, Operand(3 * kPointerSize));  // limit, index, receiver
 
   __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
   __ b(hi, &okay);
diff --git a/src/codegen-arm.cc b/src/arm/codegen-arm.cc
similarity index 99%
rename from src/codegen-arm.cc
rename to src/arm/codegen-arm.cc
index 9337454..57e98c1 100644
--- a/src/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -4596,7 +4596,9 @@
   __ ldr(ip, MemOperand(ip));
   __ cmp(sp, Operand(ip));
   __ b(hs, &within_limit);
-  // Do tail-call to runtime routine.
+  // Do tail-call to runtime routine.  Runtime routines expect at least one
+  // argument, so give it a Smi.
+  __ mov(r0, Operand(Smi::FromInt(0)));
   __ push(r0);
   __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);
   __ bind(&within_limit);
diff --git a/src/codegen-arm.h b/src/arm/codegen-arm.h
similarity index 100%
rename from src/codegen-arm.h
rename to src/arm/codegen-arm.h
diff --git a/src/constants-arm.h b/src/arm/constants-arm.h
similarity index 100%
rename from src/constants-arm.h
rename to src/arm/constants-arm.h
diff --git a/src/cpu-arm.cc b/src/arm/cpu-arm.cc
similarity index 100%
rename from src/cpu-arm.cc
rename to src/arm/cpu-arm.cc
diff --git a/src/debug-arm.cc b/src/arm/debug-arm.cc
similarity index 100%
rename from src/debug-arm.cc
rename to src/arm/debug-arm.cc
diff --git a/src/disasm-arm.cc b/src/arm/disasm-arm.cc
similarity index 100%
rename from src/disasm-arm.cc
rename to src/arm/disasm-arm.cc
diff --git a/src/frames-arm.cc b/src/arm/frames-arm.cc
similarity index 98%
rename from src/frames-arm.cc
rename to src/arm/frames-arm.cc
index 121fb75..d26198a 100644
--- a/src/frames-arm.cc
+++ b/src/arm/frames-arm.cc
@@ -28,7 +28,7 @@
 #include "v8.h"
 
 #include "frames-inl.h"
-#include "assembler-arm-inl.h"
+#include "arm/assembler-arm-inl.h"
 
 
 namespace v8 { namespace internal {
diff --git a/src/frames-arm.h b/src/arm/frames-arm.h
similarity index 100%
rename from src/frames-arm.h
rename to src/arm/frames-arm.h
diff --git a/src/ic-arm.cc b/src/arm/ic-arm.cc
similarity index 95%
rename from src/ic-arm.cc
rename to src/arm/ic-arm.cc
index ad6eb2c..e418556 100644
--- a/src/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -127,27 +127,20 @@
 }
 
 
-// Helper function used to check that a value is either not a function
-// or is loaded if it is a function.
-static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm,
-                                             Label* miss,
-                                             Register value,
-                                             Register scratch) {
+// Helper function used to check that a value is either not an object
+// or is loaded if it is an object.
+static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm,
+                                           Label* miss,
+                                           Register value,
+                                           Register scratch) {
   Label done;
   // Check if the value is a Smi.
   __ tst(value, Operand(kSmiTagMask));
   __ b(eq, &done);
-  // Check if the value is a function.
-  __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
-  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
-  __ cmp(scratch, Operand(JS_FUNCTION_TYPE));
-  __ b(ne, &done);
-  // Check if the function has been loaded.
-  __ ldr(scratch,
-         FieldMemOperand(value, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(scratch,
-         FieldMemOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset));
-  __ cmp(scratch, Operand(Factory::undefined_value()));
+  // Check if the object has been loaded.
+  __ ldr(scratch, FieldMemOperand(value, JSObject::kMapOffset));
+  __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitField2Offset));
+  __ tst(scratch, Operand(1 << Map::kNeedsLoading));
   __ b(ne, miss);
   __ bind(&done);
 }
@@ -284,9 +277,9 @@
   __ b(ne, miss);
 
   // Check that the function has been loaded.
-  __ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kLazyLoadDataOffset));
-  __ cmp(r0, Operand(Factory::undefined_value()));
+  __ ldr(r0, FieldMemOperand(r1, JSObject::kMapOffset));
+  __ ldrb(r0, FieldMemOperand(r0, Map::kBitField2Offset));
+  __ tst(r0, Operand(1 << Map::kNeedsLoading));
   __ b(ne, miss);
 
   // Patch the receiver with the global proxy if necessary.
@@ -470,7 +463,7 @@
 
   __ bind(&probe);
   GenerateDictionaryLoad(masm, &miss, r1, r0);
-  GenerateCheckNonFunctionOrLoaded(masm, &miss, r0, r1);
+  GenerateCheckNonObjectOrLoaded(masm, &miss, r0, r1);
   __ Ret();
 
   // Global object access: Check access rights.
diff --git a/src/jump-target-arm.cc b/src/arm/jump-target-arm.cc
similarity index 100%
rename from src/jump-target-arm.cc
rename to src/arm/jump-target-arm.cc
diff --git a/src/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
similarity index 100%
rename from src/macro-assembler-arm.cc
rename to src/arm/macro-assembler-arm.cc
diff --git a/src/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
similarity index 100%
rename from src/macro-assembler-arm.h
rename to src/arm/macro-assembler-arm.h
diff --git a/src/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
similarity index 97%
rename from src/regexp-macro-assembler-arm.cc
rename to src/arm/regexp-macro-assembler-arm.cc
index bcfddf6..bf07f0e 100644
--- a/src/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -28,7 +28,7 @@
 #include "v8.h"
 #include "ast.h"
 #include "regexp-macro-assembler.h"
-#include "regexp-macro-assembler-arm.h"
+#include "arm/regexp-macro-assembler-arm.h"
 
 namespace v8 { namespace internal {
 
diff --git a/src/regexp-macro-assembler-arm.h b/src/arm/regexp-macro-assembler-arm.h
similarity index 100%
rename from src/regexp-macro-assembler-arm.h
rename to src/arm/regexp-macro-assembler-arm.h
diff --git a/src/register-allocator-arm.cc b/src/arm/register-allocator-arm.cc
similarity index 100%
rename from src/register-allocator-arm.cc
rename to src/arm/register-allocator-arm.cc
diff --git a/src/simulator-arm.cc b/src/arm/simulator-arm.cc
similarity index 99%
rename from src/simulator-arm.cc
rename to src/arm/simulator-arm.cc
index 7d96b3a..9737e95 100644
--- a/src/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -30,8 +30,8 @@
 #include "v8.h"
 
 #include "disasm.h"
-#include "constants-arm.h"
-#include "simulator-arm.h"
+#include "arm/constants-arm.h"
+#include "arm/simulator-arm.h"
 
 #if !defined(__arm__)
 
diff --git a/src/simulator-arm.h b/src/arm/simulator-arm.h
similarity index 100%
rename from src/simulator-arm.h
rename to src/arm/simulator-arm.h
diff --git a/src/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
similarity index 100%
rename from src/stub-cache-arm.cc
rename to src/arm/stub-cache-arm.cc
diff --git a/src/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc
similarity index 98%
rename from src/virtual-frame-arm.cc
rename to src/arm/virtual-frame-arm.cc
index b794d8b..43100f1 100644
--- a/src/virtual-frame-arm.cc
+++ b/src/arm/virtual-frame-arm.cc
@@ -71,6 +71,16 @@
 }
 
 
+void VirtualFrame::SyncRange(int begin, int end) {
+  // All elements are in memory on ARM (ie, synced).
+#ifdef DEBUG
+  for (int i = begin; i <= end; i++) {
+    ASSERT(elements_[i].is_synced());
+  }
+#endif
+}
+
+
 void VirtualFrame::MergeTo(VirtualFrame* expected) {
   Comment cmnt(masm_, "[ Merge frame");
   // We should always be merging the code generator's current frame to an
diff --git a/src/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
similarity index 100%
rename from src/virtual-frame-arm.h
rename to src/arm/virtual-frame-arm.h
diff --git a/src/ast.cc b/src/ast.cc
index 1a6010a..d19e3b3 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -152,6 +152,27 @@
 }
 
 
+bool ObjectLiteral::IsValidJSON() {
+  int length = properties()->length();
+  for (int i = 0; i < length; i++) {
+    Property* prop = properties()->at(i);
+    if (!prop->value()->IsValidJSON())
+      return false;
+  }
+  return true;
+}
+
+
+bool ArrayLiteral::IsValidJSON() {
+  int length = values()->length();
+  for (int i = 0; i < length; i++) {
+    if (!values()->at(i)->IsValidJSON())
+      return false;
+  }
+  return true;
+}
+
+
 void TargetCollector::AddTarget(BreakTarget* target) {
   // Add the label to the collector, but discard duplicates.
   int length = targets_->length();
diff --git a/src/ast.h b/src/ast.h
index b496816..6a2f671 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -155,6 +155,7 @@
  public:
   virtual Expression* AsExpression()  { return this; }
 
+  virtual bool IsValidJSON() { return false; }
   virtual bool IsValidLeftHandSide() { return false; }
 
   // Mark the expression as being compiled as an expression
@@ -625,6 +626,8 @@
     return handle_.is_identical_to(other->handle_);
   }
 
+  virtual bool IsValidJSON() { return true; }
+
   // Identity testers.
   bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
   bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); }
@@ -653,6 +656,8 @@
   // constants and simple object and array literals.
   bool is_simple() const { return is_simple_; }
 
+  virtual bool IsValidJSON() { return true; }
+
   int depth() const { return depth_; }
 
  private:
@@ -704,6 +709,7 @@
 
   virtual ObjectLiteral* AsObjectLiteral() { return this; }
   virtual void Accept(AstVisitor* v);
+  virtual bool IsValidJSON();
 
   Handle<FixedArray> constant_properties() const {
     return constant_properties_;
@@ -751,6 +757,7 @@
 
   virtual void Accept(AstVisitor* v);
   virtual ArrayLiteral* AsArrayLiteral() { return this; }
+  virtual bool IsValidJSON();
 
   Handle<FixedArray> literals() const { return literals_; }
   ZoneList<Expression*>* values() const { return values_; }
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index eebec74..c434207 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -530,7 +530,7 @@
     global_context()->function_instance_map()->set_prototype(*empty_function);
 
     // Allocate the function map first and then patch the prototype later
-    Handle<Map> empty_fm = Factory::CopyMap(fm);
+    Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
     empty_fm->set_instance_descriptors(*function_map_descriptors);
     empty_fm->set_prototype(global_context()->object_function()->prototype());
     empty_function->set_map(*empty_fm);
@@ -741,6 +741,19 @@
     global_context()->set_regexp_function(*regexp_fun);
   }
 
+  {  // -- J S O N
+    Handle<String> name = Factory::NewStringFromAscii(CStrVector("JSON"));
+    Handle<JSFunction> cons = Factory::NewFunction(
+        name,
+        Factory::the_hole_value());
+    cons->SetInstancePrototype(global_context()->initial_object_prototype());
+    cons->SetInstanceClassName(*name);
+    Handle<JSObject> json_object = Factory::NewJSObject(cons, TENURED);
+    ASSERT(json_object->IsJSObject());
+    SetProperty(global, name, json_object, DONT_ENUM);
+    global_context()->set_json_object(*json_object);
+  }
+
   {  // --- arguments_boilerplate_
     // Make sure we can recognize argument objects at runtime.
     // This is done by introducing an anonymous function with
@@ -1068,6 +1081,10 @@
               Natives::GetIndex("regexp"),
               Top::global_context(),
               Handle<Context>(Top::context()->runtime_context()));
+    SetupLazy(Handle<JSObject>(global_context()->json_object()),
+              Natives::GetIndex("json"),
+              Top::global_context(),
+              Handle<Context>(Top::context()->runtime_context()));
 
   } else if (strlen(FLAG_natives_file) != 0) {
     // Otherwise install natives from natives file if file exists and
@@ -1416,7 +1433,7 @@
 
   Handle<DescriptorArray> function_map_descriptors =
       ComputeFunctionInstanceDescriptor(false, true);
-  Handle<Map> fm = Factory::CopyMap(Top::function_map());
+  Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
   fm->set_instance_descriptors(*function_map_descriptors);
   Top::context()->global_context()->set_function_map(*fm);
 }
diff --git a/src/codegen.h b/src/codegen.h
index 54fe330..e9a5edd 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -77,9 +77,9 @@
 
 
 #ifdef ARM
-#include "codegen-arm.h"
+#include "arm/codegen-arm.h"
 #else
-#include "codegen-ia32.h"
+#include "ia32/codegen-ia32.h"
 #endif
 
 namespace v8 { namespace internal {
diff --git a/src/compiler.cc b/src/compiler.cc
index 62e838e..c16b938 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -80,8 +80,20 @@
 }
 
 
+static bool IsValidJSON(FunctionLiteral* lit) {
+  if (!lit->body()->length() == 1)
+    return false;
+  Statement* stmt = lit->body()->at(0);
+  if (stmt->AsExpressionStatement() == NULL)
+    return false;
+  Expression *expr = stmt->AsExpressionStatement()->expression();
+  return expr->IsValidJSON();
+}
+
+
 static Handle<JSFunction> MakeFunction(bool is_global,
                                        bool is_eval,
+                                       bool is_json,
                                        Handle<Script> script,
                                        Handle<Context> context,
                                        v8::Extension* extension,
@@ -109,6 +121,19 @@
     return Handle<JSFunction>::null();
   }
 
+  // When parsing JSON we do an ordinary parse and then afterwards
+  // check the AST to ensure it was well-formed.  If not we give a
+  // syntax error.
+  if (is_json && !IsValidJSON(lit)) {
+    HandleScope scope;
+    Handle<JSArray> args = Factory::NewJSArray(1);
+    Handle<Object> source(script->source());
+    SetElement(args, 0, source);
+    Handle<Object> result = Factory::NewSyntaxError("invalid_json", args);
+    Top::Throw(*result, NULL);
+    return Handle<JSFunction>::null();
+  }
+
   // Measure how long it takes to do the compilation; only take the
   // rest of the function into account to avoid overlap with the
   // parsing statistics.
@@ -215,6 +240,7 @@
     // Compile the function and add it to the cache.
     result = MakeFunction(true,
                           false,
+                          false,
                           script,
                           Handle<Context>::null(),
                           extension,
@@ -237,7 +263,8 @@
 Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
                                          Handle<Context> context,
                                          int line_offset,
-                                         bool is_global) {
+                                         bool is_global,
+                                         bool is_json) {
   int source_length = source->length();
   Counters::total_eval_size.Increment(source_length);
   Counters::total_compile_size.Increment(source_length);
@@ -256,7 +283,13 @@
     // Create a script object describing the script to be compiled.
     Handle<Script> script = Factory::NewScript(source);
     script->set_line_offset(Smi::FromInt(line_offset));
-    result = MakeFunction(is_global, true, script, context, NULL, NULL);
+    result = MakeFunction(is_global,
+                          true,
+                          is_json,
+                          script,
+                          context,
+                          NULL,
+                          NULL);
     if (!result.is_null()) {
       CompilationCache::PutEval(source, context, entry, result);
     }
diff --git a/src/compiler.h b/src/compiler.h
index 4f589b7..8abe130 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -60,7 +60,8 @@
   static Handle<JSFunction> CompileEval(Handle<String> source,
                                         Handle<Context> context,
                                         int line_offset,
-                                        bool is_global);
+                                        bool is_global,
+                                        bool is_json);
 
   // Compile from function info (used for lazy compilation). Returns
   // true on success and false if the compilation resulted in a stack
diff --git a/src/contexts.h b/src/contexts.h
index 3c25bd3..ed4b1cf 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -64,6 +64,7 @@
   V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
   V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
   V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
+  V(JSON_OBJECT_INDEX, JSObject, json_object) \
   V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
   V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
   V(CREATE_DATE_FUN_INDEX, JSFunction,  create_date_fun) \
@@ -186,6 +187,7 @@
     OBJECT_FUNCTION_INDEX,
     ARRAY_FUNCTION_INDEX,
     DATE_FUNCTION_INDEX,
+    JSON_OBJECT_INDEX,
     REGEXP_FUNCTION_INDEX,
     CREATE_DATE_FUN_INDEX,
     TO_NUMBER_FUN_INDEX,
diff --git a/src/date-delay.js b/src/date-delay.js
index 2421e5b..dbb9c2c 100644
--- a/src/date-delay.js
+++ b/src/date-delay.js
@@ -985,6 +985,25 @@
 }
 
 
+function PadInt(n) {
+  // Format integers to have at least two digits.
+  return n < 10 ? '0' + n : n;
+}
+
+
+function DateToISOString() {
+  return this.getUTCFullYear() + '-' + PadInt(this.getUTCMonth() + 1) +
+      '-' + PadInt(this.getUTCDate()) + 'T' + PadInt(this.getUTCHours()) +
+      ':' + PadInt(this.getUTCMinutes()) + ':' + PadInt(this.getUTCSeconds()) +
+      'Z';
+}
+
+
+function DateToJSON(key) {
+  return CheckJSONPrimitive(this.toISOString());
+}
+
+
 // -------------------------------------------------------------------
 
 function SetupDate() {
@@ -1044,7 +1063,9 @@
     "toGMTString", DateToGMTString,
     "toUTCString", DateToUTCString,
     "getYear", DateGetYear,
-    "setYear", DateSetYear
+    "setYear", DateSetYear,
+    "toISOString", DateToISOString,
+    "toJSON", DateToJSON
   ));
 }
 
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
index 9838746..0fab188 100644
--- a/src/debug-agent.cc
+++ b/src/debug-agent.cc
@@ -107,7 +107,7 @@
 
   // Create a new session and hook up the debug message handler.
   session_ = new DebuggerAgentSession(this, client);
-  v8::Debug::SetMessageHandler(DebuggerAgentMessageHandler, this);
+  v8::Debug::SetMessageHandler(DebuggerAgentMessageHandler);
   session_->Start();
 }
 
diff --git a/src/debug-delay.js b/src/debug-delay.js
index 6cb5e7f..961f304 100644
--- a/src/debug-delay.js
+++ b/src/debug-delay.js
@@ -1133,7 +1133,7 @@
   try {
     try {
       // Convert the JSON string to an object.
-      request = %CompileString('(' + json_request + ')', 0)();
+      request = %CompileString('(' + json_request + ')', 0, false)();
 
       // Create an initial response.
       response = this.createResponse(request);
diff --git a/src/debug.cc b/src/debug.cc
index 32a96a8..239a373 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1420,16 +1420,13 @@
 bool Debugger::compiling_natives_ = false;
 bool Debugger::is_loading_debugger_ = false;
 bool Debugger::never_unload_debugger_ = false;
-DebugMessageThread* Debugger::message_thread_ = NULL;
 v8::Debug::MessageHandler Debugger::message_handler_ = NULL;
 bool Debugger::message_handler_cleared_ = false;
 v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
 int Debugger::host_dispatch_micros_ = 100 * 1000;
 DebuggerAgent* Debugger::agent_ = NULL;
-LockingMessageQueue Debugger::command_queue_(kQueueInitialSize);
-LockingMessageQueue Debugger::message_queue_(kQueueInitialSize);
+LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize);
 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
-Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0);
 
 
 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
@@ -1818,7 +1815,7 @@
   // Notify the debugger that a debug event has occurred unless auto continue is
   // active in which case no event is send.
   if (!auto_continue) {
-    bool success = SendEventMessage(event_data);
+    bool success = InvokeMessageHandlerWithEvent(event_data);
     if (!success) {
       // If failed to notify debugger just continue running.
       return;
@@ -1845,7 +1842,7 @@
     StackGuard::Continue(DEBUGCOMMAND);
 
     // Get the command from the queue.
-    Message command = command_queue_.Get();
+    CommandMessage command = command_queue_.Get();
     Logger::DebugTag("Got request from command queue, in interactive loop.");
     if (!Debugger::IsDebuggerActive()) {
       // Delete command text and user data.
@@ -1900,7 +1897,7 @@
     }
 
     // Return the result.
-    SendMessage(Message::NewOutput(response, command.client_data()));
+    InvokeMessageHandler(response, command.client_data());
 
     // Return from debug event processing if either the VM is put into the
     // runnning state (through a continue command) or auto continue is active
@@ -1946,17 +1943,11 @@
 }
 
 
-void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler,
-                                 bool message_handler_thread) {
+void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) {
   ScopedLock with(debugger_access_);
 
   message_handler_ = handler;
-  if (handler != NULL) {
-    if (!message_thread_ && message_handler_thread) {
-      message_thread_ = new DebugMessageThread();
-      message_thread_->Start();
-    }
-  } else {
+  if (handler == NULL) {
     // Indicate that the message handler was recently cleared.
     message_handler_cleared_ = true;
 
@@ -1980,34 +1971,25 @@
 // public API. Messages are kept internally as Vector<uint16_t> strings, which
 // are allocated in various places and deallocated by the calling function
 // sometime after this call.
-void Debugger::InvokeMessageHandler(Message message) {
+void Debugger::InvokeMessageHandler(v8::Handle<v8::String> output,
+                                    v8::Debug::ClientData* data) {
   ScopedLock with(debugger_access_);
 
   if (message_handler_ != NULL) {
-    message_handler_(message.text().start(),
-                     message.text().length(),
-                     message.client_data());
+    Vector<uint16_t> text = Vector<uint16_t>::New(output->Length());
+    output->Write(text.start(), 0, output->Length());
+
+    message_handler_(text.start(),
+                     text.length(),
+                     data);
+
+    text.Dispose();
   }
-  message.Dispose();
+  delete data;
 }
 
 
-void Debugger::SendMessage(Message message) {
-  if (message_thread_ == NULL) {
-    // If there is no message thread just invoke the message handler from the
-    // V8 thread.
-    InvokeMessageHandler(message);
-  } else {
-    // Put the message coming from V8 on the queue. The text and user data will
-    // be destroyed by the message thread.
-    Logger::DebugTag("Put message on event message_queue.");
-    message_queue_.Put(message);
-    message_received_->Signal();
-  }
-}
-
-
-bool Debugger::SendEventMessage(Handle<Object> event_data) {
+bool Debugger::InvokeMessageHandlerWithEvent(Handle<Object> event_data) {
   v8::HandleScope scope;
   // Call toJSONProtocol on the debug event object.
   v8::Local<v8::Object> api_event_data =
@@ -2024,11 +2006,10 @@
       if (FLAG_trace_debug_json) {
         PrintLn(json_event_string);
       }
-      SendMessage(Message::NewOutput(
-          json_event_string,
-          NULL /* no user data since there was no request */));
+      InvokeMessageHandler(json_event_string,
+                           NULL /* no user data since there was no request */);
     } else {
-      SendMessage(Message::NewEmptyMessage());
+      InvokeMessageHandler(v8::String::Empty(), NULL);
     }
   } else {
     PrintLn(try_catch.Exception());
@@ -2041,13 +2022,11 @@
 // Puts a command coming from the public API on the queue.  Creates
 // a copy of the command string managed by the debugger.  Up to this
 // point, the command data was managed by the API client.  Called
-// by the API client thread.  This is where the API client hands off
-// processing of the command to the DebugMessageThread thread.
-// The new copy of the command is destroyed in HandleCommand().
+// by the API client thread.
 void Debugger::ProcessCommand(Vector<const uint16_t> command,
                               v8::Debug::ClientData* client_data) {
   // Need to cast away const.
-  Message message = Message::NewCommand(
+  CommandMessage message = CommandMessage::New(
       Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
                        command.length()),
       client_data);
@@ -2122,99 +2101,51 @@
 }
 
 
-void Debugger::TearDown() {
-  if (message_thread_ != NULL) {
-    message_thread_->Stop();
-    delete message_thread_;
-    message_thread_ = NULL;
-  }
+CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
+                                   client_data_(NULL) {
 }
 
 
-void DebugMessageThread::Run() {
-  // Sends debug events to an installed debugger message callback.
-  while (keep_running_) {
-    // Wait and Get are paired so that semaphore count equals queue length.
-    Debugger::message_received_->Wait();
-    Logger::DebugTag("Get message from event message_queue.");
-    Message message = Debugger::message_queue_.Get();
-    if (message.text().length() > 0) {
-      Debugger::InvokeMessageHandler(message);
-    } else {
-      message.Dispose();
-    }
-  }
-}
-
-
-void DebugMessageThread::Stop() {
-  keep_running_ = false;
-  Debugger::SendMessage(Message::NewEmptyMessage());
-  Join();
-}
-
-
-Message::Message() : text_(Vector<uint16_t>::empty()),
-                     client_data_(NULL) {
-}
-
-
-Message::Message(const Vector<uint16_t>& text,
-                 v8::Debug::ClientData* data)
+CommandMessage::CommandMessage(const Vector<uint16_t>& text,
+                               v8::Debug::ClientData* data)
     : text_(text),
       client_data_(data) {
 }
 
 
-Message::~Message() {
+CommandMessage::~CommandMessage() {
 }
 
 
-void Message::Dispose() {
+void CommandMessage::Dispose() {
   text_.Dispose();
   delete client_data_;
   client_data_ = NULL;
 }
 
 
-Message Message::NewCommand(const Vector<uint16_t>& command,
-                            v8::Debug::ClientData* data) {
-  return Message(command.Clone(), data);
+CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
+                                   v8::Debug::ClientData* data) {
+  return CommandMessage(command.Clone(), data);
 }
 
 
-Message Message::NewOutput(v8::Handle<v8::String> output,
-                           v8::Debug::ClientData* data) {
-  Vector<uint16_t> text;
-  if (!output.IsEmpty()) {
-    // Do not include trailing '\0'.
-    text = Vector<uint16_t>::New(output->Length());
-    output->Write(text.start(), 0, output->Length());
-  }
-  return Message(text, data);
+CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
+                                                     size_(size) {
+  messages_ = NewArray<CommandMessage>(size);
 }
 
 
-Message Message::NewEmptyMessage() {
-  return Message();
-}
-
-
-MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) {
-  messages_ = NewArray<Message>(size);
-}
-
-
-MessageQueue::~MessageQueue() {
+CommandMessageQueue::~CommandMessageQueue() {
   while (!IsEmpty()) {
-    Message m = Get();
+    CommandMessage m = Get();
     m.Dispose();
   }
   DeleteArray(messages_);
 }
 
 
-Message MessageQueue::Get() {
+CommandMessage CommandMessageQueue::Get() {
   ASSERT(!IsEmpty());
   int result = start_;
   start_ = (start_ + 1) % size_;
@@ -2222,7 +2153,7 @@
 }
 
 
-void MessageQueue::Put(const Message& message) {
+void CommandMessageQueue::Put(const CommandMessage& message) {
   if ((end_ + 1) % size_ == start_) {
     Expand();
   }
@@ -2231,12 +2162,12 @@
 }
 
 
-void MessageQueue::Expand() {
-  MessageQueue new_queue(size_ * 2);
+void CommandMessageQueue::Expand() {
+  CommandMessageQueue new_queue(size_ * 2);
   while (!IsEmpty()) {
     new_queue.Put(Get());
   }
-  Message* array_to_free = messages_;
+  CommandMessage* array_to_free = messages_;
   *this = new_queue;
   new_queue.messages_ = array_to_free;
   // Make the new_queue empty so that it doesn't call Dispose on any messages.
@@ -2245,38 +2176,39 @@
 }
 
 
-LockingMessageQueue::LockingMessageQueue(int size) : queue_(size) {
+LockingCommandMessageQueue::LockingCommandMessageQueue(int size)
+    : queue_(size) {
   lock_ = OS::CreateMutex();
 }
 
 
-LockingMessageQueue::~LockingMessageQueue() {
+LockingCommandMessageQueue::~LockingCommandMessageQueue() {
   delete lock_;
 }
 
 
-bool LockingMessageQueue::IsEmpty() const {
+bool LockingCommandMessageQueue::IsEmpty() const {
   ScopedLock sl(lock_);
   return queue_.IsEmpty();
 }
 
 
-Message LockingMessageQueue::Get() {
+CommandMessage LockingCommandMessageQueue::Get() {
   ScopedLock sl(lock_);
-  Message result = queue_.Get();
+  CommandMessage result = queue_.Get();
   Logger::DebugEvent("Get", result.text());
   return result;
 }
 
 
-void LockingMessageQueue::Put(const Message& message) {
+void LockingCommandMessageQueue::Put(const CommandMessage& message) {
   ScopedLock sl(lock_);
   queue_.Put(message);
   Logger::DebugEvent("Put", message.text());
 }
 
 
-void LockingMessageQueue::Clear() {
+void LockingCommandMessageQueue::Clear() {
   ScopedLock sl(lock_);
   queue_.Clear();
 }
diff --git a/src/debug.h b/src/debug.h
index ffd3da9..8a50cd2 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -405,70 +405,65 @@
 // In addition to command text it may contain a pointer to some user data
 // which are expected to be passed along with the command reponse to message
 // handler.
-class Message {
+class CommandMessage {
  public:
-  static Message NewCommand(const Vector<uint16_t>& command,
+  static CommandMessage New(const Vector<uint16_t>& command,
                             v8::Debug::ClientData* data);
-  static Message NewOutput(v8::Handle<v8::String> output,
-                           v8::Debug::ClientData* data);
-  static Message NewEmptyMessage();
-  Message();
-  ~Message();
+  CommandMessage();
+  ~CommandMessage();
 
   // Deletes user data and disposes of the text.
   void Dispose();
   Vector<uint16_t> text() const { return text_; }
   v8::Debug::ClientData* client_data() const { return client_data_; }
  private:
-  Message(const Vector<uint16_t>& text,
-          v8::Debug::ClientData* data);
+  CommandMessage(const Vector<uint16_t>& text,
+                 v8::Debug::ClientData* data);
 
   Vector<uint16_t> text_;
   v8::Debug::ClientData* client_data_;
 };
 
-// A Queue of Vector<uint16_t> objects.  A thread-safe version is
-// LockingMessageQueue, based on this class.
-class MessageQueue BASE_EMBEDDED {
+// A Queue of CommandMessage objects.  A thread-safe version is
+// LockingCommandMessageQueue, based on this class.
+class CommandMessageQueue BASE_EMBEDDED {
  public:
-  explicit MessageQueue(int size);
-  ~MessageQueue();
+  explicit CommandMessageQueue(int size);
+  ~CommandMessageQueue();
   bool IsEmpty() const { return start_ == end_; }
-  Message Get();
-  void Put(const Message& message);
+  CommandMessage Get();
+  void Put(const CommandMessage& message);
   void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
  private:
   // Doubles the size of the message queue, and copies the messages.
   void Expand();
 
-  Message* messages_;
+  CommandMessage* messages_;
   int start_;
   int end_;
   int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
 };
 
 
-// LockingMessageQueue is a thread-safe circular buffer of Vector<uint16_t>
-// messages.  The message data is not managed by LockingMessageQueue.
+// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
+// messages.  The message data is not managed by LockingCommandMessageQueue.
 // Pointers to the data are passed in and out. Implemented by adding a
-// Mutex to MessageQueue.  Includes logging of all puts and gets.
-class LockingMessageQueue BASE_EMBEDDED {
+// Mutex to CommandMessageQueue.  Includes logging of all puts and gets.
+class LockingCommandMessageQueue BASE_EMBEDDED {
  public:
-  explicit LockingMessageQueue(int size);
-  ~LockingMessageQueue();
+  explicit LockingCommandMessageQueue(int size);
+  ~LockingCommandMessageQueue();
   bool IsEmpty() const;
-  Message Get();
-  void Put(const Message& message);
+  CommandMessage Get();
+  void Put(const CommandMessage& message);
   void Clear();
  private:
-  MessageQueue queue_;
+  CommandMessageQueue queue_;
   Mutex* lock_;
-  DISALLOW_COPY_AND_ASSIGN(LockingMessageQueue);
+  DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
 };
 
 
-class DebugMessageThread;
-
 class Debugger {
  public:
   static void DebugRequest(const uint16_t* json_request, int length);
@@ -503,21 +498,16 @@
                                    Handle<Object> event_data,
                                    bool auto_continue);
   static void SetEventListener(Handle<Object> callback, Handle<Object> data);
-  static void SetMessageHandler(v8::Debug::MessageHandler handler,
-                                bool message_handler_thread);
-  static void TearDown();
+  static void SetMessageHandler(v8::Debug::MessageHandler handler);
   static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
                                      int period);
 
   // Invoke the message handler function.
-  static void InvokeMessageHandler(Message message);
-
-  // Send a message to the message handler eiher through the message thread or
-  // directly.
-  static void SendMessage(Message message);
+  static void InvokeMessageHandler(v8::Handle<v8::String> output,
+                                   v8::Debug::ClientData* data);
 
   // Send the JSON message for a debug event.
-  static bool SendEventMessage(Handle<Object> event_data);
+  static bool InvokeMessageHandlerWithEvent(Handle<Object> event_data);
 
   // Add a debugger command to the command queue.
   static void ProcessCommand(Vector<const uint16_t> command,
@@ -568,7 +558,6 @@
   static bool compiling_natives_;  // Are we compiling natives?
   static bool is_loading_debugger_;  // Are we loading the debugger?
   static bool never_unload_debugger_;  // Can we unload the debugger?
-  static DebugMessageThread* message_thread_;
   static v8::Debug::MessageHandler message_handler_;
   static bool message_handler_cleared_;  // Was message handler cleared?
   static v8::Debug::HostDispatchHandler host_dispatch_handler_;
@@ -577,32 +566,10 @@
   static DebuggerAgent* agent_;
 
   static const int kQueueInitialSize = 4;
-  static LockingMessageQueue command_queue_;
-  static LockingMessageQueue message_queue_;
+  static LockingCommandMessageQueue command_queue_;
   static Semaphore* command_received_;  // Signaled for each command received.
-  static Semaphore* message_received_;  // Signalled for each message send.
 
   friend class EnterDebugger;
-  friend class DebugMessageThread;
-};
-
-
-// Thread to read messages from the message queue and invoke the debug message
-// handler in another thread as the V8 thread. This thread is started if the
-// registration of the debug message handler requested to be called in a thread
-// seperate from the V8 thread.
-class DebugMessageThread: public Thread {
- public:
-  DebugMessageThread() : keep_running_(true) {}
-  virtual ~DebugMessageThread() {}
-
-  // Main function of DebugMessageThread thread.
-  void Run();
-  void Stop();
-
- private:
-  bool keep_running_;
-  DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
 };
 
 
diff --git a/src/execution.cc b/src/execution.cc
index 1d4d9ef..8fa059a 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -33,9 +33,9 @@
 #include "codegen-inl.h"
 
 #ifdef ARM
-#include "simulator-arm.h"
+#include "arm/simulator-arm.h"
 #else  // ia32
-#include "simulator-ia32.h"
+#include "ia32/simulator-ia32.h"
 #endif
 
 #include "debug.h"
diff --git a/src/factory.cc b/src/factory.cc
index c849ab7..c6b1d17 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -208,14 +208,14 @@
 }
 
 
-Handle<Map> Factory::CopyMap(Handle<Map> src) {
-  CALL_HEAP_FUNCTION(src->Copy(), Map);
+Handle<Map> Factory::CopyMapDropDescriptors(Handle<Map> src) {
+  CALL_HEAP_FUNCTION(src->CopyDropDescriptors(), Map);
 }
 
 
 Handle<Map> Factory::CopyMap(Handle<Map> src,
                              int extra_inobject_properties) {
-  Handle<Map> copy = CopyMap(src);
+  Handle<Map> copy = CopyMapDropDescriptors(src);
   // Check that we do not overflow the instance size when adding the
   // extra inobject properties.
   int instance_size_delta = extra_inobject_properties * kPointerSize;
diff --git a/src/factory.h b/src/factory.h
index 54f2089..6ac2706 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -153,7 +153,7 @@
 
   static Handle<JSObject> NewFunctionPrototype(Handle<JSFunction> function);
 
-  static Handle<Map> CopyMap(Handle<Map> map);
+  static Handle<Map> CopyMapDropDescriptors(Handle<Map> map);
 
   // Copy the map adding more inobject properties if possible without
   // overflowing the instance size.
diff --git a/src/frames-inl.h b/src/frames-inl.h
index cb03e2f..481b83b 100644
--- a/src/frames-inl.h
+++ b/src/frames-inl.h
@@ -30,9 +30,9 @@
 
 #include "frames.h"
 #ifdef ARM
-#include "frames-arm.h"
+#include "arm/frames-arm.h"
 #else
-#include "frames-ia32.h"
+#include "ia32/frames-ia32.h"
 #endif
 
 
diff --git a/src/handles.cc b/src/handles.cc
index 99161ce..773483d 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -627,9 +627,9 @@
 }
 
 
-void LoadLazy(Handle<JSFunction> fun, bool* pending_exception) {
+void LoadLazy(Handle<JSObject> obj, bool* pending_exception) {
   HandleScope scope;
-  Handle<FixedArray> info(FixedArray::cast(fun->shared()->lazy_load_data()));
+  Handle<FixedArray> info(FixedArray::cast(obj->map()->constructor()));
   int index = Smi::cast(info->get(0))->value();
   ASSERT(index >= 0);
   Handle<Context> compile_context(Context::cast(info->get(1)));
@@ -674,27 +674,39 @@
 
   // Reset the lazy load data before running the script to make sure
   // not to get recursive lazy loading.
-  fun->shared()->set_lazy_load_data(Heap::undefined_value());
+  obj->map()->set_needs_loading(false);
+  obj->map()->set_constructor(info->get(3));
 
   // Run the script.
   Handle<JSFunction> script_fun(
       Factory::NewFunctionFromBoilerplate(boilerplate, function_context));
   Execution::Call(script_fun, receiver, 0, NULL, pending_exception);
 
-  // If lazy loading failed, restore the unloaded state of fun.
-  if (*pending_exception) fun->shared()->set_lazy_load_data(*info);
+  // If lazy loading failed, restore the unloaded state of obj.
+  if (*pending_exception) {
+    obj->map()->set_needs_loading(true);
+    obj->map()->set_constructor(*info);
+  }
 }
 
 
-void SetupLazy(Handle<JSFunction> fun,
+void SetupLazy(Handle<JSObject> obj,
                int index,
                Handle<Context> compile_context,
                Handle<Context> function_context) {
-  Handle<FixedArray> arr = Factory::NewFixedArray(3);
+  Handle<FixedArray> arr = Factory::NewFixedArray(4);
   arr->set(0, Smi::FromInt(index));
   arr->set(1, *compile_context);  // Compile in this context
   arr->set(2, *function_context);  // Set function context to this
-  fun->shared()->set_lazy_load_data(*arr);
+  arr->set(3, obj->map()->constructor());  // Remember the constructor
+  Handle<Map> old_map(obj->map());
+  Handle<Map> new_map = Factory::CopyMapDropTransitions(old_map);
+  obj->set_map(*new_map);
+  new_map->set_needs_loading(true);
+  // Store the lazy loading info in the constructor field.  We'll
+  // reestablish the constructor from the fixed array after loading.
+  new_map->set_constructor(*arr);
+  ASSERT(!obj->IsLoaded());
 }
 
 } }  // namespace v8::internal
diff --git a/src/handles.h b/src/handles.h
index 9cc1db4..652d6c7 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -301,11 +301,11 @@
 bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
 
 // These deal with lazily loaded properties.
-void SetupLazy(Handle<JSFunction> fun,
+void SetupLazy(Handle<JSObject> obj,
                int index,
                Handle<Context> compile_context,
                Handle<Context> function_context);
-void LoadLazy(Handle<JSFunction> fun, bool* pending_exception);
+void LoadLazy(Handle<JSObject> obj, bool* pending_exception);
 
 class NoHandleAllocation BASE_EMBEDDED {
  public:
diff --git a/src/heap.cc b/src/heap.cc
index a57884c..0775a5d 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -939,6 +939,7 @@
   map->set_code_cache(empty_fixed_array());
   map->set_unused_property_fields(0);
   map->set_bit_field(0);
+  map->set_bit_field2(0);
   return map;
 }
 
@@ -1409,7 +1410,6 @@
   share->set_formal_parameter_count(0);
   share->set_instance_class_name(Object_symbol());
   share->set_function_data(undefined_value());
-  share->set_lazy_load_data(undefined_value());
   share->set_script(undefined_value());
   share->set_start_position_and_type(0);
   share->set_debug_info(undefined_value());
diff --git a/src/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
similarity index 100%
rename from src/assembler-ia32-inl.h
rename to src/ia32/assembler-ia32-inl.h
diff --git a/src/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
similarity index 100%
rename from src/assembler-ia32.cc
rename to src/ia32/assembler-ia32.cc
diff --git a/src/assembler-ia32.h b/src/ia32/assembler-ia32.h
similarity index 100%
rename from src/assembler-ia32.h
rename to src/ia32/assembler-ia32.h
diff --git a/src/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
similarity index 100%
rename from src/builtins-ia32.cc
rename to src/ia32/builtins-ia32.cc
diff --git a/src/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
similarity index 99%
rename from src/codegen-ia32.cc
rename to src/ia32/codegen-ia32.cc
index fb2f8bf..2d6fe83 100644
--- a/src/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -5273,12 +5273,14 @@
   // instruction.
   ASSERT(value.is_register() && value.reg().is(eax));
   // The delta from the start of the map-compare instruction to the
-  // test eax instruction.  We use masm_ directly here instead of the
+  // test instruction.  We use masm_ directly here instead of the
   // double underscore macro because the macro sometimes uses macro
   // expansion to turn into something that can't return a value.  This
   // is encountered when doing generated code coverage tests.
   int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
-  __ test(value.reg(), Immediate(-delta_to_patch_site));
+  // Here we use masm_-> instead of the double underscore macro because this
+  // is the instruction that gets patched and coverage code gets in the way.
+  masm_->test(value.reg(), Immediate(-delta_to_patch_site));
   __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
 
   // The receiver and key were spilled by the call, so their state as
diff --git a/src/codegen-ia32.h b/src/ia32/codegen-ia32.h
similarity index 100%
rename from src/codegen-ia32.h
rename to src/ia32/codegen-ia32.h
diff --git a/src/cpu-ia32.cc b/src/ia32/cpu-ia32.cc
similarity index 100%
rename from src/cpu-ia32.cc
rename to src/ia32/cpu-ia32.cc
diff --git a/src/debug-ia32.cc b/src/ia32/debug-ia32.cc
similarity index 100%
rename from src/debug-ia32.cc
rename to src/ia32/debug-ia32.cc
diff --git a/src/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
similarity index 100%
rename from src/disasm-ia32.cc
rename to src/ia32/disasm-ia32.cc
diff --git a/src/frames-ia32.cc b/src/ia32/frames-ia32.cc
similarity index 100%
rename from src/frames-ia32.cc
rename to src/ia32/frames-ia32.cc
diff --git a/src/frames-ia32.h b/src/ia32/frames-ia32.h
similarity index 100%
rename from src/frames-ia32.h
rename to src/ia32/frames-ia32.h
diff --git a/src/ic-ia32.cc b/src/ia32/ic-ia32.cc
similarity index 96%
rename from src/ic-ia32.cc
rename to src/ia32/ic-ia32.cc
index 664303f..559ac24 100644
--- a/src/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -123,23 +123,19 @@
 }
 
 
-// Helper function used to check that a value is either not a function
-// or is loaded if it is a function.
-static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm, Label* miss,
-                                             Register value, Register scratch) {
+// Helper function used to check that a value is either not an object
+// or is loaded if it is an object.
+static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss,
+                                           Register value, Register scratch) {
   Label done;
   // Check if the value is a Smi.
   __ test(value, Immediate(kSmiTagMask));
   __ j(zero, &done, not_taken);
-  // Check if the value is a function.
-  __ CmpObjectType(value, JS_FUNCTION_TYPE, scratch);
-  __ j(not_equal, &done, taken);
-  // Check if the function has been loaded.
-  __ mov(scratch, FieldOperand(value, JSFunction::kSharedFunctionInfoOffset));
-  __ mov(scratch,
-         FieldOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset));
-  __ cmp(scratch, Factory::undefined_value());
-  __ j(not_equal, miss, not_taken);
+  // Check if the object has been loaded.
+  __ mov(scratch, FieldOperand(value, JSFunction::kMapOffset));
+  __ mov(scratch, FieldOperand(scratch, Map::kBitField2Offset));
+  __ test(scratch, Immediate(1 << Map::kNeedsLoading));
+  __ j(not_zero, miss, not_taken);
   __ bind(&done);
 }
 
@@ -268,7 +264,7 @@
   __ j(not_zero, &slow, not_taken);
   // Probe the dictionary leaving result in ecx.
   GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax);
-  GenerateCheckNonFunctionOrLoaded(masm, &slow, ecx, edx);
+  GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx);
   __ mov(eax, Operand(ecx));
   __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
   __ ret(0);
@@ -493,10 +489,10 @@
   __ j(not_equal, miss, not_taken);
 
   // Check that the function has been loaded.
-  __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-  __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kLazyLoadDataOffset));
-  __ cmp(edx, Factory::undefined_value());
-  __ j(not_equal, miss, not_taken);
+  __ mov(edx, FieldOperand(edi, JSFunction::kMapOffset));
+  __ mov(edx, FieldOperand(edx, Map::kBitField2Offset));
+  __ test(edx, Immediate(1 << Map::kNeedsLoading));
+  __ j(not_zero, miss, not_taken);
 
   // Patch the receiver with the global proxy if necessary.
   if (is_global_object) {
@@ -683,7 +679,7 @@
   // Search the dictionary placing the result in eax.
   __ bind(&probe);
   GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx);
-  GenerateCheckNonFunctionOrLoaded(masm, &miss, eax, edx);
+  GenerateCheckNonObjectOrLoaded(masm, &miss, eax, edx);
   __ ret(0);
 
   // Global object access: Check access rights.
diff --git a/src/jump-target-ia32.cc b/src/ia32/jump-target-ia32.cc
similarity index 100%
rename from src/jump-target-ia32.cc
rename to src/ia32/jump-target-ia32.cc
diff --git a/src/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
similarity index 100%
rename from src/macro-assembler-ia32.cc
rename to src/ia32/macro-assembler-ia32.cc
diff --git a/src/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
similarity index 100%
rename from src/macro-assembler-ia32.h
rename to src/ia32/macro-assembler-ia32.h
diff --git a/src/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
similarity index 99%
rename from src/regexp-macro-assembler-ia32.cc
rename to src/ia32/regexp-macro-assembler-ia32.cc
index 8c92091..83dac54 100644
--- a/src/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -32,8 +32,8 @@
 #include "regexp-stack.h"
 #include "macro-assembler.h"
 #include "regexp-macro-assembler.h"
-#include "macro-assembler-ia32.h"
-#include "regexp-macro-assembler-ia32.h"
+#include "ia32/macro-assembler-ia32.h"
+#include "ia32/regexp-macro-assembler-ia32.h"
 
 namespace v8 { namespace internal {
 
diff --git a/src/regexp-macro-assembler-ia32.h b/src/ia32/regexp-macro-assembler-ia32.h
similarity index 100%
rename from src/regexp-macro-assembler-ia32.h
rename to src/ia32/regexp-macro-assembler-ia32.h
diff --git a/src/register-allocator-ia32.cc b/src/ia32/register-allocator-ia32.cc
similarity index 100%
rename from src/register-allocator-ia32.cc
rename to src/ia32/register-allocator-ia32.cc
diff --git a/src/simulator-ia32.cc b/src/ia32/simulator-ia32.cc
similarity index 100%
rename from src/simulator-ia32.cc
rename to src/ia32/simulator-ia32.cc
diff --git a/src/simulator-ia32.h b/src/ia32/simulator-ia32.h
similarity index 100%
rename from src/simulator-ia32.h
rename to src/ia32/simulator-ia32.h
diff --git a/src/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
similarity index 100%
rename from src/stub-cache-ia32.cc
rename to src/ia32/stub-cache-ia32.cc
diff --git a/src/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc
similarity index 97%
rename from src/virtual-frame-ia32.cc
rename to src/ia32/virtual-frame-ia32.cc
index 3647ca5..656ef21 100644
--- a/src/virtual-frame-ia32.cc
+++ b/src/ia32/virtual-frame-ia32.cc
@@ -158,6 +158,28 @@
 }
 
 
+// Clear the dirty bits for the range of elements in
+// [min(stack_pointer_ + 1,begin), end].
+void VirtualFrame::SyncRange(int begin, int end) {
+  ASSERT(begin >= 0);
+  ASSERT(end < elements_.length());
+  // Sync elements below the range if they have not been materialized
+  // on the stack.
+  int start = Min(begin, stack_pointer_ + 1);
+
+  // If positive we have to adjust the stack pointer.
+  int delta = end - stack_pointer_;
+  if (delta > 0) {
+    stack_pointer_ = end;
+    __ sub(Operand(esp), Immediate(delta * kPointerSize));
+  }
+
+  for (int i = start; i <= end; i++) {
+    if (!elements_[i].is_synced()) SyncElementBelowStackPointer(i);
+  }
+}
+
+
 void VirtualFrame::MergeTo(VirtualFrame* expected) {
   Comment cmnt(masm_, "[ Merge frame");
   // We should always be merging the code generator's current frame to an
@@ -467,7 +489,7 @@
     // we sync them with the actual frame to allocate space for spilling
     // them later.  First sync everything above the stack pointer so we can
     // use pushes to allocate and initialize the locals.
-    SyncRange(stack_pointer_ + 1, elements_.length());
+    SyncRange(stack_pointer_ + 1, elements_.length() - 1);
     Handle<Object> undefined = Factory::undefined_value();
     FrameElement initial_value =
         FrameElement::ConstantElement(undefined, FrameElement::SYNCED);
diff --git a/src/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h
similarity index 100%
rename from src/virtual-frame-ia32.h
rename to src/ia32/virtual-frame-ia32.h
diff --git a/src/json-delay.js b/src/json-delay.js
new file mode 100644
index 0000000..90150c6
--- /dev/null
+++ b/src/json-delay.js
@@ -0,0 +1,254 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+var $JSON = global.JSON;
+
+function ParseJSONUnfiltered(text) {
+  var s = $String(text);
+  var f = %CompileString("(" + text + ")", -1, true);
+  return f();
+}
+
+function Revive(holder, name, reviver) {
+  var val = holder[name];
+  if (IS_OBJECT(val)) {
+    if (IS_ARRAY(val)) {
+      var length = val.length;
+      for (var i = 0; i < length; i++) {
+        var newElement = Revive(val, $String(i), reviver);
+        val[i] = newElement;
+      }
+    } else {
+      for (var p in val) {
+        if (ObjectHasOwnProperty.call(val, p)) {
+          var newElement = Revive(val, p, reviver);
+          if (IS_UNDEFINED(newElement)) {
+            delete val[p];
+          } else {
+            val[p] = newElement;
+          }
+        }
+      }
+    }
+  }
+  return reviver.call(holder, name, val);
+}
+
+function JSONParse(text, reviver) {
+  var unfiltered = ParseJSONUnfiltered(text);
+  if (IS_FUNCTION(reviver)) {
+    return Revive({'': unfiltered}, '', reviver);
+  } else {
+    return unfiltered;
+  }
+}
+
+var characterQuoteCache = {
+  '\"': '\\"',
+  '\\': '\\\\',
+  '/': '\\/',
+  '\b': '\\b',
+  '\f': '\\f',
+  '\n': '\\n',
+  '\r': '\\r',
+  '\t': '\\t',
+  '\x0B': '\\u000b'
+};
+
+function QuoteSingleJSONCharacter(c) {
+  if (c in characterQuoteCache)
+    return characterQuoteCache[c];
+  var charCode = c.charCodeAt(0);
+  var result;
+  if (charCode < 16) result = '\\u000';
+  else if (charCode < 256) result = '\\u00';
+  else if (charCode < 4096) result = '\\u0';
+  else result = '\\u';
+  result += charCode.toString(16);
+  characterQuoteCache[c] = result;
+  return result;
+}
+
+function QuoteJSONString(str) {
+  var quotable = /[\\\"\x00-\x1f\x80-\uffff]/g;
+  return '"' + str.replace(quotable, QuoteSingleJSONCharacter) + '"';
+}
+
+function StackContains(stack, val) {
+  var length = stack.length;
+  for (var i = 0; i < length; i++) {
+    if (stack[i] === val)
+      return true;
+  }
+  return false;
+}
+
+function SerializeArray(value, replacer, stack, indent, gap) {
+  if (StackContains(stack, value))
+    throw MakeTypeError('circular_structure', []);
+  stack.push(value);
+  var stepback = indent;
+  indent += gap;
+  var partial = [];
+  var len = value.length;
+  for (var i = 0; i < len; i++) {
+    var strP = JSONSerialize($String(i), value, replacer, stack,
+        indent, gap);
+    if (IS_UNDEFINED(strP))
+      strP = "null";
+    partial.push(strP);
+  }
+  var final;
+  if (gap == "") {
+    final = "[" + partial.join(",") + "]";
+  } else if (partial.length > 0) {
+    var separator = ",\n" + indent;
+    final = "[\n" + indent + partial.join(separator) + "\n" +
+        stepback + "]";
+  } else {
+    final = "[]";
+  }
+  stack.pop();
+  return final;
+}
+
+function SerializeObject(value, replacer, stack, indent, gap) {
+  if (StackContains(stack, value))
+    throw MakeTypeError('circular_structure', []);
+  stack.push(value);
+  var stepback = indent;
+  indent += gap;
+  var partial = [];
+  if (IS_ARRAY(replacer)) {
+    var length = replacer.length;
+    for (var i = 0; i < length; i++) {
+      if (ObjectHasOwnProperty.call(replacer, i)) {
+        var p = replacer[i];
+        var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
+        if (!IS_UNDEFINED(strP)) {
+          var member = QuoteJSONString(p) + ":";
+          if (gap != "") member += " ";
+          member += strP;
+          partial.push(member);
+        }
+      }
+    }
+  } else {
+    for (var p in value) {
+      if (ObjectHasOwnProperty.call(value, p)) {
+        var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
+        if (!IS_UNDEFINED(strP)) {
+          var member = QuoteJSONString(p) + ":";
+          if (gap != "") member += " ";
+          member += strP;
+          partial.push(member);
+        }
+      }
+    }
+  }
+  var final;
+  if (gap == "") {
+    final = "{" + partial.join(",") + "}";
+  } else if (partial.length > 0) {
+    var separator = ",\n" + indent;
+    final = "{\n" + indent + partial.join(separator) + "\n" +
+        stepback + "}";
+  } else {
+    final = "{}";
+  }
+  stack.pop();
+  return final;
+}
+
+function JSONSerialize(key, holder, replacer, stack, indent, gap) {
+  var value = holder[key];
+  if (IS_OBJECT(value) && value) {
+    var toJSON = value.toJSON;
+    if (IS_FUNCTION(toJSON))
+      value = toJSON.call(value, key);
+  }
+  if (IS_FUNCTION(replacer))
+    value = replacer.call(holder, key, value);
+  // Unwrap value if necessary
+  if (IS_OBJECT(value)) {
+    if (IS_NUMBER_WRAPPER(value)) {
+      value = $Number(value);
+    } else if (IS_STRING_WRAPPER(value)) {
+      value = $String(value);
+    }
+  }
+  switch (typeof value) {
+    case "string":
+      return QuoteJSONString(value);
+    case "object":
+      if (!value) {
+        return "null";
+      } else if (IS_ARRAY(value)) {
+        return SerializeArray(value, replacer, stack, indent, gap);
+      } else {
+        return SerializeObject(value, replacer, stack, indent, gap);
+      }
+    case "number":
+      return $isFinite(value) ? $String(value) : "null";
+    case "boolean":
+      return value ? "true" : "false";
+  }
+}
+
+function JSONStringify(value, replacer, space) {
+  var stack = [];
+  var indent = "";
+  if (IS_OBJECT(space)) {
+    // Unwrap 'space' if it is wrapped
+    if (IS_NUMBER_WRAPPER(space)) {
+      space = $Number(space);
+    } else if (IS_STRING_WRAPPER(space)) {
+      space = $String(space);
+    }
+  }
+  var gap;
+  if (IS_NUMBER(space)) {
+    space = $Math.min(space, 100);
+    gap = "";
+    for (var i = 0; i < space; i++)
+      gap += " ";
+  } else if (IS_STRING(space)) {
+    gap = space;
+  } else {
+    gap = "";
+  }
+  return JSONSerialize('', {'': value}, replacer, stack, indent, gap);
+}
+
+function SetupJSON() {
+  InstallFunctions($JSON, DONT_ENUM, $Array(
+    "parse", JSONParse,
+    "stringify", JSONStringify
+  ));
+}
+
+SetupJSON();
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 40241e6..89d11eb 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -43,10 +43,10 @@
 #include "regexp-stack.h"
 
 #ifdef ARM
-#include "regexp-macro-assembler-arm.h"
+#include "arm/regexp-macro-assembler-arm.h"
 #else  // IA32
-#include "macro-assembler-ia32.h"
-#include "regexp-macro-assembler-ia32.h"
+#include "ia32/macro-assembler-ia32.h"
+#include "ia32/regexp-macro-assembler-ia32.h"
 #endif
 
 #include "interpreter-irregexp.h"
diff --git a/src/macro-assembler.h b/src/macro-assembler.h
index 84a1eef..d21f479 100644
--- a/src/macro-assembler.h
+++ b/src/macro-assembler.h
@@ -30,20 +30,20 @@
 
 #ifdef ARM
 
-#include "constants-arm.h"
+#include "arm/constants-arm.h"
 #include "assembler.h"
-#include "assembler-arm.h"
-#include "assembler-arm-inl.h"
+#include "arm/assembler-arm.h"
+#include "arm/assembler-arm-inl.h"
 #include "code.h"  // must be after assembler_*.h
-#include "macro-assembler-arm.h"
+#include "arm/macro-assembler-arm.h"
 
 #else  // ia32
 
 #include "assembler.h"
-#include "assembler-ia32.h"
-#include "assembler-ia32-inl.h"
+#include "ia32/assembler-ia32.h"
+#include "ia32/assembler-ia32-inl.h"
 #include "code.h"  // must be after assembler_*.h
-#include "macro-assembler-ia32.h"
+#include "ia32/macro-assembler-ia32.h"
 
 #endif
 
diff --git a/src/macros.py b/src/macros.py
index d78ecd9..ebfd816 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -84,6 +84,8 @@
 macro IS_REGEXP(arg)            = %HasRegExpClass(arg);
 macro IS_ARRAY(arg)             = %HasArrayClass(arg);
 macro IS_DATE(arg)              = %HasDateClass(arg);
+macro IS_NUMBER_WRAPPER(arg)    = %HasNumberClass(arg);
+macro IS_STRING_WRAPPER(arg)    = %HasStringClass(arg);
 macro IS_ERROR(arg)             = (%ClassOf(arg) === 'Error');
 macro IS_SCRIPT(arg)            = (%ClassOf(arg) === 'Script');
 macro FLOOR(arg)                = %Math_floor(arg);
diff --git a/src/messages.js b/src/messages.js
index fa6fb1f..df8a2d1 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -114,6 +114,9 @@
   illegal_return:               "Illegal return statement",
   error_loading_debugger:       "Error loading debugger %0",
   no_input_to_regexp:           "No input to %0",
+  result_not_primitive:         "Result of %0 must be a primitive, was %1",
+  invalid_json:                 "String '%0' is not valid JSON",
+  circular_structure:           "Converting circular structure to JSON"
 };
 
 
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 635ef0f..e172014 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -558,8 +558,6 @@
   code()->ShortPrint();
   PrintF("\n - source code = ");
   GetSourceCode()->ShortPrint();
-  PrintF("\n - lazy load: %s",
-         lazy_load_data() == Heap::undefined_value() ? "no" : "yes");
   // Script files are often large, hard to read.
   // PrintF("\n - script =");
   // script()->Print();
@@ -579,7 +577,6 @@
   VerifyObjectField(kCodeOffset);
   VerifyObjectField(kInstanceClassNameOffset);
   VerifyObjectField(kExternalReferenceDataOffset);
-  VerifyObjectField(kLazyLoadDataOffset);
   VerifyObjectField(kScriptOffset);
   VerifyObjectField(kDebugInfoOffset);
 }
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 73b9c84..ff64d65 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1811,6 +1811,16 @@
 }
 
 
+byte Map::bit_field2() {
+  return READ_BYTE_FIELD(this, kBitField2Offset);
+}
+
+
+void Map::set_bit_field2(byte value) {
+  WRITE_BYTE_FIELD(this, kBitField2Offset, value);
+}
+
+
 void Map::set_non_instance_prototype(bool value) {
   if (value) {
     set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
@@ -2075,7 +2085,6 @@
           kInstanceClassNameOffset)
 ACCESSORS(SharedFunctionInfo, function_data, Object,
           kExternalReferenceDataOffset)
-ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
@@ -2141,8 +2150,8 @@
 }
 
 
-bool JSFunction::IsLoaded() {
-  return shared()->lazy_load_data() == Heap::undefined_value();
+bool JSObject::IsLoaded() {
+  return !map()->needs_loading();
 }
 
 
diff --git a/src/objects.cc b/src/objects.cc
index 31c5bab..55fc971 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -358,7 +358,7 @@
   Handle<Object> receiver_handle(receiver);
   Handle<String> name_handle(name);
   bool pending_exception;
-  LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+  LoadLazy(Handle<JSObject>(JSObject::cast(result->GetLazyValue())),
            &pending_exception);
   if (pending_exception) return Failure::Exception();
   return this_handle->GetPropertyWithReceiver(*receiver_handle,
@@ -377,7 +377,7 @@
   Handle<String> name_handle(name);
   Handle<Object> value_handle(value);
   bool pending_exception;
-  LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+  LoadLazy(Handle<JSObject>(JSObject::cast(result->GetLazyValue())),
            &pending_exception);
   if (pending_exception) return Failure::Exception();
   return this_handle->SetProperty(*name_handle, *value_handle, attributes);
@@ -389,7 +389,7 @@
   Handle<JSObject> this_handle(this);
   Handle<String> name_handle(name);
   bool pending_exception;
-  LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+  LoadLazy(Handle<JSObject>(JSObject::cast(result->GetLazyValue())),
            &pending_exception);
   if (pending_exception) return Failure::Exception();
   return this_handle->DeleteProperty(*name_handle);
@@ -1158,7 +1158,7 @@
          (index - map()->inobject_properties()) < properties()->length() ||
          map()->unused_property_fields() == 0);
   // Allocate a new map for the object.
-  Object* r = map()->Copy();
+  Object* r = map()->CopyDropDescriptors();
   if (r->IsFailure()) return r;
   Map* new_map = Map::cast(r);
   if (allow_map_transition) {
@@ -1203,7 +1203,7 @@
   if (new_descriptors->IsFailure()) return new_descriptors;
 
   // Allocate a new map for the object.
-  Object* new_map = map()->Copy();
+  Object* new_map = map()->CopyDropDescriptors();
   if (new_map->IsFailure()) return new_map;
 
   DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
@@ -1361,7 +1361,7 @@
       DescriptorArray::cast(descriptors_unchecked);
 
   // Make a new map for the object.
-  Object* new_map_unchecked = map()->Copy();
+  Object* new_map_unchecked = map()->CopyDropDescriptors();
   if (new_map_unchecked->IsFailure()) return new_map_unchecked;
   Map* new_map = Map::cast(new_map_unchecked);
   new_map->set_instance_descriptors(new_descriptors);
@@ -2032,7 +2032,7 @@
   dictionary->SetNextEnumerationIndex(index);
 
   // Allocate new map.
-  obj = map()->Copy();
+  obj = map()->CopyDropDescriptors();
   if (obj->IsFailure()) return obj;
   Map* new_map = Map::cast(obj);
 
@@ -2704,24 +2704,29 @@
 }
 
 
-Object* Map::Copy() {
+Object* Map::CopyDropDescriptors() {
   Object* result = Heap::AllocateMap(instance_type(), instance_size());
   if (result->IsFailure()) return result;
   Map::cast(result)->set_prototype(prototype());
   Map::cast(result)->set_constructor(constructor());
   // Don't copy descriptors, so map transitions always remain a forest.
+  // If we retained the same descriptors we would have two maps
+  // pointing to the same transition which is bad because the garbage
+  // collector relies on being able to reverse pointers from transitions
+  // to maps.  If properties need to be retained use CopyDropTransitions.
   Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array());
   // Please note instance_type and instance_size are set when allocated.
   Map::cast(result)->set_inobject_properties(inobject_properties());
   Map::cast(result)->set_unused_property_fields(unused_property_fields());
   Map::cast(result)->set_bit_field(bit_field());
+  Map::cast(result)->set_bit_field2(bit_field2());
   Map::cast(result)->ClearCodeCache();
   return result;
 }
 
 
 Object* Map::CopyDropTransitions() {
-  Object* new_map = Copy();
+  Object* new_map = CopyDropDescriptors();
   if (new_map->IsFailure()) return new_map;
   Object* descriptors = instance_descriptors()->RemoveTransitions();
   if (descriptors->IsFailure()) return descriptors;
@@ -7153,7 +7158,7 @@
 
   descriptors->Sort();
   // Allocate new map.
-  Object* new_map = obj->map()->Copy();
+  Object* new_map = obj->map()->CopyDropDescriptors();
   if (new_map->IsFailure()) return new_map;
 
   // Transform the object.
diff --git a/src/objects.h b/src/objects.h
index db3c449..8e76591 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1242,6 +1242,9 @@
                           String* name,
                           PropertyAttributes* attributes);
 
+  // Tells whether this object needs to be loaded.
+  inline bool IsLoaded();
+
   bool HasProperty(String* name) {
     return GetPropertyAttribute(name) != ABSENT;
   }
@@ -2397,6 +2400,10 @@
   inline byte bit_field();
   inline void set_bit_field(byte value);
 
+  // Bit field 2.
+  inline byte bit_field2();
+  inline void set_bit_field2(byte value);
+
   // Tells whether the object in the prototype property will be used
   // for instances created from this function.  If the prototype
   // property is set to a value that is not a JSObject, the prototype
@@ -2447,6 +2454,20 @@
     return ((1 << kIsUndetectable) & bit_field()) != 0;
   }
 
+  inline void set_needs_loading(bool value) {
+    if (value) {
+      set_bit_field2(bit_field2() | (1 << kNeedsLoading));
+    } else {
+      set_bit_field2(bit_field2() & ~(1 << kNeedsLoading));
+    }
+  }
+
+  // Does this object or function require a lazily loaded script to be
+  // run before being used?
+  inline bool needs_loading() {
+    return ((1 << kNeedsLoading) & bit_field2()) != 0;
+  }
+
   // Tells whether the instance has a call-as-function handler.
   inline void set_has_instance_call_handler() {
     set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
@@ -2474,7 +2495,7 @@
   DECL_ACCESSORS(code_cache, FixedArray)
 
   // Returns a copy of the map.
-  Object* Copy();
+  Object* CopyDropDescriptors();
 
   // Returns a copy of the map, with all transitions dropped from the
   // instance descriptors.
@@ -2550,7 +2571,7 @@
   static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
   static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
   static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
-  // The  byte at position 3 is not in use at the moment.
+  static const int kBitField2Offset = kInstanceAttributesOffset + 3;
 
   // Bit positions for bit field.
   static const int kUnused = 0;  // To be used for marking recently used maps.
@@ -2561,6 +2582,10 @@
   static const int kIsUndetectable = 5;
   static const int kHasInstanceCallHandler = 6;
   static const int kIsAccessCheckNeeded = 7;
+
+  // Bit positions for but field 2
+  static const int kNeedsLoading = 0;
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
 };
@@ -2677,10 +2702,6 @@
   // on objects.
   DECL_ACCESSORS(function_data, Object)
 
-  // [lazy load data]: If the function has lazy loading, this field
-  // contains contexts and other data needed to load it.
-  DECL_ACCESSORS(lazy_load_data, Object)
-
   // [script info]: Script from which the function originates.
   DECL_ACCESSORS(script, Object)
 
@@ -2754,9 +2775,7 @@
       kExpectedNofPropertiesOffset + kIntSize;
   static const int kExternalReferenceDataOffset =
       kInstanceClassNameOffset + kPointerSize;
-  static const int kLazyLoadDataOffset =
-      kExternalReferenceDataOffset + kPointerSize;
-  static const int kScriptOffset = kLazyLoadDataOffset + kPointerSize;
+  static const int kScriptOffset = kExternalReferenceDataOffset + kPointerSize;
   static const int kStartPositionAndTypeOffset = kScriptOffset + kPointerSize;
   static const int kEndPositionOffset = kStartPositionAndTypeOffset + kIntSize;
   static const int kFunctionTokenPositionOffset = kEndPositionOffset + kIntSize;
@@ -2809,9 +2828,6 @@
   // function.
   inline bool IsBoilerplate();
 
-  // Tells whether this function needs to be loaded.
-  inline bool IsLoaded();
-
   // [literals]: Fixed array holding the materialized literals.
   //
   // If the function contains object, regexp or array literals, the
diff --git a/src/property.h b/src/property.h
index 65d4a0d..60a9b54 100644
--- a/src/property.h
+++ b/src/property.h
@@ -245,14 +245,25 @@
   // Tells whether the value needs to be loaded.
   bool IsLoaded() {
     if (lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE) {
-      Object* value = GetValue();
-      if (value->IsJSFunction()) {
-        return JSFunction::cast(value)->IsLoaded();
-      }
+      Object* target = GetLazyValue();
+      return !target->IsJSObject() || JSObject::cast(target)->IsLoaded();
     }
     return true;
   }
 
+  Object* GetLazyValue() {
+    switch (type()) {
+      case FIELD:
+        return holder()->FastPropertyAt(GetFieldIndex());
+      case NORMAL:
+        return holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
+      case CONSTANT_FUNCTION:
+        return GetConstantFunction();
+      default:
+        return Smi::FromInt(0);
+    }
+  }
+
   Map* GetTransitionMap() {
     ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
     ASSERT(type() == MAP_TRANSITION);
diff --git a/src/runtime.cc b/src/runtime.cc
index 2b350a5..a1e23b4 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -4824,14 +4824,18 @@
 
 static Object* Runtime_CompileString(Arguments args) {
   HandleScope scope;
-  ASSERT(args.length() == 2);
+  ASSERT_EQ(3, args.length());
   CONVERT_ARG_CHECKED(String, source, 0);
   CONVERT_ARG_CHECKED(Smi, line_offset, 1);
+  CONVERT_ARG_CHECKED(Oddball, is_json, 2)
 
   // Compile source string in the global context.
   Handle<Context> context(Top::context()->global_context());
-  Handle<JSFunction> boilerplate =
-      Compiler::CompileEval(source, context, line_offset->value(), true);
+  Handle<JSFunction> boilerplate = Compiler::CompileEval(source,
+                                                         context,
+                                                         line_offset->value(),
+                                                         true,
+                                                         is_json->IsTrue());
   if (boilerplate.is_null()) return Failure::Exception();
   Handle<JSFunction> fun =
       Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -4856,7 +4860,7 @@
 
   // Compile source string in the current context.
   Handle<JSFunction> boilerplate =
-      Compiler::CompileEval(source, context, 0, is_global);
+      Compiler::CompileEval(source, context, 0, is_global, false);
   if (boilerplate.is_null()) return Failure::Exception();
   Handle<JSFunction> fun =
     Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -6479,7 +6483,8 @@
       Compiler::CompileEval(function_source,
                             context,
                             0,
-                            context->IsGlobalContext());
+                            context->IsGlobalContext(),
+                            false);
   if (boilerplate.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -6537,7 +6542,11 @@
 
   // Compile the source to be evaluated.
   Handle<JSFunction> boilerplate =
-      Handle<JSFunction>(Compiler::CompileEval(source, context, 0, true));
+      Handle<JSFunction>(Compiler::CompileEval(source,
+                                               context,
+                                               0,
+                                               true,
+                                               false));
   if (boilerplate.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
diff --git a/src/runtime.h b/src/runtime.h
index 6bd19f6..b29ce70 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -194,7 +194,7 @@
   F(NumberIsFinite, 1) \
   \
   /* Globals */ \
-  F(CompileString, 2) \
+  F(CompileString, 3) \
   F(GlobalPrint, 1) \
   \
   /* Eval */ \
diff --git a/src/string.js b/src/string.js
index 3ccad9a..c7a838e 100644
--- a/src/string.js
+++ b/src/string.js
@@ -812,6 +812,11 @@
 }
 
 
+function StringToJSON(key) {
+  return CheckJSONPrimitive(this.valueOf());
+}
+
+
 // -------------------------------------------------------------------
 
 function SetupString() {
@@ -858,7 +863,8 @@
     "small", StringSmall,
     "strike", StringStrike,
     "sub", StringSub,
-    "sup", StringSup
+    "sup", StringSup,
+    "toJSON", StringToJSON
   ));
 }
 
diff --git a/src/v8.cc b/src/v8.cc
index fbe3d5d..c0124e4 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -113,10 +113,6 @@
   Heap::TearDown();
   Logger::TearDown();
 
-#ifdef ENABLE_DEBUGGER_SUPPORT
-  Debugger::TearDown();
-#endif
-
   has_been_setup_ = false;
   has_been_disposed_ = true;
 }
diff --git a/src/v8natives.js b/src/v8natives.js
index 9772e2f..29a24b4 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -110,7 +110,7 @@
                          'be the global object from which eval originated');
   }
   
-  var f = %CompileString(x, 0);
+  var f = %CompileString(x, 0, false);
   if (!IS_FUNCTION(f)) return f;
 
   return f.call(this);
@@ -121,7 +121,7 @@
 function GlobalExecScript(expr, lang) {
   // NOTE: We don't care about the character casing.
   if (!lang || /javascript/i.test(lang)) {
-    var f = %CompileString(ToString(expr), 0);
+    var f = %CompileString(ToString(expr), 0, false);
     f.call(%GlobalReceiver(global));
   }
   return null;
@@ -312,13 +312,19 @@
 }
 
 
+function BooleanToJSON(key) {
+  return CheckJSONPrimitive(this.valueOf());
+}
+
+
 // ----------------------------------------------------------------------------
 
 
 function SetupBoolean() {
   InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
     "toString", BooleanToString,
-    "valueOf", BooleanValueOf
+    "valueOf", BooleanValueOf,
+    "toJSON", BooleanToJSON
   ));
 }
 
@@ -418,6 +424,18 @@
 }
 
 
+function CheckJSONPrimitive(val) {
+  if (!IsPrimitive(val))
+    throw MakeTypeError('result_not_primitive', ['toJSON', val]);
+  return val;
+}
+
+
+function NumberToJSON(key) {
+  return CheckJSONPrimitive(this.valueOf());
+}
+
+
 // ----------------------------------------------------------------------------
 
 function SetupNumber() {
@@ -455,7 +473,8 @@
     "valueOf", NumberValueOf,
     "toFixed", NumberToFixed,
     "toExponential", NumberToExponential,
-    "toPrecision", NumberToPrecision
+    "toPrecision", NumberToPrecision,
+    "toJSON", NumberToJSON
   ));
 }
 
@@ -521,7 +540,7 @@
 
   // The call to SetNewFunctionAttributes will ensure the prototype
   // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
-  var f = %CompileString(source, -1)();
+  var f = %CompileString(source, -1, false)();
   %FunctionSetName(f, "anonymous");
   return %SetNewFunctionAttributes(f);
 }
diff --git a/src/virtual-frame.cc b/src/virtual-frame.cc
index a03e31a..cef1d80 100644
--- a/src/virtual-frame.cc
+++ b/src/virtual-frame.cc
@@ -213,40 +213,14 @@
 }
 
 
-// Clear the dirty bits for the range of elements in
-// [min(stack_pointer_ + 1,begin), end).
-void VirtualFrame::SyncRange(int begin, int end) {
-  ASSERT(begin >= 0);
-  ASSERT(end <= elements_.length());
-  if (begin > stack_pointer_) {
-    // Elements between stack_pointer_ + 1 and begin must also be synced.
-    for (int i = stack_pointer_ + 1; i < end; i++) {
-      SyncElementByPushing(i);
-    }
-  } else if (end <= stack_pointer_ + 1) {
-    for (int i = begin; i < end; i++) {
-      if (!elements_[i].is_synced()) {
-          SyncElementBelowStackPointer(i);
-      }
-    }
-  } else {
-    // Split into two ranges that each satisfy a condition above.
-    SyncRange(begin, stack_pointer_ + 1);
-    SyncRange(stack_pointer_ + 1, end);
-  }
-}
-
-
 // Clear the dirty bit for the element at a given index.
 void VirtualFrame::SyncElementAt(int index) {
   if (index <= stack_pointer_) {
-    if (!elements_[index].is_synced()) {
-      SyncElementBelowStackPointer(index);
-    }
+    if (!elements_[index].is_synced()) SyncElementBelowStackPointer(index);
+  } else if (index == stack_pointer_ + 1) {
+    SyncElementByPushing(index);
   } else {
-    for (int i = stack_pointer_ + 1; i <= index; i++) {
-      SyncElementByPushing(i);
-    }
+    SyncRange(stack_pointer_ + 1, index);
   }
 }
 
@@ -310,7 +284,7 @@
   ASSERT(height() >= spilled_args);
   ASSERT(dropped_args <= spilled_args);
 
-  SyncRange(0, elements_.length());
+  SyncRange(0, elements_.length() - 1);
   // Spill registers.
   for (int i = 0; i < kNumRegisters; i++) {
     if (is_used(i)) {
diff --git a/src/virtual-frame.h b/src/virtual-frame.h
index 99b4f76..13e68b0 100644
--- a/src/virtual-frame.h
+++ b/src/virtual-frame.h
@@ -198,9 +198,9 @@
 } }  // namespace v8::internal
 
 #ifdef ARM
-#include "virtual-frame-arm.h"
+#include "arm/virtual-frame-arm.h"
 #else  // ia32
-#include "virtual-frame-ia32.h"
+#include "ia32/virtual-frame-ia32.h"
 #endif
 
 #endif  // V8_VIRTUAL_FRAME_H_