Version 3.12.7

Fixed lazy compilation for strict eval scopes. (Chromium issue 135066)

Made MACOSX_DEPLOYMENT_TARGET configurable in GYP. (issue 2151)

Report "hidden properties" in heap profiler for properties case. (issue 2212)

Activated optimization of packed arrays by default.

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@11978 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index cd6ee92..adabfc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2012-07-03: Version 3.12.7
+
+        Fixed lazy compilation for strict eval scopes.
+        (Chromium issue 135066)
+
+        Made MACOSX_DEPLOYMENT_TARGET configurable in GYP.
+        (issue 2151)
+
+        Report "hidden properties" in heap profiler for properties case.
+        (issue 2212)
+
+        Activated optimization of packed arrays by default.
+
+        Performance and stability improvements on all platforms.
+
+
 2012-06-29: Version 3.12.6
 
         Cleaned up hardfp ABI detection for ARM (V8 issue 2140).
diff --git a/Makefile b/Makefile
index 9a17d6b..d0cfd81 100644
--- a/Makefile
+++ b/Makefile
@@ -35,6 +35,7 @@
 TESTFLAGS ?=
 ANDROID_NDK_ROOT ?=
 ANDROID_TOOL_PREFIX = $(ANDROID_NDK_ROOT)/toolchain/bin/arm-linux-androideabi
+ANDROID_V8 ?= /data/local/v8
 
 # Special build flags. Use them like this: "make library=shared"
 
@@ -107,7 +108,7 @@
 # - every combination <arch>.<mode>, e.g. "ia32.release"
 # - "native": current host's architecture, release mode
 # - any of the above with .check appended, e.g. "ia32.release.check"
-# - "android": cross-compile for Android/ARM (release mode)
+# - "android": cross-compile for Android/ARM
 # - default (no target specified): build all DEFAULT_ARCHES and MODES
 # - "check": build all targets and run all tests
 # - "<arch>.clean" for any <arch> in ARCHES
@@ -120,6 +121,7 @@
 ARCHES = ia32 x64 arm mips
 DEFAULT_ARCHES = ia32 x64 arm
 MODES = release debug
+ANDROID_MODES = android.release android.debug
 
 # List of files that trigger Makefile regeneration:
 GYPFILES = build/all.gyp build/common.gypi build/standalone.gypi \
@@ -166,8 +168,9 @@
 	         CXX="$(CXX)" LINK="$(LINK)" BUILDTYPE=Release \
 	         builddir="$(shell pwd)/$(OUTDIR)/$@"
 
-# TODO(jkummerow): add "android.debug" when we need it.
-android android.release: $(OUTDIR)/Makefile.android
+android: $(ANDROID_MODES)
+
+$(ANDROID_MODES): $(OUTDIR)/Makefile.android
 	@$(MAKE) -C "$(OUTDIR)" -f Makefile.android \
 	        CXX="$(ANDROID_TOOL_PREFIX)-g++" \
 	        AR="$(ANDROID_TOOL_PREFIX)-ar" \
@@ -175,8 +178,9 @@
 	        CC="$(ANDROID_TOOL_PREFIX)-gcc" \
 	        LD="$(ANDROID_TOOL_PREFIX)-ld" \
 	        LINK="$(ANDROID_TOOL_PREFIX)-g++" \
-	        BUILDTYPE=Release \
-	        builddir="$(shell pwd)/$(OUTDIR)/android.release"
+	        BUILDTYPE=$(shell echo $(subst .,,$(suffix $@)) | \
+	                    python -c "print raw_input().capitalize()") \
+	        builddir="$(shell pwd)/$(OUTDIR)/$@"
 
 # Test targets.
 check: all
@@ -196,6 +200,17 @@
 	@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) \
 	    --arch-and-mode=$(basename $@) $(TESTFLAGS)
 
+$(addsuffix .sync, $(ANDROID_MODES)): $$(basename $$@)
+	@tools/android-sync.sh $(basename $@) $(OUTDIR) \
+	                       $(shell pwd) $(ANDROID_V8)
+
+$(addsuffix .check, $(ANDROID_MODES)): $$(basename $$@).sync
+	@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) \
+	     --arch-and-mode=$(basename $@) \
+	     --special-command="tools/android-run.py @"
+
+android.check: android.release.check android.debug.check
+
 native.check: native
 	@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR)/native \
 	    --arch-and-mode=. $(TESTFLAGS)
diff --git a/build/standalone.gypi b/build/standalone.gypi
index ebdf557..72883ae 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -33,6 +33,7 @@
     'component%': 'static_library',
     'visibility%': 'hidden',
     'msvs_multi_core_compile%': '1',
+    'mac_deployment_target%': '10.5',
     'variables': {
       'variables': {
         'variables': {
@@ -191,7 +192,8 @@
           'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES',    # -Werror
           'GCC_VERSION': '4.2',
           'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES',  # -Wnewline-eof
-          'MACOSX_DEPLOYMENT_TARGET': '10.4',       # -mmacosx-version-min=10.4
+          # MACOSX_DEPLOYMENT_TARGET maps to -mmacosx-version-min
+          'MACOSX_DEPLOYMENT_TARGET': '<(mac_deployment_target)',
           'PREBINDING': 'NO',                       # No -Wl,-prebind
           'SYMROOT': '<(DEPTH)/xcodebuild',
           'USE_HEADERMAP': 'NO',
diff --git a/src/ast.cc b/src/ast.cc
index 8ac139f..52f452b 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -1048,7 +1048,6 @@
 REGULAR_NODE(Literal)
 REGULAR_NODE(ObjectLiteral)
 REGULAR_NODE(RegExpLiteral)
-REGULAR_NODE(ArrayLiteral)
 REGULAR_NODE(Assignment)
 REGULAR_NODE(Throw)
 REGULAR_NODE(Property)
@@ -1078,6 +1077,7 @@
 DONT_OPTIMIZE_NODE(DebuggerStatement)
 DONT_OPTIMIZE_NODE(SharedFunctionInfoLiteral)
 
+DONT_INLINE_NODE(ArrayLiteral)  // TODO(1322): Allow materialized literals.
 DONT_INLINE_NODE(FunctionLiteral)
 
 DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 125d151..98a4fce 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -152,7 +152,7 @@
 DEFINE_implication(harmony_modules, harmony_scoping)
 
 // Flags for experimental implementation features.
-DEFINE_bool(packed_arrays, false, "optimizes arrays that have no holes")
+DEFINE_bool(packed_arrays, true, "optimizes arrays that have no holes")
 DEFINE_bool(smi_only_arrays, true, "tracks arrays with only smi values")
 DEFINE_bool(clever_optimizations,
             true,
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 0766760..ee3d6b5 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -5748,16 +5748,31 @@
                                                            HValue* dependency,
                                                            Handle<Map> map,
                                                            bool is_store) {
-  HInstruction* mapcheck =
-      AddInstruction(new(zone()) HCheckMaps(object, map, zone(), dependency));
+  HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
+                                                zone(), dependency);
+  AddInstruction(mapcheck);
+  if (dependency) {
+    mapcheck->ClearGVNFlag(kDependsOnElementsKind);
+  }
+  return BuildUncheckedMonomorphicElementAccess(object, key, val,
+                                                mapcheck, map, is_store);
+}
+
+
+HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
+    HValue* object,
+    HValue* key,
+    HValue* val,
+    HCheckMaps* mapcheck,
+    Handle<Map> map,
+    bool is_store) {
   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
   // on a HElementsTransition instruction. The flag can also be removed if the
   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
   // ElementsKind transitions. Finally, the dependency can be removed for stores
   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
   // generated store code.
-  if (dependency ||
-      (map->elements_kind() == FAST_HOLEY_ELEMENTS) ||
+  if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) ||
       (map->elements_kind() == FAST_ELEMENTS && is_store)) {
     mapcheck->ClearGVNFlag(kDependsOnElementsKind);
   }
@@ -5796,6 +5811,59 @@
 }
 
 
+HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad(
+    HValue* object,
+    HValue* key,
+    HValue* val,
+    SmallMapList* maps) {
+  // For polymorphic loads of similar elements kinds (i.e. all tagged or all
+  // double), always use the "worst case" code without a transition.  This is
+  // much faster than transitioning the elements to the worst case, trading a
+  // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
+  bool has_double_maps = false;
+  bool has_smi_or_object_maps = false;
+  bool has_js_array_access = false;
+  bool has_non_js_array_access = false;
+  Handle<Map> most_general_consolidated_map;
+  for (int i = 0; i < maps->length(); ++i) {
+    Handle<Map> map = maps->at(i);
+    // Don't allow mixing of JSArrays with JSObjects.
+    if (map->instance_type() == JS_ARRAY_TYPE) {
+      if (has_non_js_array_access) return NULL;
+      has_js_array_access = true;
+    } else if (has_js_array_access) {
+      return NULL;
+    } else {
+      has_non_js_array_access = true;
+    }
+    // Don't allow mixed, incompatible elements kinds.
+    if (map->has_fast_double_elements()) {
+      if (has_smi_or_object_maps) return NULL;
+      has_double_maps = true;
+    } else if (map->has_fast_smi_or_object_elements()) {
+      if (has_double_maps) return NULL;
+      has_smi_or_object_maps = true;
+    } else {
+      return NULL;
+    }
+    // Remember the most general elements kind, the code for its load will
+    // properly handle all of the more specific cases.
+    if ((i == 0) || IsMoreGeneralElementsKindTransition(
+            most_general_consolidated_map->elements_kind(),
+            map->elements_kind())) {
+      most_general_consolidated_map = map;
+    }
+  }
+  if (!has_double_maps && !has_smi_or_object_maps) return NULL;
+
+  HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone());
+  AddInstruction(check_maps);
+  HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
+      object, key, val, check_maps, most_general_consolidated_map, false);
+  return instr;
+}
+
+
 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
                                                       HValue* key,
                                                       HValue* val,
@@ -5809,6 +5877,17 @@
   SmallMapList* maps = prop->GetReceiverTypes();
   bool todo_external_array = false;
 
+  if (!is_store) {
+    HInstruction* consolidated_load =
+        TryBuildConsolidatedElementLoad(object, key, val, maps);
+    if (consolidated_load != NULL) {
+      AddInstruction(consolidated_load);
+      *has_side_effects |= consolidated_load->HasObservableSideEffects();
+      consolidated_load->set_position(position);
+      return consolidated_load;
+    }
+  }
+
   static const int kNumElementTypes = kElementsKindCount;
   bool type_todo[kNumElementTypes];
   for (int i = 0; i < kNumElementTypes; ++i) {
diff --git a/src/hydrogen.h b/src/hydrogen.h
index abaa440..b9f2300 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1101,12 +1101,25 @@
                                        ElementsKind elements_kind,
                                        bool is_store);
 
+  HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
+                                                HValue* key,
+                                                HValue* val,
+                                                SmallMapList* maps);
+
+  HInstruction* BuildUncheckedMonomorphicElementAccess(HValue* object,
+                                                       HValue* key,
+                                                       HValue* val,
+                                                       HCheckMaps* mapcheck,
+                                                       Handle<Map> map,
+                                                       bool is_store);
+
   HInstruction* BuildMonomorphicElementAccess(HValue* object,
                                               HValue* key,
                                               HValue* val,
                                               HValue* dependency,
                                               Handle<Map> map,
                                               bool is_store);
+
   HValue* HandlePolymorphicElementAccess(HValue* object,
                                          HValue* key,
                                          HValue* val,
diff --git a/src/liveedit.cc b/src/liveedit.cc
index 80e18bb..0b8654b 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -965,12 +965,21 @@
 
 
 // Finds all references to original and replaces them with substitution.
-static void ReplaceCodeObject(Code* original, Code* substitution) {
-  ASSERT(!HEAP->InNewSpace(substitution));
+static void ReplaceCodeObject(Handle<Code> original,
+                              Handle<Code> substitution) {
+  // Perform a full GC in order to ensure that we are not in the middle of an
+  // incremental marking phase when we are replacing the code object.
+  // Since we are not in an incremental marking phase we can write pointers
+  // to code objects (that are never in new space) without worrying about
+  // write barriers.
+  HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
+                          "liveedit.cc ReplaceCodeObject");
+
+  ASSERT(!HEAP->InNewSpace(*substitution));
 
   AssertNoAllocation no_allocations_please;
 
-  ReplacingVisitor visitor(original, substitution);
+  ReplacingVisitor visitor(*original, *substitution);
 
   // Iterate over all roots. Stack frames may have pointer into original code,
   // so temporary replace the pointers with offset numbers
@@ -1066,8 +1075,8 @@
 
   if (IsJSFunctionCode(shared_info->code())) {
     Handle<Code> code = compile_info_wrapper.GetFunctionCode();
-    ReplaceCodeObject(shared_info->code(), *code);
-    Handle<Object> code_scope_info =  compile_info_wrapper.GetCodeScopeInfo();
+    ReplaceCodeObject(Handle<Code>(shared_info->code()), code);
+    Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
     if (code_scope_info->IsFixedArray()) {
       shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
     }
@@ -1309,7 +1318,7 @@
       // on stack (it is safe to substitute the code object on stack, because
       // we only change the structure of rinfo and leave instructions
       // untouched).
-      ReplaceCodeObject(info->code(), *patched_code);
+      ReplaceCodeObject(Handle<Code>(info->code()), patched_code);
     }
   }
 
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 217046f..847cff5 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -2182,16 +2182,31 @@
       switch (descs->GetType(i)) {
         case FIELD: {
           int index = descs->GetFieldIndex(i);
+
+          String* k = descs->GetKey(i);
           if (index < js_obj->map()->inobject_properties()) {
-            SetPropertyReference(
-                js_obj, entry,
-                descs->GetKey(i), js_obj->InObjectPropertyAt(index),
-                NULL,
-                js_obj->GetInObjectPropertyOffset(index));
+            Object* value = js_obj->InObjectPropertyAt(index);
+            if (k != heap_->hidden_symbol()) {
+              SetPropertyReference(
+                  js_obj, entry,
+                  k, value,
+                  NULL,
+                  js_obj->GetInObjectPropertyOffset(index));
+            } else {
+              TagObject(value, "(hidden properties)");
+              SetInternalReference(
+                  js_obj, entry,
+                  "hidden_properties", value,
+                  js_obj->GetInObjectPropertyOffset(index));
+            }
           } else {
-            SetPropertyReference(
-                js_obj, entry,
-                descs->GetKey(i), js_obj->FastPropertyAt(index));
+            Object* value = js_obj->FastPropertyAt(index);
+            if (k != heap_->hidden_symbol()) {
+              SetPropertyReference(js_obj, entry, k, value);
+            } else {
+              TagObject(value, "(hidden properties)");
+              SetInternalReference(js_obj, entry, "hidden_properties", value);
+            }
           }
           break;
         }
@@ -2237,7 +2252,7 @@
         Object* value = target->IsJSGlobalPropertyCell()
             ? JSGlobalPropertyCell::cast(target)->value()
             : target;
-        if (String::cast(k)->length() > 0) {
+        if (k != heap_->hidden_symbol()) {
           SetPropertyReference(js_obj, entry, String::cast(k), value);
         } else {
           TagObject(value, "(hidden properties)");
diff --git a/src/scopes.cc b/src/scopes.cc
index faedb5f..b0fd10e 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -662,9 +662,31 @@
 }
 
 
+bool Scope::HasLazyCompilableOuterContext() const {
+  Scope* outer = outer_scope_;
+  if (outer == NULL) return true;
+  // There are several reasons that prevent lazy compilation:
+  // - This scope is inside a with scope and all declaration scopes between
+  //   them have empty contexts. Such declaration scopes become invisible
+  //   during scope info deserialization.
+  // - This scope is inside a strict eval scope with variables that are
+  //   potentially context allocated in an artificial function scope that
+  //   is not deserialized correctly.
+  outer = outer->DeclarationScope();
+  bool found_non_trivial_declarations = false;
+  for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) {
+    if (scope->is_eval_scope()) return false;
+    if (scope->is_with_scope() && !found_non_trivial_declarations) return false;
+    if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) {
+      found_non_trivial_declarations = true;
+    }
+  }
+  return true;
+}
+
+
 bool Scope::AllowsLazyCompilation() const {
-  return !force_eager_compilation_ &&
-         !TrivialDeclarationScopesBeforeWithScope();
+  return !force_eager_compilation_ && HasLazyCompilableOuterContext();
 }
 
 
@@ -673,20 +695,6 @@
 }
 
 
-bool Scope::TrivialDeclarationScopesBeforeWithScope() const {
-  Scope* outer = outer_scope_;
-  if (outer == NULL) return false;
-  outer = outer->DeclarationScope();
-  while (outer != NULL) {
-    if (outer->is_with_scope()) return true;
-    if (outer->is_declaration_scope() && outer->num_heap_slots() > 0)
-      return false;
-    outer = outer->outer_scope_;
-  }
-  return false;
-}
-
-
 int Scope::ContextChainLength(Scope* scope) {
   int n = 0;
   for (Scope* s = this; s != scope; s = s->outer_scope_) {
diff --git a/src/scopes.h b/src/scopes.h
index 2868cde..42339a9 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -380,10 +380,8 @@
   // True if the outer context of this scope is always the global context.
   bool HasTrivialOuterContext() const;
 
-  // True if this scope is inside a with scope and all declaration scopes
-  // between them have empty contexts. Such declaration scopes become
-  // invisible during scope info deserialization.
-  bool TrivialDeclarationScopesBeforeWithScope() const;
+  // True if the outer context allows lazy compilation of this scope.
+  bool HasLazyCompilableOuterContext() const;
 
   // The number of contexts between this and scope; zero if this == scope.
   int ContextChainLength(Scope* scope);
diff --git a/src/v8threads.cc b/src/v8threads.cc
index fd8d536..32ea5e1 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2012 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:
@@ -238,12 +238,18 @@
 ThreadState::ThreadState(ThreadManager* thread_manager)
     : id_(ThreadId::Invalid()),
       terminate_on_restore_(false),
+      data_(NULL),
       next_(this),
       previous_(this),
       thread_manager_(thread_manager) {
 }
 
 
+ThreadState::~ThreadState() {
+  DeleteArray<char>(data_);
+}
+
+
 void ThreadState::AllocateSpace() {
   data_ = NewArray<char>(ArchiveSpacePerThread());
 }
@@ -306,8 +312,19 @@
 
 ThreadManager::~ThreadManager() {
   delete mutex_;
-  delete free_anchor_;
-  delete in_use_anchor_;
+  DeleteThreadStateList(free_anchor_);
+  DeleteThreadStateList(in_use_anchor_);
+}
+
+
+void ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
+  // The list starts and ends with the anchor.
+  for (ThreadState* current = anchor->next_; current != anchor;) {
+    ThreadState* next = current->next_;
+    delete current;
+    current = next;
+  }
+  delete anchor;
 }
 
 
diff --git a/src/v8threads.h b/src/v8threads.h
index a2aee4e..8dce860 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2012 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:
@@ -57,6 +57,7 @@
 
  private:
   explicit ThreadState(ThreadManager* thread_manager);
+  ~ThreadState();
 
   void AllocateSpace();
 
@@ -114,6 +115,8 @@
   ThreadManager();
   ~ThreadManager();
 
+  void DeleteThreadStateList(ThreadState* anchor);
+
   void EagerlyArchiveThread();
 
   Mutex* mutex_;
diff --git a/src/version.cc b/src/version.cc
index d5a287d..4f42c99 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     12
-#define BUILD_NUMBER      6
+#define BUILD_NUMBER      7
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index fc111ab..a2fa0aa 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -54,7 +54,7 @@
 test-weakmaps/Shrinking: FAIL
 
 ##############################################################################
-[ $arch == arm ]
+[ $arch == arm || $arch == android ]
 
 # We cannot assume that we can throw OutOfMemory exceptions in all situations.
 # Apparently our ARM box is in such a state. Skip the test as it also runs for
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index e74a312..59113e0 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -1449,6 +1449,36 @@
   CHECK_NE(NULL, setterFunction);
 }
 
+TEST(HiddenPropertiesFastCase) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun(
+      "function C(x) { this.a = this; this.b = x; }\n"
+      "c = new C(2012);\n");
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8_str("HiddenPropertiesFastCase1"));
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  const v8::HeapGraphNode* c =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "c");
+  CHECK_NE(NULL, c);
+  const v8::HeapGraphNode* hidden_props =
+      GetProperty(c, v8::HeapGraphEdge::kInternal, "hidden_properties");
+  CHECK_EQ(NULL, hidden_props);
+
+  v8::Handle<v8::Value> cHandle = env->Global()->Get(v8::String::New("c"));
+  CHECK(!cHandle.IsEmpty() && cHandle->IsObject());
+  cHandle->ToObject()->GetIdentityHash();
+
+  snapshot = v8::HeapProfiler::TakeSnapshot(
+      v8_str("HiddenPropertiesFastCase2"));
+  global = GetGlobalObject(snapshot);
+  c = GetProperty(global, v8::HeapGraphEdge::kProperty, "c");
+  CHECK_NE(NULL, c);
+  hidden_props = GetProperty(c, v8::HeapGraphEdge::kInternal,
+      "hidden_properties");
+  CHECK_NE(NULL, hidden_props);
+}
 
 bool HasWeakEdge(const v8::HeapGraphNode* node) {
   for (int i = 0; i < node->GetChildrenCount(); ++i) {
diff --git a/test/cctest/testcfg.py b/test/cctest/testcfg.py
index f1387e8..532edfc 100644
--- a/test/cctest/testcfg.py
+++ b/test/cctest/testcfg.py
@@ -93,7 +93,8 @@
       if utils.IsWindows():
         executable += '.exe'
       executable = join(self.context.buildspace, executable)
-    output = test.Execute([executable, '--list'], self.context)
+    full_command = self.context.processor([executable, '--list'])
+    output = test.Execute(full_command, self.context)
     if output.exit_code != 0:
       print output.stdout
       print output.stderr
diff --git a/test/mjsunit/external-array.js b/test/mjsunit/external-array.js
index 37dc7a0..3d5ffdb 100644
--- a/test/mjsunit/external-array.js
+++ b/test/mjsunit/external-array.js
@@ -540,3 +540,28 @@
 assertThrows(function(){ a.subarray.call({}, 0) });
 assertThrows(function(){ a.subarray.call([], 0) });
 assertThrows(function(){ a.subarray.call(a) });
+
+
+// Call constructors directly as functions, and through .call and .apply
+
+b = ArrayBuffer(100)
+a = Int8Array(b, 5, 77)
+assertInstance(b, ArrayBuffer)
+assertInstance(a, Int8Array)
+assertSame(b, a.buffer)
+assertEquals(5, a.byteOffset)
+assertEquals(77, a.byteLength)
+b = ArrayBuffer.call(null, 10)
+a = Uint16Array.call(null, b, 2, 4)
+assertInstance(b, ArrayBuffer)
+assertInstance(a, Uint16Array)
+assertSame(b, a.buffer)
+assertEquals(2, a.byteOffset)
+assertEquals(8, a.byteLength)
+b = ArrayBuffer.apply(null, [1000])
+a = Float32Array.apply(null, [b, 128, 1])
+assertInstance(b, ArrayBuffer)
+assertInstance(a, Float32Array)
+assertSame(b, a.buffer)
+assertEquals(128, a.byteOffset)
+assertEquals(4, a.byteLength)
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 2d54cf0..e14a543 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -49,28 +49,27 @@
 ##############################################################################
 # This one uses a built-in that's only present in debug mode. It takes
 # too long to run in debug mode on ARM and MIPS.
-fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm || $arch == mips)
+fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm || $arch == android || $arch == mips)
 
-big-object-literal: PASS, SKIP if ($arch == arm)
+big-object-literal: PASS, SKIP if ($arch == arm || $arch == android)
 
 # Issue 488: this test sometimes times out.
 array-constructor: PASS || TIMEOUT
 
 # Very slow on ARM and MIPS, contains no architecture dependent code.
-unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch == mips)
+unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch == android || $arch == mips)
 
 # Test Crankshaft compilation time.  Expected to take too long in debug mode.
 regress/regress-1969: PASS, SKIP if $mode == debug
 
 ##############################################################################
-[ $isolates ]
-
 # This test sets the umask on a per-process basis and hence cannot be
 # used in multi-threaded runs.
-d8-os: SKIP
+# On android there is no /tmp directory.
+d8-os: PASS, SKIP if ($isolates || $arch == android)
 
 ##############################################################################
-[ $arch == arm ]
+[ $arch == arm || $arch == android ]
 
 # Slow tests which times out in debug mode.
 try: PASS, SKIP if $mode == debug
diff --git a/test/mjsunit/regress/regress-crbug-135066.js b/test/mjsunit/regress/regress-crbug-135066.js
new file mode 100644
index 0000000..1aeca8b
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-135066.js
@@ -0,0 +1,53 @@
+// Copyright 2012 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.
+
+// Filler long enough to trigger lazy parsing.
+var filler = "//" + new Array(1024).join('x');
+
+// Test strict eval in global context.
+eval(
+  "'use strict';" +
+  "var x = 23;" +
+  "var f = function bozo1() {" +
+  "  return x;" +
+  "};" +
+  "assertSame(23, f());" +
+  filler
+);
+
+// Test default eval in strict context.
+(function() {
+  "use strict";
+  eval(
+    "var y = 42;" +
+    "var g = function bozo2() {" +
+    "  return y;" +
+    "};" +
+    "assertSame(42, g());" +
+    filler
+  );
+})();
diff --git a/test/mjsunit/typed-array-slice.js b/test/mjsunit/typed-array-slice.js
new file mode 100644
index 0000000..c6e7e94
--- /dev/null
+++ b/test/mjsunit/typed-array-slice.js
@@ -0,0 +1,61 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * 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.
+
+// Flags: --allow-natives-syntax
+
+// This is a regression test for overlapping key and value registers.
+
+var types = [Array, Int8Array, Uint8Array, Int16Array, Uint16Array,
+             Int32Array, Uint32Array, Uint8ClampedArray, Float32Array,
+             Float64Array];
+
+var results1 = [-2, -2, 254, -2, 65534, -2, 4294967294, 0, -2, -2];
+var results2 = [undefined, -1, 255, -1, 65535, -1, 4294967295, 0, -1, -1];
+var results3 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+var results4 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+
+const kElementCount = 40;
+
+function do_slice(a) {
+  return Array.prototype.slice.call(a, 4, 8);
+}
+
+for (var t = 0; t < types.length; t++) {
+  var type = types[t];
+  var a = new type(kElementCount);
+  for (var i = 0; i < kElementCount; ++i ) {
+    a[i] = i-6;
+  }
+  delete a[5];
+  var sliced = do_slice(a);
+
+  %ClearFunctionTypeFeedback(do_slice);
+  assertEquals(results1[t], sliced[0]);
+  assertEquals(results2[t], sliced[1]);
+  assertEquals(results3[t], sliced[2]);
+  assertEquals(results4[t], sliced[3]);
+}
diff --git a/tools/android-run.py b/tools/android-run.py
new file mode 100644
index 0000000..881630a
--- /dev/null
+++ b/tools/android-run.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+
+# This script executes the passed command line on Android device
+# using 'adb shell' command. Unfortunately, 'adb shell' always
+# returns exit code 0, ignoring the exit code of executed command.
+# Since we need to return non-zero exit code if the command failed,
+# we augment the passed command line with exit code checking statement
+# and output special error string in case of non-zero exit code.
+# Then we parse the output of 'adb shell' and look for that error string.
+
+import os
+from os.path import join, dirname, abspath
+import subprocess
+import sys
+import tempfile
+
+def Check(output, errors):
+  failed = any([s.startswith('/system/bin/sh:') or s.startswith('Error')
+                for s in output.split('\n')])
+  return 1 if failed else 0
+
+def Execute(cmdline):
+  (fd_out, outname) = tempfile.mkstemp()
+  (fd_err, errname) = tempfile.mkstemp()
+  process = subprocess.Popen(
+    args=cmdline,
+    shell=True,
+    stdout=fd_out,
+    stderr=fd_err,
+  )
+  exit_code = process.wait()
+  os.close(fd_out)
+  os.close(fd_err)
+  output = file(outname).read()
+  errors = file(errname).read()
+  os.unlink(outname)
+  os.unlink(errname)
+  sys.stdout.write(output)
+  sys.stderr.write(errors)
+  return exit_code or Check(output, errors)
+
+def Escape(arg):
+  def ShouldEscape():
+    for x in arg:
+      if not x.isalnum() and x != '-' and x != '_':
+        return True
+    return False
+
+  return arg if not ShouldEscape() else '"%s"' % (arg.replace('"', '\\"'))
+
+def WriteToTemporaryFile(data):
+  (fd, fname) = tempfile.mkstemp()
+  os.close(fd)
+  tmp_file = open(fname, "w")
+  tmp_file.write(data)
+  tmp_file.close()
+  return fname
+
+def Main():
+  if (len(sys.argv) == 1):
+    print("Usage: %s <command-to-run-on-device>" % sys.argv[0])
+    return 1
+  workspace = abspath(join(dirname(sys.argv[0]), '..'))
+  android_workspace = os.getenv("ANDROID_V8", "/data/local/v8")
+  args = [Escape(arg) for arg in sys.argv[1:]]
+  script = (" ".join(args) + "\n"
+            "if [ $? -ne 0 ]\n"
+            "  then echo \"Error returned by test\";\n"
+            "fi\n")
+  script = script.replace(workspace, android_workspace)
+  script_file = WriteToTemporaryFile(script)
+  android_script_file = android_workspace + "/" + script_file
+  command =  ("adb push '%s' %s;" % (script_file, android_script_file) +
+              "adb shell 'sh %s';" % android_script_file +
+              "adb shell 'rm %s'" % android_script_file)
+  error_code = Execute(command)
+  os.unlink(script_file)
+  return error_code
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/tools/android-sync.sh b/tools/android-sync.sh
new file mode 100644
index 0000000..90fa318
--- /dev/null
+++ b/tools/android-sync.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# Copyright 2012 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.
+
+# This script pushes android binaries and test data to the device.
+# The first argument can be either "android.release" or "android.debug".
+# The second argument is a relative path to the output directory with binaries.
+# The third argument is the absolute path to the V8 directory on the host.
+# The fourth argument is the absolute path to the V8 directory on the device.
+
+if [ ${#@} -lt 4 ] ; then
+  echo "Error: need 4 arguments"
+  exit 1
+fi
+
+ARCH_MODE=$1
+OUTDIR=$2
+HOST_V8=$3
+ANDROID_V8=$4
+
+function sync_file {
+  local FILE=$1
+  local ANDROID_HASH=$(adb shell "md5 \"$ANDROID_V8/$FILE\"")
+  local HOST_HASH=$(md5sum "$HOST_V8/$FILE")
+  if [ "${ANDROID_HASH%% *}" != "${HOST_HASH%% *}" ]; then
+    adb push "$HOST_V8/$FILE" "$ANDROID_V8/$FILE" &> /dev/null
+  fi
+  echo -n "."
+}
+
+function sync_dir {
+  local DIR=$1
+  echo -n "sync to $ANDROID_V8/$DIR"
+  for FILE in $(find "$HOST_V8/$DIR" -type f); do
+    local RELATIVE_FILE=${FILE:${#HOST_V8}}
+    sync_file "$RELATIVE_FILE"
+  done
+  echo ""
+}
+
+echo -n "sync to $ANDROID_V8/$OUTDIR/$ARCH_MODE"
+sync_file "$OUTDIR/$ARCH_MODE/cctest"
+sync_file "$OUTDIR/$ARCH_MODE/d8"
+sync_file "$OUTDIR/$ARCH_MODE/preparser"
+echo ""
+echo -n "sync to $ANDROID_V8/tools"
+sync_file tools/consarray.js
+sync_file tools/codemap.js
+sync_file tools/csvparser.js
+sync_file tools/profile.js
+sync_file tools/splaytree.js
+echo ""
+sync_dir test/message
+sync_dir test/mjsunit
+sync_dir test/preparser
diff --git a/tools/test-wrapper-gypbuild.py b/tools/test-wrapper-gypbuild.py
index 6de021b..5d3c7e4 100755
--- a/tools/test-wrapper-gypbuild.py
+++ b/tools/test-wrapper-gypbuild.py
@@ -148,7 +148,7 @@
       print "Unknown mode %s" % mode
       return False
   for arch in options.arch:
-    if not arch in ['ia32', 'x64', 'arm', 'mips']:
+    if not arch in ['ia32', 'x64', 'arm', 'mips', 'android']:
       print "Unknown architecture %s" % arch
       return False
   if options.buildbot:
diff --git a/tools/test.py b/tools/test.py
index 5131ad7..d3bfb5b 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -140,9 +140,9 @@
   parts = []
   for part in command:
     if ' ' in part:
-      # Escape spaces.  We may need to escape more characters for this
-      # to work properly.
-      parts.append('"%s"' % part)
+      # Escape spaces and double quotes. We may need to escape more characters
+      # for this to work properly.
+      parts.append('"%s"' % part.replace('"', '\\"'))
     else:
       parts.append(part)
   return " ".join(parts)
@@ -1283,7 +1283,7 @@
     options.scons_flags.append("arch=" + options.arch)
   # Simulators are slow, therefore allow a longer default timeout.
   if options.timeout == -1:
-    if options.arch == 'arm' or options.arch == 'mips':
+    if options.arch in ['android', 'arm', 'mips']:
       options.timeout = 2 * TIMEOUT_DEFAULT;
     else:
       options.timeout = TIMEOUT_DEFAULT;