Version 3.24.15

Introduce an API mirroring the gc extension.

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@18575 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 61dc8e3..2311051 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-01-14: Version 3.24.15
+
+        Introduce an API mirroring the gc extension.
+
+        Performance and stability improvements on all platforms.
+
+
 2014-01-10: Version 3.24.14
 
         ES6: Add Object.getOwnPropertySymbols (issue 3049).
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 71907be..fe15157 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -61,15 +61,11 @@
 def _SkipTreeCheck(input_api, output_api):
   """Check the env var whether we want to skip tree check.
      Only skip if src/version.cc has been updated."""
-  print "skip tree check?", input_api.environ.get('PRESUBMIT_TREE_CHECK')
   src_version = 'src/version.cc'
-  def FilterFile(file):
-    print "Changed file:", file.LocalPath()
-    return file.LocalPath() == src_version
-  if not input_api.AffectedSourceFiles(FilterFile):
+  FilterFile = lambda file: file.LocalPath() == src_version
+  if not input_api.AffectedSourceFiles(
+      lambda file: file.LocalPath() == src_version):
     return False
-  if input_api.environ.get('PRESUBMIT_TREE_CHECK') == 'skip':
-    print "Skip tree check requested via environment variable."
   return input_api.environ.get('PRESUBMIT_TREE_CHECK') == 'skip'
 
 
@@ -98,7 +94,6 @@
   results.extend(input_api.canned_checks.CheckChangeHasDescription(
       input_api, output_api))
   if not _SkipTreeCheck(input_api, output_api):
-    print "Checking if tree is open."
     results.extend(input_api.canned_checks.CheckTreeIsOpen(
         input_api, output_api,
         json_url='http://v8-status.appspot.com/current?format=json'))
diff --git a/include/v8.h b/include/v8.h
index c56295a..d186752 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -945,16 +945,6 @@
   /**
    * Pre-compiles the specified script (context-independent).
    *
-   * \param input Pointer to UTF-8 script source code.
-   * \param length Length of UTF-8 script source code.
-   */
-  static ScriptData* PreCompile(Isolate* isolate,
-                                const char* input,
-                                int length);
-
-  /**
-   * Pre-compiles the specified script (context-independent).
-   *
    * NOTE: Pre-compilation using this method cannot happen on another thread
    * without using Lockers.
    *
@@ -3903,7 +3893,8 @@
 enum GCCallbackFlags {
   kNoGCCallbackFlags = 0,
   kGCCallbackFlagCompacted = 1 << 0,
-  kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1
+  kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1,
+  kGCCallbackFlagForced = 1 << 2
 };
 
 typedef void (*GCPrologueCallback)(GCType type, GCCallbackFlags flags);
@@ -3973,6 +3964,15 @@
   };
 
   /**
+   * Types of garbage collections that can be requested via
+   * RequestGarbageCollectionForTesting.
+   */
+  enum GarbageCollectionType {
+    kFullGarbageCollection,
+    kMinorGarbageCollection
+  };
+
+  /**
    * Creates a new isolate.  Does not change the currently entered
    * isolate.
    *
@@ -4184,6 +4184,17 @@
    */
   void ClearInterrupt();
 
+  /**
+   * Request garbage collection in this Isolate. It is only valid to call this
+   * function if --expose_gc was specified.
+   *
+   * This should only be used for testing purposes and not to enforce a garbage
+   * collection schedule. It has strong negative impact on the garbage
+   * collection performance. Use IdleNotification() or LowMemoryNotification()
+   * instead to influence the garbage collection schedule.
+   */
+  void RequestGarbageCollectionForTesting(GarbageCollectionType type);
+
  private:
   Isolate();
   Isolate(const Isolate&);
diff --git a/src/api.cc b/src/api.cc
index db2045f..5ef6e59 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -121,9 +121,9 @@
 #define API_ENTRY_CHECK(isolate, msg)                                          \
   do {                                                                         \
     if (v8::Locker::IsActive()) {                                              \
-      ApiCheck(isolate->thread_manager()->IsLockedByCurrentThread(),           \
-               msg,                                                            \
-               "Entering the V8 API without proper locking in place");         \
+      Utils::ApiCheck(isolate->thread_manager()->IsLockedByCurrentThread(),    \
+                      msg,                                                     \
+                      "Entering the V8 API without proper locking in place");  \
     }                                                                          \
   } while (false)
 
@@ -143,15 +143,6 @@
 }
 
 
-static FatalErrorCallback GetFatalErrorHandler() {
-  i::Isolate* isolate = i::Isolate::Current();
-  if (isolate->exception_behavior() == NULL) {
-    isolate->set_exception_behavior(DefaultFatalErrorHandler);
-  }
-  return isolate->exception_behavior();
-}
-
-
 void i::FatalProcessOutOfMemory(const char* location) {
   i::V8::FatalProcessOutOfMemory(location, false);
 }
@@ -221,21 +212,19 @@
     // HeapIterator here without doing a special GC.
     isolate->heap()->RecordStats(&heap_stats, false);
   }
-  isolate->SignalFatalError();
-  FatalErrorCallback callback = GetFatalErrorHandler();
-  const char* message = "Allocation failed - process out of memory";
-  callback(location, message);
-  // If the callback returns, we stop execution.
+  Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
+  // If the fatal error handler returns, we stop execution.
   FATAL("API fatal error handler returned after process out of memory");
 }
 
 
-bool Utils::ReportApiFailure(const char* location, const char* message) {
-  FatalErrorCallback callback = GetFatalErrorHandler();
-  callback(location, message);
+void Utils::ReportApiFailure(const char* location, const char* message) {
   i::Isolate* isolate = i::Isolate::Current();
+  FatalErrorCallback callback = isolate->exception_behavior() == NULL
+      ? DefaultFatalErrorHandler
+      : isolate->exception_behavior();
+  callback(location, message);
   isolate->SignalFatalError();
-  return false;
 }
 
 
@@ -245,20 +234,6 @@
 }
 
 
-static inline bool ApiCheck(bool condition,
-                            const char* location,
-                            const char* message) {
-  return condition ? true : Utils::ReportApiFailure(location, message);
-}
-
-
-static bool ReportEmptyHandle(const char* location) {
-  FatalErrorCallback callback = GetFatalErrorHandler();
-  callback(location, "Reading from empty handle");
-  return true;
-}
-
-
 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
   if (!isolate->IsInitialized()) return false;
   if (isolate->has_scheduled_exception()) {
@@ -269,16 +244,6 @@
 }
 
 
-static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
-  return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
-}
-
-
-static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
-  return (obj == 0) ? ReportEmptyHandle(location) : false;
-}
-
-
 // --- S t a t i c s ---
 
 
@@ -295,11 +260,10 @@
 
 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
                                                const char* location) {
-  if (isolate != NULL) {
-    if (isolate->IsInitialized()) return true;
-  }
-  ASSERT(isolate == i::Isolate::Current());
-  return ApiCheck(InitializeHelper(isolate), location, "Error initializing V8");
+  return (isolate != NULL && isolate->IsInitialized()) ||
+      Utils::ApiCheck(InitializeHelper(isolate),
+                      location,
+                      "Error initializing V8");
 }
 
 
@@ -519,11 +483,11 @@
 
 
 ResourceConstraints::ResourceConstraints()
-  : max_young_space_size_(0),
-    max_old_space_size_(0),
-    max_executable_size_(0),
-    stack_limit_(NULL),
-    max_available_threads_(0) { }
+    : max_young_space_size_(0),
+      max_old_space_size_(0),
+      max_executable_size_(0),
+      stack_limit_(NULL),
+      max_available_threads_(0) { }
 
 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
                                             uint32_t number_of_processors) {
@@ -688,9 +652,9 @@
 
 
 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
-  ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(),
-           "EscapeableHandleScope::Escape",
-           "Escape value set twice");
+  Utils::ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(),
+                  "EscapeableHandleScope::Escape",
+                  "Escape value set twice");
   if (escape_value == NULL) {
     *escape_slot_ = isolate_->heap()->undefined_value();
     return NULL;
@@ -714,27 +678,25 @@
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   i::Handle<i::Context> context = i::Handle<i::Context>::null();
   ENTER_V8(isolate);
-  if (!ApiCheck(isolate->handle_scope_implementer()->LeaveContext(context),
-                "v8::Context::Exit()",
-                "Cannot exit non-entered context")) {
+  i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
+  if (!Utils::ApiCheck(impl->LeaveContext(context),
+                       "v8::Context::Exit()",
+                       "Cannot exit non-entered context")) {
     return;
   }
-  // Content of 'last_context' could be NULL.
-  i::Context* last_context =
-      isolate->handle_scope_implementer()->RestoreContext();
-  isolate->set_context(last_context);
+  isolate->set_context(impl->RestoreContext());
 }
 
 
 static void* DecodeSmiToAligned(i::Object* value, const char* location) {
-  ApiCheck(value->IsSmi(), location, "Not a Smi");
+  Utils::ApiCheck(value->IsSmi(), location, "Not a Smi");
   return reinterpret_cast<void*>(value);
 }
 
 
 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
   i::Smi* smi = reinterpret_cast<i::Smi*>(value);
-  ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
+  Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
   return smi;
 }
 
@@ -745,13 +707,14 @@
                                                 const char* location) {
   i::Handle<i::Context> env = Utils::OpenHandle(context);
   bool ok =
-      ApiCheck(env->IsNativeContext(), location, "Not a native context") &&
-      ApiCheck(index >= 0, location, "Negative index");
+      Utils::ApiCheck(env->IsNativeContext(),
+                      location,
+                      "Not a native context") &&
+      Utils::ApiCheck(index >= 0, location, "Negative index");
   if (!ok) return i::Handle<i::FixedArray>();
   i::Handle<i::FixedArray> data(env->embedder_data());
   if (index < data->length()) return data;
-  if (!can_grow) {
-    Utils::ReportApiFailure(location, "Index too large");
+  if (!Utils::ApiCheck(can_grow, location, "Index too large")) {
     return i::Handle<i::FixedArray>();
   }
   int new_size = i::Max(index, data->length() << 1) + 1;
@@ -899,9 +862,9 @@
   const int kSize = 3;
   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   v8::Handle<v8::Data> data[kSize] = {
-      name,
-      value,
-      v8::Integer::New(v8_isolate, attribute)};
+    name,
+    value,
+    v8::Integer::New(v8_isolate, attribute)};
   TemplateSet(isolate, this, kSize, data);
 }
 
@@ -920,18 +883,18 @@
   const int kSize = 5;
   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   v8::Handle<v8::Data> data[kSize] = {
-      name,
-      getter,
-      setter,
-      v8::Integer::New(v8_isolate, attribute),
-      v8::Integer::New(v8_isolate, access_control)};
+    name,
+    getter,
+    setter,
+    v8::Integer::New(v8_isolate, attribute),
+    v8::Integer::New(v8_isolate, access_control)};
   TemplateSet(isolate, this, kSize, data);
 }
 
 
 // --- F u n c t i o n   T e m p l a t e ---
 static void InitializeFunctionTemplate(
-      i::Handle<i::FunctionTemplateInfo> info) {
+    i::Handle<i::FunctionTemplateInfo> info) {
   info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
   info->set_flag(0);
 }
@@ -1031,8 +994,8 @@
 
 
 Local<AccessorSignature> AccessorSignature::New(
-      Isolate* isolate,
-      Handle<FunctionTemplate> receiver) {
+    Isolate* isolate,
+    Handle<FunctionTemplate> receiver) {
   return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
 }
 
@@ -1047,7 +1010,7 @@
       i::Handle<i::DeclaredAccessorDescriptor>();
   if (previous_descriptor != NULL) {
     previous = Utils::OpenHandle(
-      static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
+        static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
   }
   i::Handle<i::DeclaredAccessorDescriptor> descriptor =
       i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
@@ -1056,7 +1019,7 @@
 
 
 Local<RawOperationDescriptor>
-  ObjectOperationDescriptor::NewInternalFieldDereference(
+ObjectOperationDescriptor::NewInternalFieldDereference(
     Isolate* isolate,
     int internal_field) {
   i::DeclaredAccessorDescriptorData data;
@@ -1191,9 +1154,9 @@
 }
 
 
-#define SET_FIELD_WRAPPED(obj, setter, cdata) do {    \
-    i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata);  \
-    (obj)->setter(*foreign);                          \
+#define SET_FIELD_WRAPPED(obj, setter, cdata) do {                      \
+    i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
+    (obj)->setter(*foreign);                                            \
   } while (false)
 
 
@@ -1235,13 +1198,13 @@
 
 template<typename Getter, typename Setter>
 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
-      v8::Handle<String> name,
-      Getter getter,
-      Setter setter,
-      v8::Handle<Value> data,
-      v8::AccessControl settings,
-      v8::PropertyAttribute attributes,
-      v8::Handle<AccessorSignature> signature) {
+    v8::Handle<String> name,
+    Getter getter,
+    Setter setter,
+    v8::Handle<Value> data,
+    v8::AccessControl settings,
+    v8::PropertyAttribute attributes,
+    v8::Handle<AccessorSignature> signature) {
   i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
   i::Handle<i::ExecutableAccessorInfo> obj =
       isolate->factory()->NewExecutableAccessorInfo();
@@ -1256,13 +1219,13 @@
 
 
 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
-      v8::Handle<String> name,
-      v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
-      void* setter_ignored,
-      void* data_ignored,
-      v8::AccessControl settings,
-      v8::PropertyAttribute attributes,
-      v8::Handle<AccessorSignature> signature) {
+    v8::Handle<String> name,
+    v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
+    void* setter_ignored,
+    void* data_ignored,
+    v8::AccessControl settings,
+    v8::PropertyAttribute attributes,
+    v8::Handle<AccessorSignature> signature) {
   i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
   if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
   i::Handle<i::DeclaredAccessorInfo> obj =
@@ -1274,8 +1237,11 @@
 
 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  if (EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
+  if (!Utils::ApiCheck(this != NULL,
+                       "v8::FunctionTemplate::InstanceTemplate()",
+                       "Reading from empty handle")) {
     return Local<ObjectTemplate>();
+  }
   ENTER_V8(isolate);
   i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this);
   if (handle->instance_template()->IsUndefined()) {
@@ -1338,8 +1304,8 @@
 
 
 Local<ObjectTemplate> ObjectTemplate::New(
-      i::Isolate* isolate,
-      v8::Handle<FunctionTemplate> constructor) {
+    i::Isolate* isolate,
+    v8::Handle<FunctionTemplate> constructor) {
   EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
   LOG_API(isolate, "ObjectTemplate::New");
   ENTER_V8(isolate);
@@ -1508,10 +1474,10 @@
 
 
 void ObjectTemplate::SetAccessCheckCallbacks(
-      NamedSecurityCallback named_callback,
-      IndexedSecurityCallback indexed_callback,
-      Handle<Value> data,
-      bool turned_on_by_default) {
+    NamedSecurityCallback named_callback,
+    IndexedSecurityCallback indexed_callback,
+    Handle<Value> data,
+    bool turned_on_by_default) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
@@ -1539,12 +1505,12 @@
 
 
 void ObjectTemplate::SetIndexedPropertyHandler(
-      IndexedPropertyGetterCallback getter,
-      IndexedPropertySetterCallback setter,
-      IndexedPropertyQueryCallback query,
-      IndexedPropertyDeleterCallback remover,
-      IndexedPropertyEnumeratorCallback enumerator,
-      Handle<Value> data) {
+    IndexedPropertyGetterCallback getter,
+    IndexedPropertySetterCallback setter,
+    IndexedPropertyQueryCallback query,
+    IndexedPropertyDeleterCallback remover,
+    IndexedPropertyEnumeratorCallback enumerator,
+    Handle<Value> data) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
@@ -1600,9 +1566,9 @@
 
 void ObjectTemplate::SetInternalFieldCount(int value) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  if (!ApiCheck(i::Smi::IsValid(value),
-                "v8::ObjectTemplate::SetInternalFieldCount()",
-                "Invalid internal field count")) {
+  if (!Utils::ApiCheck(i::Smi::IsValid(value),
+                       "v8::ObjectTemplate::SetInternalFieldCount()",
+                       "Invalid internal field count")) {
     return;
   }
   ENTER_V8(isolate);
@@ -1619,22 +1585,12 @@
 // --- S c r i p t D a t a ---
 
 
-ScriptData* ScriptData::PreCompile(v8::Isolate* isolate,
-                                   const char* input,
-                                   int length) {
-  i::Utf8ToUtf16CharacterStream stream(
-      reinterpret_cast<const unsigned char*>(input), length);
-  return i::PreParserApi::PreParse(
-      reinterpret_cast<i::Isolate*>(isolate), &stream);
-}
-
-
 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
   i::Handle<i::String> str = Utils::OpenHandle(*source);
   i::Isolate* isolate = str->GetIsolate();
   if (str->IsExternalTwoByteString()) {
     i::ExternalTwoByteStringUtf16CharacterStream stream(
-      i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
+        i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
     return i::PreParserApi::PreParse(isolate, &stream);
   } else {
     i::GenericStringUtf16CharacterStream stream(str, 0, str->length());
@@ -1711,16 +1667,16 @@
       pre_data_impl = NULL;
     }
     i::Handle<i::SharedFunctionInfo> result =
-      i::Compiler::CompileScript(str,
-                                 name_obj,
-                                 line_offset,
-                                 column_offset,
-                                 is_shared_cross_origin,
-                                 isolate->global_context(),
-                                 NULL,
-                                 pre_data_impl,
-                                 Utils::OpenHandle(*script_data, true),
-                                 i::NOT_NATIVES_CODE);
+        i::Compiler::CompileScript(str,
+                                   name_obj,
+                                   line_offset,
+                                   column_offset,
+                                   is_shared_cross_origin,
+                                   isolate->global_context(),
+                                   NULL,
+                                   pre_data_impl,
+                                   Utils::OpenHandle(*script_data, true),
+                                   i::NOT_NATIVES_CODE);
     has_pending_exception = result.is_null();
     EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
     raw_result = *result;
@@ -2425,23 +2381,23 @@
 }
 
 
-#define TYPED_ARRAY_LIST(F) \
-F(Uint8Array, kExternalUnsignedByteArray) \
-F(Int8Array, kExternalByteArray) \
-F(Uint16Array, kExternalUnsignedShortArray) \
-F(Int16Array, kExternalShortArray) \
-F(Uint32Array, kExternalUnsignedIntArray) \
-F(Int32Array, kExternalIntArray) \
-F(Float32Array, kExternalFloatArray) \
-F(Float64Array, kExternalDoubleArray) \
-F(Uint8ClampedArray, kExternalPixelArray)
+#define TYPED_ARRAY_LIST(F)                     \
+  F(Uint8Array, kExternalUnsignedByteArray)     \
+  F(Int8Array, kExternalByteArray)              \
+  F(Uint16Array, kExternalUnsignedShortArray)   \
+  F(Int16Array, kExternalShortArray)            \
+  F(Uint32Array, kExternalUnsignedIntArray)     \
+  F(Int32Array, kExternalIntArray)              \
+  F(Float32Array, kExternalFloatArray)          \
+  F(Float64Array, kExternalDoubleArray)         \
+  F(Uint8ClampedArray, kExternalPixelArray)
 
 
-#define VALUE_IS_TYPED_ARRAY(TypedArray, type_const)                          \
-  bool Value::Is##TypedArray() const {                                        \
-    i::Handle<i::Object> obj = Utils::OpenHandle(this);                       \
-    if (!obj->IsJSTypedArray()) return false;                                 \
-    return i::JSTypedArray::cast(*obj)->type() == type_const;                 \
+#define VALUE_IS_TYPED_ARRAY(TypedArray, type_const)            \
+  bool Value::Is##TypedArray() const {                          \
+    i::Handle<i::Object> obj = Utils::OpenHandle(this);         \
+    if (!obj->IsJSTypedArray()) return false;                   \
+    return i::JSTypedArray::cast(*obj)->type() == type_const;   \
   }
 
 TYPED_ARRAY_LIST(VALUE_IS_TYPED_ARRAY)
@@ -2490,9 +2446,9 @@
   if (obj->IsNumber()) {
     double value = obj->Number();
     return !i::IsMinusZero(value) &&
-           value >= 0 &&
-           value <= i::kMaxUInt32 &&
-           value == i::FastUI2D(i::FastD2UI(value));
+        value >= 0 &&
+        value <= i::kMaxUInt32 &&
+        value == i::FastUI2D(i::FastD2UI(value));
   }
   return false;
 }
@@ -2544,7 +2500,7 @@
   if (!constr->IsJSFunction()) return false;
   i::JSFunction* func = i::JSFunction::cast(constr);
   return func->shared()->native() &&
-         constr == LookupBuiltin(isolate, class_name);
+      constr == LookupBuiltin(isolate, class_name);
 }
 
 
@@ -2681,106 +2637,108 @@
 
 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
-  ApiCheck(isolate != NULL && isolate->IsInitialized() && !isolate->IsDead(),
-           "v8::internal::Internals::CheckInitialized()",
-           "Isolate is not initialized or V8 has died");
+  Utils::ApiCheck(isolate != NULL &&
+                  isolate->IsInitialized() &&
+                  !isolate->IsDead(),
+                  "v8::internal::Internals::CheckInitialized()",
+                  "Isolate is not initialized or V8 has died");
 }
 
 
 void External::CheckCast(v8::Value* that) {
-  ApiCheck(Utils::OpenHandle(that)->IsExternal(),
-           "v8::External::Cast()",
-           "Could not convert to external");
+  Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(),
+                  "v8::External::Cast()",
+                  "Could not convert to external");
 }
 
 
 void v8::Object::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSObject(),
-           "v8::Object::Cast()",
-           "Could not convert to object");
+  Utils::ApiCheck(obj->IsJSObject(),
+                  "v8::Object::Cast()",
+                  "Could not convert to object");
 }
 
 
 void v8::Function::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSFunction(),
-           "v8::Function::Cast()",
-           "Could not convert to function");
+  Utils::ApiCheck(obj->IsJSFunction(),
+                  "v8::Function::Cast()",
+                  "Could not convert to function");
 }
 
 
 void v8::String::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsString(),
-           "v8::String::Cast()",
-           "Could not convert to string");
+  Utils::ApiCheck(obj->IsString(),
+                  "v8::String::Cast()",
+                  "Could not convert to string");
 }
 
 
 void v8::Symbol::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsSymbol(),
-           "v8::Symbol::Cast()",
-           "Could not convert to symbol");
+  Utils::ApiCheck(obj->IsSymbol(),
+                  "v8::Symbol::Cast()",
+                  "Could not convert to symbol");
 }
 
 
 void v8::Number::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsNumber(),
-           "v8::Number::Cast()",
-           "Could not convert to number");
+  Utils::ApiCheck(obj->IsNumber(),
+                  "v8::Number::Cast()",
+                  "Could not convert to number");
 }
 
 
 void v8::Integer::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsNumber(),
-           "v8::Integer::Cast()",
-           "Could not convert to number");
+  Utils::ApiCheck(obj->IsNumber(),
+                  "v8::Integer::Cast()",
+                  "Could not convert to number");
 }
 
 
 void v8::Array::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSArray(),
-           "v8::Array::Cast()",
-           "Could not convert to array");
+  Utils::ApiCheck(obj->IsJSArray(),
+                  "v8::Array::Cast()",
+                  "Could not convert to array");
 }
 
 
 void v8::ArrayBuffer::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSArrayBuffer(),
-           "v8::ArrayBuffer::Cast()",
-           "Could not convert to ArrayBuffer");
+  Utils::ApiCheck(obj->IsJSArrayBuffer(),
+                  "v8::ArrayBuffer::Cast()",
+                  "Could not convert to ArrayBuffer");
 }
 
 
 void v8::ArrayBufferView::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSArrayBufferView(),
-           "v8::ArrayBufferView::Cast()",
-           "Could not convert to ArrayBufferView");
+  Utils::ApiCheck(obj->IsJSArrayBufferView(),
+                  "v8::ArrayBufferView::Cast()",
+                  "Could not convert to ArrayBufferView");
 }
 
 
 void v8::TypedArray::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSTypedArray(),
-           "v8::TypedArray::Cast()",
-           "Could not convert to TypedArray");
+  Utils::ApiCheck(obj->IsJSTypedArray(),
+                  "v8::TypedArray::Cast()",
+                  "Could not convert to TypedArray");
 }
 
 
-#define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst)                         \
-  void v8::ApiClass::CheckCast(Value* that) {                               \
-    i::Handle<i::Object> obj = Utils::OpenHandle(that);                     \
-    ApiCheck(obj->IsJSTypedArray() &&                                       \
-             i::JSTypedArray::cast(*obj)->type() == typeConst,              \
-             "v8::" #ApiClass "::Cast()",                                   \
-             "Could not convert to " #ApiClass);                            \
+#define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst)                     \
+  void v8::ApiClass::CheckCast(Value* that) {                           \
+    i::Handle<i::Object> obj = Utils::OpenHandle(that);                 \
+    Utils::ApiCheck(obj->IsJSTypedArray() &&                            \
+                    i::JSTypedArray::cast(*obj)->type() == typeConst,   \
+                    "v8::" #ApiClass "::Cast()",                        \
+                    "Could not convert to " #ApiClass);                 \
   }
 
 
@@ -2791,62 +2749,62 @@
 
 void v8::DataView::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSDataView(),
-           "v8::DataView::Cast()",
-           "Could not convert to DataView");
+  Utils::ApiCheck(obj->IsJSDataView(),
+                  "v8::DataView::Cast()",
+                  "Could not convert to DataView");
 }
 
 
 void v8::Date::CheckCast(v8::Value* that) {
   i::Isolate* isolate = i::Isolate::Current();
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()),
-           "v8::Date::Cast()",
-           "Could not convert to date");
+  Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()),
+                  "v8::Date::Cast()",
+                  "Could not convert to date");
 }
 
 
 void v8::StringObject::CheckCast(v8::Value* that) {
   i::Isolate* isolate = i::Isolate::Current();
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()),
-           "v8::StringObject::Cast()",
-           "Could not convert to StringObject");
+  Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()),
+                  "v8::StringObject::Cast()",
+                  "Could not convert to StringObject");
 }
 
 
 void v8::SymbolObject::CheckCast(v8::Value* that) {
   i::Isolate* isolate = i::Isolate::Current();
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
-           "v8::SymbolObject::Cast()",
-           "Could not convert to SymbolObject");
+  Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
+                  "v8::SymbolObject::Cast()",
+                  "Could not convert to SymbolObject");
 }
 
 
 void v8::NumberObject::CheckCast(v8::Value* that) {
   i::Isolate* isolate = i::Isolate::Current();
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()),
-           "v8::NumberObject::Cast()",
-           "Could not convert to NumberObject");
+  Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()),
+                  "v8::NumberObject::Cast()",
+                  "Could not convert to NumberObject");
 }
 
 
 void v8::BooleanObject::CheckCast(v8::Value* that) {
   i::Isolate* isolate = i::Isolate::Current();
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
-           "v8::BooleanObject::Cast()",
-           "Could not convert to BooleanObject");
+  Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
+                  "v8::BooleanObject::Cast()",
+                  "Could not convert to BooleanObject");
 }
 
 
 void v8::RegExp::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsJSRegExp(),
-           "v8::RegExp::Cast()",
-           "Could not convert to regular expression");
+  Utils::ApiCheck(obj->IsJSRegExp(),
+                  "v8::RegExp::Cast()",
+                  "Could not convert to regular expression");
 }
 
 
@@ -2978,8 +2936,9 @@
 
 bool Value::Equals(Handle<Value> that) const {
   i::Isolate* isolate = i::Isolate::Current();
-  if (EmptyCheck("v8::Value::Equals()", this) ||
-      EmptyCheck("v8::Value::Equals()", that)) {
+  if (!Utils::ApiCheck(this != NULL && !that.IsEmpty(),
+                       "v8::Value::Equals()",
+                       "Reading from empty handle")) {
     return false;
   }
   LOG_API(isolate, "Equals");
@@ -3004,8 +2963,9 @@
 
 bool Value::StrictEquals(Handle<Value> that) const {
   i::Isolate* isolate = i::Isolate::Current();
-  if (EmptyCheck("v8::Value::StrictEquals()", this) ||
-      EmptyCheck("v8::Value::StrictEquals()", that)) {
+  if (!Utils::ApiCheck(this != NULL && !that.IsEmpty(),
+                       "v8::Value::StrictEquals()",
+                       "Reading from empty handle")) {
     return false;
   }
   LOG_API(isolate, "StrictEquals");
@@ -3024,7 +2984,7 @@
     return other->IsNumber() && obj->Number() == other->Number();
   } else if (obj->IsString()) {
     return other->IsString() &&
-      i::String::cast(*obj)->Equals(i::String::cast(*other));
+        i::String::cast(*obj)->Equals(i::String::cast(*other));
   } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
     return other->IsUndefined() || other->IsUndetectableObject();
   } else {
@@ -3035,8 +2995,9 @@
 
 bool Value::SameValue(Handle<Value> that) const {
   i::Isolate* isolate = i::Isolate::Current();
-  if (EmptyCheck("v8::Value::SameValue()", this) ||
-      EmptyCheck("v8::Value::SameValue()", that)) {
+  if (!Utils::ApiCheck(this != NULL && !that.IsEmpty(),
+                       "v8::Value::SameValue()",
+                       "Reading from empty handle")) {
     return false;
   }
   LOG_API(isolate, "SameValue");
@@ -3559,7 +3520,7 @@
 
 
 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
-      Handle<String> key) {
+    Handle<String> key) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ON_BAILOUT(isolate,
              "v8::Object::GetRealNamedPropertyInPrototypeChain()",
@@ -3772,15 +3733,16 @@
   ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  if (!ApiCheck(length >= 0 && length <= i::ExternalPixelArray::kMaxLength,
-                "v8::Object::SetIndexedPropertiesToPixelData()",
-                "length exceeds max acceptable value")) {
+  if (!Utils::ApiCheck(length >= 0 &&
+                       length <= i::ExternalPixelArray::kMaxLength,
+                       "v8::Object::SetIndexedPropertiesToPixelData()",
+                       "length exceeds max acceptable value")) {
     return;
   }
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  if (!ApiCheck(!self->IsJSArray(),
-                "v8::Object::SetIndexedPropertiesToPixelData()",
-                "JSArray is not supported")) {
+  if (!Utils::ApiCheck(!self->IsJSArray(),
+                       "v8::Object::SetIndexedPropertiesToPixelData()",
+                       "JSArray is not supported")) {
     return;
   }
   PrepareExternalArrayElements(self, data, kExternalPixelArray, length);
@@ -3828,15 +3790,15 @@
   ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  if (!ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
-                "v8::Object::SetIndexedPropertiesToExternalArrayData()",
-                "length exceeds max acceptable value")) {
+  if (!Utils::ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
+                       "v8::Object::SetIndexedPropertiesToExternalArrayData()",
+                       "length exceeds max acceptable value")) {
     return;
   }
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  if (!ApiCheck(!self->IsJSArray(),
-                "v8::Object::SetIndexedPropertiesToExternalArrayData()",
-                "JSArray is not supported")) {
+  if (!Utils::ApiCheck(!self->IsJSArray(),
+                       "v8::Object::SetIndexedPropertiesToExternalArrayData()",
+                       "JSArray is not supported")) {
     return;
   }
   PrepareExternalArrayElements(self, data, array_type, length);
@@ -4000,7 +3962,7 @@
   ENTER_V8(isolate);
   return FunctionTemplateNew(
       isolate, callback, data, Local<Signature>(), length, true)->
-          GetFunction();
+      GetFunction();
 }
 
 
@@ -4083,7 +4045,7 @@
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
              return ToApiHandle<Primitive>(
-                isolate->factory()->undefined_value()));
+                 isolate->factory()->undefined_value()));
   ENTER_V8(isolate);
   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
   i::Handle<i::String> property_name =
@@ -4109,9 +4071,9 @@
     i::Handle<i::Object> scriptName = GetScriptNameOrSourceURL(script);
     v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate());
     v8::ScriptOrigin origin(
-      Utils::ToLocal(scriptName),
-      v8::Integer::New(isolate, script->line_offset()->value()),
-      v8::Integer::New(isolate, script->column_offset()->value()));
+        Utils::ToLocal(scriptName),
+        v8::Integer::New(isolate, script->line_offset()->value()),
+        v8::Integer::New(isolate, script->column_offset()->value()));
     return origin;
   }
   return v8::ScriptOrigin(Handle<Value>());
@@ -4198,7 +4160,7 @@
 
 static inline const uint16_t* Align(const uint16_t* chars) {
   return reinterpret_cast<uint16_t*>(
-    reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
+      reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
 }
 
 class ContainsOnlyOneByteHelper {
@@ -4218,7 +4180,7 @@
     // Align to uintptr_t.
     const uint16_t* end = chars + length;
     while (Unaligned(chars) && chars != end) {
-        acc |= *chars++;
+      acc |= *chars++;
     }
     // Read word aligned in blocks,
     // checking the return value at the end of each block.
@@ -4322,8 +4284,8 @@
   class Visitor {
    public:
     inline explicit Visitor()
-      : utf8_length_(0),
-        state_(kInitialState) {}
+        : utf8_length_(0),
+          state_(kInitialState) {}
 
     void VisitOneByteString(const uint8_t* chars, int length) {
       int utf8_length = 0;
@@ -4396,7 +4358,7 @@
     if (!(*state & kRightmostEdgeIsCalculated)) {
       ASSERT(!(*state & kRightmostEdgeIsSurrogate));
       *state |= (kRightmostEdgeIsCalculated
-          | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
+                 | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
     } else if (edge_surrogate && StartsWithSurrogate(*state)) {
       *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
     }
@@ -4503,13 +4465,13 @@
  public:
   Utf8WriterVisitor(
       char* buffer, int capacity, bool skip_capacity_check)
-    : early_termination_(false),
-      last_character_(unibrow::Utf16::kNoPreviousCharacter),
-      buffer_(buffer),
-      start_(buffer),
-      capacity_(capacity),
-      skip_capacity_check_(capacity == -1 || skip_capacity_check),
-      utf16_chars_read_(0) {
+      : early_termination_(false),
+        last_character_(unibrow::Utf16::kNoPreviousCharacter),
+        buffer_(buffer),
+        start_(buffer),
+        capacity_(capacity),
+        skip_capacity_check_(capacity == -1 || skip_capacity_check),
+        utf16_chars_read_(0) {
   }
 
   static int WriteEndCharacter(uint16_t character,
@@ -4656,8 +4618,8 @@
 
 
 static bool RecursivelySerializeToUtf8(i::String* current,
-                                      Utf8WriterVisitor* writer,
-                                      int recursion_budget) {
+                                       Utf8WriterVisitor* writer,
+                                       int recursion_budget) {
   while (!writer->IsDone()) {
     i::ConsString* cons_string = i::String::VisitFlat(writer, current);
     if (cons_string == NULL) return true;  // Leaf node.
@@ -4815,14 +4777,14 @@
   } else {
     expected = NULL;
     expectedEncoding = str->IsOneByteRepresentation() ? ASCII_ENCODING
-                                                    : TWO_BYTE_ENCODING;
+        : TWO_BYTE_ENCODING;
   }
   CHECK_EQ(expected, value);
   CHECK_EQ(expectedEncoding, encoding);
 }
 
 const v8::String::ExternalAsciiStringResource*
-      v8::String::GetExternalAsciiStringResource() const {
+v8::String::GetExternalAsciiStringResource() const {
   i::Handle<i::String> str = Utils::OpenHandle(this);
   if (i::StringShape(*str).IsExternalAscii()) {
     const void* resource =
@@ -4897,9 +4859,9 @@
 static bool InternalFieldOK(i::Handle<i::JSObject> obj,
                             int index,
                             const char* location) {
-  return ApiCheck(index < obj->GetInternalFieldCount(),
-                  location,
-                  "Internal field out of bounds");
+  return Utils::ApiCheck(index < obj->GetInternalFieldCount(),
+                         location,
+                         "Internal field out of bounds");
 }
 
 
@@ -4983,7 +4945,7 @@
 
 
 void v8::V8::SetReturnAddressLocationResolver(
-      ReturnAddressLocationResolver return_address_resolver) {
+    ReturnAddressLocationResolver return_address_resolver) {
   i::V8::SetReturnAddressLocationResolver(return_address_resolver);
 }
 
@@ -5021,9 +4983,9 @@
 
 void v8::V8::SetArrayBufferAllocator(
     ArrayBuffer::Allocator* allocator) {
-  if (!ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
-                "v8::V8::SetArrayBufferAllocator",
-                "ArrayBufferAllocator might only be set once"))
+  if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
+                       "v8::V8::SetArrayBufferAllocator",
+                       "ArrayBufferAllocator might only be set once"))
     return;
   i::V8::SetArrayBufferAllocator(allocator);
 }
@@ -5031,9 +4993,9 @@
 
 bool v8::V8::Dispose() {
   i::Isolate* isolate = i::Isolate::Current();
-  if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
-                "v8::V8::Dispose()",
-                "Use v8::Isolate::Dispose() for a non-default isolate.")) {
+  if (!Utils::ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
+                       "v8::V8::Dispose()",
+                       "Use v8::Isolate::Dispose() for non-default isolate.")) {
     return false;
   }
   i::V8::TearDown();
@@ -5252,7 +5214,7 @@
   // but can't presently as calls to GetProtoype will return the wrong result.
   if (i::Handle<i::JSGlobalProxy>::cast(
           global)->IsDetachedFrom(context->global_object())) {
-     global = i::Handle<i::Object>(context->global_object(), isolate);
+    global = i::Handle<i::Object>(context->global_object(), isolate);
   }
   return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
 }
@@ -5472,25 +5434,23 @@
 }
 
 
-i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate,
-      v8::String::ExternalStringResource* resource) {
-  i::Handle<i::String> result =
-      isolate->factory()->NewExternalStringFromTwoByte(resource);
-  return result;
+static i::Handle<i::String> NewExternalStringHandle(
+    i::Isolate* isolate,
+    v8::String::ExternalStringResource* resource) {
+  return isolate->factory()->NewExternalStringFromTwoByte(resource);
 }
 
 
-i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate,
-      v8::String::ExternalAsciiStringResource* resource) {
-  i::Handle<i::String> result =
-      isolate->factory()->NewExternalStringFromAscii(resource);
-  return result;
+static i::Handle<i::String> NewExternalAsciiStringHandle(
+    i::Isolate* isolate,
+    v8::String::ExternalAsciiStringResource* resource) {
+  return isolate->factory()->NewExternalStringFromAscii(resource);
 }
 
 
-bool RedirectToExternalString(i::Isolate* isolate,
-                              i::Handle<i::String> parent,
-                              i::Handle<i::String> external) {
+static bool RedirectToExternalString(i::Isolate* isolate,
+                                     i::Handle<i::String> parent,
+                                     i::Handle<i::String> external) {
   if (parent->IsConsString()) {
     i::Handle<i::ConsString> cons = i::Handle<i::ConsString>::cast(parent);
     cons->set_first(*external);
@@ -5506,8 +5466,8 @@
 
 
 Local<String> v8::String::NewExternal(
-      Isolate* isolate,
-      v8::String::ExternalStringResource* resource) {
+    Isolate* isolate,
+    v8::String::ExternalStringResource* resource) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
   LOG_API(i_isolate, "String::NewExternal");
@@ -5556,8 +5516,8 @@
 
 
 Local<String> v8::String::NewExternal(
-      Isolate* isolate,
-      v8::String::ExternalAsciiStringResource* resource) {
+    Isolate* isolate,
+    v8::String::ExternalAsciiStringResource* resource) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
   LOG_API(i_isolate, "String::NewExternal");
@@ -5819,8 +5779,8 @@
 
 
 // Assert that the static flags cast in GetFlags is valid.
-#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag)        \
-  STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) ==     \
+#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag)          \
+  STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) ==       \
                 static_cast<int>(i::JSRegExp::internal_flag))
 REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
@@ -5888,9 +5848,9 @@
 
 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
-  ApiCheck(!obj->is_external(),
-            "v8::ArrayBuffer::Externalize",
-            "ArrayBuffer already externalized");
+  Utils::ApiCheck(!obj->is_external(),
+                  "v8::ArrayBuffer::Externalize",
+                  "ArrayBuffer already externalized");
   obj->set_is_external(true);
   size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
   Contents contents;
@@ -5903,9 +5863,9 @@
 void v8::ArrayBuffer::Neuter() {
   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
   i::Isolate* isolate = obj->GetIsolate();
-  ApiCheck(obj->is_external(),
-           "v8::ArrayBuffer::Neuter",
-           "Only externalized ArrayBuffers can be neutered");
+  Utils::ApiCheck(obj->is_external(),
+                  "v8::ArrayBuffer::Neuter",
+                  "Only externalized ArrayBuffers can be neutered");
   LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
   ENTER_V8(isolate);
 
@@ -5989,7 +5949,7 @@
     size_t byte_offset,
     size_t byte_length) {
   ASSERT(byte_offset + byte_length <=
-      static_cast<size_t>(buffer->byte_length()->Number()));
+         static_cast<size_t>(buffer->byte_length()->Number()));
 
   obj->set_buffer(*buffer);
 
@@ -5997,11 +5957,11 @@
   buffer->set_weak_first_view(*obj);
 
   i::Handle<i::Object> byte_offset_object =
-    isolate->factory()->NewNumberFromSize(byte_offset);
+      isolate->factory()->NewNumberFromSize(byte_offset);
   obj->set_byte_offset(*byte_offset_object);
 
   i::Handle<i::Object> byte_length_object =
-    isolate->factory()->NewNumberFromSize(byte_length);
+      isolate->factory()->NewNumberFromSize(byte_length);
   obj->set_byte_length(*byte_length_object);
 }
 
@@ -6023,7 +5983,7 @@
       isolate, obj, buffer, byte_offset, byte_length);
 
   i::Handle<i::Object> length_object =
-    isolate->factory()->NewNumberFromSize(length);
+      isolate->factory()->NewNumberFromSize(length);
   obj->set_length(*length_object);
 
   i::Handle<i::ExternalArray> elements =
@@ -6175,7 +6135,7 @@
   NeanderObject obj(isolate, 2);
   obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that)));
   obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
-                            : *Utils::OpenHandle(*data));
+          : *Utils::OpenHandle(*data));
   listeners.add(obj.value());
   return true;
 }
@@ -6201,9 +6161,9 @@
 
 
 void V8::SetCaptureStackTraceForUncaughtExceptions(
-      bool capture,
-      int frame_limit,
-      StackTrace::StackTraceOptions options) {
+    bool capture,
+    int frame_limit,
+    StackTrace::StackTraceOptions options) {
   i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
       capture,
       frame_limit,
@@ -6232,7 +6192,7 @@
 }
 
 void V8::SetFailedAccessCheckCallbackFunction(
-      FailedAccessCheckCallback callback) {
+    FailedAccessCheckCallback callback) {
   i::Isolate* isolate = i::Isolate::Current();
   isolate->SetFailedAccessCheckCallback(callback);
 }
@@ -6452,6 +6412,21 @@
 }
 
 
+void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
+  CHECK(i::FLAG_expose_gc);
+  if (type == kMinorGarbageCollection) {
+    reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
+        i::NEW_SPACE, "Isolate::RequestGarbageCollection",
+        kGCCallbackFlagForced);
+  } else {
+    ASSERT_EQ(kFullGarbageCollection, type);
+    reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
+        i::Heap::kNoGCFlags, "Isolate::RequestGarbageCollection",
+        kGCCallbackFlagForced);
+  }
+}
+
+
 Isolate* Isolate::GetCurrent() {
   i::Isolate* isolate = i::Isolate::UncheckedCurrent();
   return reinterpret_cast<Isolate*>(isolate);
@@ -6466,9 +6441,9 @@
 
 void Isolate::Dispose() {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
-  if (!ApiCheck(!isolate->IsInUse(),
-                "v8::Isolate::Dispose()",
-                "Disposing the isolate that is entered by a thread.")) {
+  if (!Utils::ApiCheck(!isolate->IsInUse(),
+                       "v8::Isolate::Dispose()",
+                       "Disposing the isolate that is entered by a thread.")) {
     return;
   }
   isolate->TearDown();
@@ -7130,15 +7105,15 @@
 
 void HeapSnapshot::Serialize(OutputStream* stream,
                              HeapSnapshot::SerializationFormat format) const {
-  ApiCheck(format == kJSON,
-           "v8::HeapSnapshot::Serialize",
-           "Unknown serialization format");
-  ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
-           "v8::HeapSnapshot::Serialize",
-           "Unsupported output encoding");
-  ApiCheck(stream->GetChunkSize() > 0,
-           "v8::HeapSnapshot::Serialize",
-           "Invalid stream chunk size");
+  Utils::ApiCheck(format == kJSON,
+                  "v8::HeapSnapshot::Serialize",
+                  "Unknown serialization format");
+  Utils::ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
+                  "v8::HeapSnapshot::Serialize",
+                  "Unsupported output encoding");
+  Utils::ApiCheck(stream->GetChunkSize() > 0,
+                  "v8::HeapSnapshot::Serialize",
+                  "Invalid stream chunk size");
   i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
   serializer.Serialize(stream);
 }
diff --git a/src/api.h b/src/api.h
index aa3c38c..6091aa1 100644
--- a/src/api.h
+++ b/src/api.h
@@ -196,7 +196,12 @@
 
 class Utils {
  public:
-  static bool ReportApiFailure(const char* location, const char* message);
+  static inline bool ApiCheck(bool condition,
+                              const char* location,
+                              const char* message) {
+    if (!condition) Utils::ReportApiFailure(location, message);
+    return condition;
+  }
 
   static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj);
   static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj);
@@ -303,6 +308,9 @@
   static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) {
     return OpenHandle(*handle);
   }
+
+ private:
+  static void ReportApiFailure(const char* location, const char* message);
 };
 
 
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 4e7b248..d9449d5 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -1351,13 +1351,13 @@
     {
       AllowExternalCallThatCantCauseGC scope(masm);
       __ PrepareCallCFunction(0, 2, scratch);
-      __ SetCallCDoubleArguments(double_base, double_exponent);
+      __ MovToFloatParameters(double_base, double_exponent);
       __ CallCFunction(
           ExternalReference::power_double_double_function(masm->isolate()),
           0, 2);
     }
     __ pop(lr);
-    __ GetCFunctionDoubleResult(double_result);
+    __ MovFromFloatResult(double_result);
     __ jmp(&done);
 
     __ bind(&int_exponent_convert);
@@ -1425,13 +1425,13 @@
     {
       AllowExternalCallThatCantCauseGC scope(masm);
       __ PrepareCallCFunction(0, 2, scratch);
-      __ SetCallCDoubleArguments(double_base, double_exponent);
+      __ MovToFloatParameters(double_base, double_exponent);
       __ CallCFunction(
           ExternalReference::power_double_double_function(masm->isolate()),
           0, 2);
     }
     __ pop(lr);
-    __ GetCFunctionDoubleResult(double_result);
+    __ MovFromFloatResult(double_result);
 
     __ bind(&done);
     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 5477b24..c850742 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -357,9 +357,9 @@
 
   MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
 
-  __ GetCFunctionDoubleResult(d0);
+  __ MovFromFloatParameter(d0);
   __ vsqrt(d0, d0);
-  __ SetCallCDoubleArguments(d0);
+  __ MovToFloatResult(d0);
   __ Ret();
 
   CodeDesc desc;
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 8888ec6..d2c9a25 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2128,12 +2128,12 @@
       break;
     case Token::MOD: {
       __ PrepareCallCFunction(0, 2, scratch0());
-      __ SetCallCDoubleArguments(left, right);
+      __ MovToFloatParameters(left, right);
       __ CallCFunction(
           ExternalReference::mod_two_doubles_operation(isolate()),
           0, 2);
       // Move the result in the double result register.
-      __ GetCFunctionDoubleResult(result);
+      __ MovFromFloatResult(result);
       break;
     }
     default:
@@ -3934,10 +3934,10 @@
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   __ PrepareCallCFunction(0, 1, scratch0());
-  __ SetCallCDoubleArguments(ToDoubleRegister(instr->value()));
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
   __ CallCFunction(ExternalReference::math_log_double_function(isolate()),
                    0, 1);
-  __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
 
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 97d05a6..38ab0e9 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1081,7 +1081,7 @@
 }
 
 
-void MacroAssembler::GetCFunctionDoubleResult(const DwVfpRegister dst) {
+void MacroAssembler::MovFromFloatResult(const DwVfpRegister dst) {
   if (use_eabi_hardfloat()) {
     Move(dst, d0);
   } else {
@@ -1090,6 +1090,12 @@
 }
 
 
+// On ARM this is just a synonym to make the purpose clear.
+void MacroAssembler::MovFromFloatParameter(DwVfpRegister dst) {
+  MovFromFloatResult(dst);
+}
+
+
 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
   // This macro takes the dst register to make the code more readable
   // at the call sites. However, the dst register has to be r5 to
@@ -3540,33 +3546,27 @@
 }
 
 
-void MacroAssembler::SetCallCDoubleArguments(DwVfpRegister dreg) {
-  ASSERT(dreg.is(d0));
+void MacroAssembler::MovToFloatParameter(DwVfpRegister src) {
+  ASSERT(src.is(d0));
   if (!use_eabi_hardfloat()) {
-    vmov(r0, r1, dreg);
+    vmov(r0, r1, src);
   }
 }
 
 
-void MacroAssembler::SetCallCDoubleArguments(DwVfpRegister dreg1,
-                                             DwVfpRegister dreg2) {
-  ASSERT(dreg1.is(d0));
-  ASSERT(dreg2.is(d1));
-  if (!use_eabi_hardfloat()) {
-    vmov(r0, r1, dreg1);
-    vmov(r2, r3, dreg2);
-  }
+// On ARM this is just a synonym to make the purpose clear.
+void MacroAssembler::MovToFloatResult(DwVfpRegister src) {
+  MovToFloatParameter(src);
 }
 
 
-void MacroAssembler::SetCallCDoubleArguments(DwVfpRegister dreg,
-                                             Register reg) {
-  ASSERT(dreg.is(d0));
-  if (use_eabi_hardfloat()) {
-    Move(r0, reg);
-  } else {
-    Move(r2, reg);
-    vmov(r0, r1, dreg);
+void MacroAssembler::MovToFloatParameters(DwVfpRegister src1,
+                                          DwVfpRegister src2) {
+  ASSERT(src1.is(d0));
+  ASSERT(src2.is(d1));
+  if (!use_eabi_hardfloat()) {
+    vmov(r0, r1, src1);
+    vmov(r2, r3, src2);
   }
 }
 
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index c4feb3e..3a133b9 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -1125,9 +1125,9 @@
   // whether soft or hard floating point ABI is used. These functions
   // abstract parameter passing for the three different ways we call
   // C functions from generated code.
-  void SetCallCDoubleArguments(DwVfpRegister dreg);
-  void SetCallCDoubleArguments(DwVfpRegister dreg1, DwVfpRegister dreg2);
-  void SetCallCDoubleArguments(DwVfpRegister dreg, Register reg);
+  void MovToFloatParameter(DwVfpRegister src);
+  void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2);
+  void MovToFloatResult(DwVfpRegister src);
 
   // Calls a C function and cleans up the space for arguments allocated
   // by PrepareCallCFunction. The called function is not allowed to trigger a
@@ -1143,7 +1143,8 @@
                      int num_reg_arguments,
                      int num_double_arguments);
 
-  void GetCFunctionDoubleResult(const DwVfpRegister dst);
+  void MovFromFloatParameter(DwVfpRegister dst);
+  void MovFromFloatResult(DwVfpRegister dst);
 
   // Calls an API function.  Allocates HandleScope, extracts returned value
   // from handle and propagates exceptions.  Restores context.  stack_space
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index f384720..800b5b4 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -2293,9 +2293,9 @@
     current = current->next();
   }
   // Didn't find the extension; fail.
-  if (current == NULL) {
-    v8::Utils::ReportApiFailure(
-        "v8::Context::New()", "Cannot find required extension");
+  if (!Utils::ApiCheck(current != NULL,
+                       "v8::Context::New()",
+                       "Cannot find required extension")) {
     return false;
   }
   return InstallExtension(isolate, current, extension_states);
@@ -2310,9 +2310,9 @@
   if (extension_states->get_state(current) == INSTALLED) return true;
   // The current node has already been visited so there must be a
   // cycle in the dependency graph; fail.
-  if (extension_states->get_state(current) == VISITED) {
-    v8::Utils::ReportApiFailure(
-        "v8::Context::New()", "Circular extension dependency");
+  if (!Utils::ApiCheck(extension_states->get_state(current) != VISITED,
+                       "v8::Context::New()",
+                       "Circular extension dependency")) {
     return false;
   }
   ASSERT(extension_states->get_state(current) == UNVISITED);
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 67f9dc8..785b9ca 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -491,20 +491,16 @@
                             AllocationSite::kNestedSiteOffset),
                         graph()->GetConstant0());
 
-  // Pretenuring calculation fields.
+  // Pretenuring calculation field.
   Add<HStoreNamedField>(object,
                         HObjectAccess::ForAllocationSiteOffset(
-                            AllocationSite::kMementoFoundCountOffset),
+                            AllocationSite::kPretenureDataOffset),
                         graph()->GetConstant0());
 
+  // Pretenuring memento creation count field.
   Add<HStoreNamedField>(object,
                         HObjectAccess::ForAllocationSiteOffset(
-                            AllocationSite::kMementoCreateCountOffset),
-                        graph()->GetConstant0());
-
-  Add<HStoreNamedField>(object,
-                        HObjectAccess::ForAllocationSiteOffset(
-                            AllocationSite::kPretenureDecisionOffset),
+                            AllocationSite::kPretenureCreateCountOffset),
                         graph()->GetConstant0());
 
   // Store an empty fixed array for the code dependency.
diff --git a/src/extensions/gc-extension.cc b/src/extensions/gc-extension.cc
index 69fd717..205587f 100644
--- a/src/extensions/gc-extension.cc
+++ b/src/extensions/gc-extension.cc
@@ -42,9 +42,11 @@
 void GCExtension::GC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
   if (args[0]->BooleanValue()) {
-    isolate->heap()->CollectGarbage(NEW_SPACE, "gc extension");
+    isolate->heap()->CollectGarbage(
+        NEW_SPACE, "gc extension", v8::kGCCallbackFlagForced);
   } else {
-    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "gc extension");
+    isolate->heap()->CollectAllGarbage(
+        Heap::kNoGCFlags, "gc extension", v8::kGCCallbackFlagForced);
   }
 }
 
diff --git a/src/handles.cc b/src/handles.cc
index bc8d2d7..b3282fa 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -63,9 +63,9 @@
   ASSERT(result == current->limit);
   // Make sure there's at least one scope on the stack and that the
   // top of the scope stack isn't a barrier.
-  if (current->level == 0) {
-    Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
-                            "Cannot create a handle without a HandleScope");
+  if (!Utils::ApiCheck(current->level != 0,
+                       "v8::HandleScope::CreateHandle()",
+                       "Cannot create a handle without a HandleScope")) {
     return NULL;
   }
   HandleScopeImplementer* impl = isolate->handle_scope_implementer();
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 5e6fb2b..f70b6f7 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -485,22 +485,32 @@
 
 void Heap::UpdateAllocationSiteFeedback(HeapObject* object) {
   Heap* heap = object->GetHeap();
-  if (FLAG_allocation_site_pretenuring &&
-      heap->new_space_high_promotion_mode_active_ &&
-      AllocationSite::CanTrack(object->map()->instance_type())) {
-    AllocationMemento* memento = AllocationMemento::FindForHeapObject(
-        object, heap, true);
-    if (memento != NULL) {
-      ASSERT(memento->IsValid());
-      bool add_to_scratchpad =
-          memento->GetAllocationSite()->IncrementMementoFoundCount();
-      if (add_to_scratchpad && heap->allocation_sites_scratchpad_length <
-              kAllocationSiteScratchpadSize) {
-        heap->allocation_sites_scratchpad[
-            heap->allocation_sites_scratchpad_length++] =
-                memento->GetAllocationSite();
-      }
-    }
+  ASSERT(heap->InNewSpace(object));
+
+  if (!FLAG_allocation_site_pretenuring ||
+      !heap->new_space_high_promotion_mode_active_ ||
+      !AllocationSite::CanTrack(object->map()->instance_type())) return;
+
+  // Either object is the last object in the from space, or there is another
+  // object of at least word size (the header map word) following it, so
+  // suffices to compare ptr and top here.
+  Address ptr = object->address() + object->Size();
+  Address top = heap->new_space()->FromSpacePageHigh();
+  ASSERT(ptr == top || ptr + HeapObject::kHeaderSize <= top);
+  if (ptr == top) return;
+
+  HeapObject* candidate = HeapObject::FromAddress(ptr);
+  if (candidate->map() != heap->allocation_memento_map()) return;
+
+  AllocationMemento* memento = AllocationMemento::cast(candidate);
+  if (!memento->IsValid()) return;
+
+  if (memento->GetAllocationSite()->IncrementMementoFoundCount() &&
+      heap->allocation_sites_scratchpad_length <
+      kAllocationSiteScratchpadSize) {
+    heap->allocation_sites_scratchpad[
+        heap->allocation_sites_scratchpad_length++] =
+        memento->GetAllocationSite();
   }
 }
 
@@ -532,10 +542,13 @@
 }
 
 
-bool Heap::CollectGarbage(AllocationSpace space, const char* gc_reason) {
+bool Heap::CollectGarbage(AllocationSpace space,
+                          const char* gc_reason,
+                          const v8::GCCallbackFlags callbackFlags) {
   const char* collector_reason = NULL;
   GarbageCollector collector = SelectGarbageCollector(space, &collector_reason);
-  return CollectGarbage(space, collector, gc_reason, collector_reason);
+  return CollectGarbage(
+      space, collector, gc_reason, collector_reason, callbackFlags);
 }
 
 
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 3125a26..35cfcb4 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1403,15 +1403,12 @@
                        AllocationSite::kTransitionInfoOffset);
   SetInternalReference(site, entry, "nested_site", site->nested_site(),
                        AllocationSite::kNestedSiteOffset);
-  SetInternalReference(site, entry, "memento_found_count",
-                       site->memento_found_count(),
-                       AllocationSite::kMementoFoundCountOffset);
-  SetInternalReference(site, entry, "memento_create_count",
-                       site->memento_create_count(),
-                       AllocationSite::kMementoCreateCountOffset);
-  SetInternalReference(site, entry, "pretenure_decision",
-                       site->pretenure_decision(),
-                       AllocationSite::kPretenureDecisionOffset);
+  SetInternalReference(site, entry, "pretenure_data",
+                       site->pretenure_data(),
+                       AllocationSite::kPretenureDataOffset);
+  SetInternalReference(site, entry, "pretenure_create_count",
+                       site->pretenure_create_count(),
+                       AllocationSite::kPretenureCreateCountOffset);
   SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
                        AllocationSite::kDependentCodeOffset);
 }
@@ -2131,7 +2128,7 @@
     group->info = NULL;  // Acquire info object ownership.
   }
   isolate->global_handles()->RemoveObjectGroups();
-  isolate->heap()->CallGCEpilogueCallbacks(major_gc_type);
+  isolate->heap()->CallGCEpilogueCallbacks(major_gc_type, kNoGCCallbackFlags);
   // Record objects that are not in ObjectGroups, but have class ID.
   GlobalHandlesExtractor extractor(this);
   isolate->global_handles()->IterateAllRootsWithClassIds(&extractor);
diff --git a/src/heap.cc b/src/heap.cc
index 60b425c..899d701 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -526,8 +526,8 @@
               list_element->IsAllocationSite()) {
       AllocationSite* site = use_scratchpad ?
         allocation_sites_scratchpad[i] : AllocationSite::cast(list_element);
-      allocation_mementos_found += site->memento_found_count()->value();
-      if (site->memento_found_count()->value() > 0) {
+      allocation_mementos_found += site->memento_found_count();
+      if (site->memento_found_count() > 0) {
         active_allocation_sites++;
       }
       if (site->DigestPretenuringFeedback()) {
@@ -702,12 +702,14 @@
 }
 
 
-void Heap::CollectAllGarbage(int flags, const char* gc_reason) {
+void Heap::CollectAllGarbage(int flags,
+                             const char* gc_reason,
+                             const v8::GCCallbackFlags gc_callback_flags) {
   // Since we are ignoring the return value, the exact choice of space does
   // not matter, so long as we do not specify NEW_SPACE, which would not
   // cause a full GC.
   mark_compact_collector_.SetFlags(flags);
-  CollectGarbage(OLD_POINTER_SPACE, gc_reason);
+  CollectGarbage(OLD_POINTER_SPACE, gc_reason, gc_callback_flags);
   mark_compact_collector_.SetFlags(kNoGCFlags);
 }
 
@@ -750,7 +752,8 @@
 bool Heap::CollectGarbage(AllocationSpace space,
                           GarbageCollector collector,
                           const char* gc_reason,
-                          const char* collector_reason) {
+                          const char* collector_reason,
+                          const v8::GCCallbackFlags gc_callback_flags) {
   // The VM is in the GC state until exiting this function.
   VMState<GC> state(isolate_);
 
@@ -805,7 +808,7 @@
           (collector == SCAVENGER) ? isolate_->counters()->gc_scavenger()
                                    : isolate_->counters()->gc_compactor());
       next_gc_likely_to_collect_more =
-          PerformGarbageCollection(collector, &tracer);
+          PerformGarbageCollection(collector, &tracer, gc_callback_flags);
     }
 
     GarbageCollectionEpilogue();
@@ -1032,8 +1035,10 @@
   survival_rate_ = survival_rate;
 }
 
-bool Heap::PerformGarbageCollection(GarbageCollector collector,
-                                    GCTracer* tracer) {
+bool Heap::PerformGarbageCollection(
+    GarbageCollector collector,
+    GCTracer* tracer,
+    const v8::GCCallbackFlags gc_callback_flags) {
   bool next_gc_likely_to_collect_more = false;
 
   if (collector != SCAVENGER) {
@@ -1164,7 +1169,7 @@
     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
     VMState<EXTERNAL> state(isolate_);
     HandleScope handle_scope(isolate_);
-    CallGCEpilogueCallbacks(gc_type);
+    CallGCEpilogueCallbacks(gc_type, gc_callback_flags);
   }
 
 #ifdef VERIFY_HEAP
@@ -1194,18 +1199,19 @@
 }
 
 
-void Heap::CallGCEpilogueCallbacks(GCType gc_type) {
+void Heap::CallGCEpilogueCallbacks(GCType gc_type,
+                                   GCCallbackFlags gc_callback_flags) {
   for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
     if (gc_type & gc_epilogue_callbacks_[i].gc_type) {
       if (!gc_epilogue_callbacks_[i].pass_isolate_) {
         v8::GCPrologueCallback callback =
             reinterpret_cast<v8::GCPrologueCallback>(
                 gc_epilogue_callbacks_[i].callback);
-        callback(gc_type, kNoGCCallbackFlags);
+        callback(gc_type, gc_callback_flags);
       } else {
         v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
         gc_epilogue_callbacks_[i].callback(
-            isolate, gc_type, kNoGCCallbackFlags);
+            isolate, gc_type, gc_callback_flags);
       }
     }
   }
diff --git a/src/heap.h b/src/heap.h
index 7134f06..19d91a9 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1157,8 +1157,10 @@
   // Performs garbage collection operation.
   // Returns whether there is a chance that another major GC could
   // collect more garbage.
-  inline bool CollectGarbage(AllocationSpace space,
-                             const char* gc_reason = NULL);
+  inline bool CollectGarbage(
+      AllocationSpace space,
+      const char* gc_reason = NULL,
+      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
 
   static const int kNoGCFlags = 0;
   static const int kSweepPreciselyMask = 1;
@@ -1173,7 +1175,10 @@
   // Performs a full garbage collection.  If (flags & kMakeHeapIterableMask) is
   // non-zero, then the slower precise sweeper is used, which leaves the heap
   // in a state where we can iterate over the heap visiting all objects.
-  void CollectAllGarbage(int flags, const char* gc_reason = NULL);
+  void CollectAllGarbage(
+      int flags,
+      const char* gc_reason = NULL,
+      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
 
   // Last hope GC, should try to squeeze as much as possible.
   void CollectAllAvailableGarbage(const char* gc_reason = NULL);
@@ -1701,7 +1706,7 @@
   inline Isolate* isolate();
 
   void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags);
-  void CallGCEpilogueCallbacks(GCType gc_type);
+  void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags);
 
   inline bool OldGenerationAllocationLimitReached();
 
@@ -2052,16 +2057,20 @@
   // Performs garbage collection operation.
   // Returns whether there is a chance that another major GC could
   // collect more garbage.
-  bool CollectGarbage(AllocationSpace space,
-                      GarbageCollector collector,
-                      const char* gc_reason,
-                      const char* collector_reason);
+  bool CollectGarbage(
+      AllocationSpace space,
+      GarbageCollector collector,
+      const char* gc_reason,
+      const char* collector_reason,
+      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
 
   // Performs garbage collection
   // Returns whether there is a chance another major GC could
   // collect more garbage.
-  bool PerformGarbageCollection(GarbageCollector collector,
-                                GCTracer* tracer);
+  bool PerformGarbageCollection(
+      GarbageCollector collector,
+      GCTracer* tracer,
+      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
 
   inline void UpdateOldSpaceLimits();
 
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 4991668..4e614d8 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -4284,11 +4284,9 @@
       return HObjectAccess(kInobject, offset, Representation::Tagged());
     case AllocationSite::kNestedSiteOffset:
       return HObjectAccess(kInobject, offset, Representation::Tagged());
-    case AllocationSite::kMementoFoundCountOffset:
+    case AllocationSite::kPretenureDataOffset:
       return HObjectAccess(kInobject, offset, Representation::Smi());
-    case AllocationSite::kMementoCreateCountOffset:
-      return HObjectAccess(kInobject, offset, Representation::Smi());
-    case AllocationSite::kPretenureDecisionOffset:
+    case AllocationSite::kPretenureCreateCountOffset:
       return HObjectAccess(kInobject, offset, Representation::Smi());
     case AllocationSite::kDependentCodeOffset:
       return HObjectAccess(kInobject, offset, Representation::Tagged());
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 7c6b2cb..4377b42 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2642,7 +2642,7 @@
   if (FLAG_allocation_site_pretenuring) {
     HValue* memento_create_count = Add<HLoadNamedField>(
         allocation_site, HObjectAccess::ForAllocationSiteOffset(
-            AllocationSite::kMementoCreateCountOffset));
+            AllocationSite::kPretenureCreateCountOffset));
     memento_create_count = AddUncasted<HAdd>(
         memento_create_count, graph()->GetConstant1());
     // This smi value is reset to zero after every gc, overflow isn't a problem
@@ -2650,7 +2650,7 @@
     memento_create_count->ClearFlag(HValue::kCanOverflow);
     HStoreNamedField* store = Add<HStoreNamedField>(
         allocation_site, HObjectAccess::ForAllocationSiteOffset(
-            AllocationSite::kMementoCreateCountOffset), memento_create_count);
+            AllocationSite::kPretenureCreateCountOffset), memento_create_count);
     // No write barrier needed to store a smi.
     store->SkipWriteBarrier();
   }
@@ -7613,11 +7613,12 @@
   HValue* function = Top();
 
   AddCheckConstantFunction(expr->holder(), function, function_map);
-  Drop(1);
 
   CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
   HValue* receiver = Pop();
 
+  Drop(1);  // Pop the function.
+
   if (function_state()->outer() == NULL) {
     HInstruction* elements = Add<HArgumentsElements>(false);
     HInstruction* length = Add<HArgumentsLength>(elements);
@@ -7906,10 +7907,11 @@
 
   ElementsKind kind = expr->elements_kind();
   Handle<Cell> cell = expr->allocation_info_cell();
-  AllocationSite* site = AllocationSite::cast(cell->value());
+  Handle<AllocationSite> site(AllocationSite::cast(cell->value()));
 
   // Register on the site for deoptimization if the cell value changes.
-  site->AddDependentCompilationInfo(AllocationSite::TRANSITIONS, top_info());
+  AllocationSite::AddDependentCompilationInfo(
+      site, AllocationSite::TRANSITIONS, top_info());
   HInstruction* cell_instruction = Add<HConstant>(cell);
 
   // In the single constant argument case, we may have to adjust elements kind
@@ -8924,8 +8926,9 @@
     // Register the dependent code with the allocation site.
     if (!allocation_mode.feedback_site().is_null()) {
       ASSERT(!graph()->info()->IsStub());
-      allocation_mode.feedback_site()->AddDependentCompilationInfo(
-          AllocationSite::TENURING, top_info());
+      Handle<AllocationSite> site(allocation_mode.feedback_site());
+      AllocationSite::AddDependentCompilationInfo(
+          site, AllocationSite::TENURING, top_info());
     }
 
     // Inline string addition if we know that we'll create a cons string.
@@ -9501,8 +9504,9 @@
   PretenureFlag pretenure_flag = isolate()->heap()->GetPretenureMode();
   if (FLAG_allocation_site_pretenuring) {
     pretenure_flag = site_context->current()->GetPretenureMode();
-    site_context->current()->AddDependentCompilationInfo(
-        AllocationSite::TENURING, top_info());
+    Handle<AllocationSite> site(site_context->current());
+    AllocationSite::AddDependentCompilationInfo(
+        site, AllocationSite::TENURING, top_info());
   }
 
   HInstruction* object = Add<HAllocate>(object_size_constant, type,
@@ -10716,10 +10720,21 @@
     }
 
     PrintEmptyProperty("xhandlers");
-    const char* flags = current->IsLoopSuccessorDominator()
-        ? "dom-loop-succ"
-        : "";
-    PrintStringProperty("flags", flags);
+
+    {
+      PrintIndent();
+      trace_.Add("flags");
+      if (current->IsLoopSuccessorDominator()) {
+        trace_.Add(" \"dom-loop-succ\"");
+      }
+      if (current->IsUnreachable()) {
+        trace_.Add(" \"dead\"");
+      }
+      if (current->is_osr_entry()) {
+        trace_.Add(" \"osr\"");
+      }
+      trace_.Add("\n");
+    }
 
     if (current->dominator() != NULL) {
       PrintBlockProperty("dominator", current->dominator()->block_id());
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 933cf43..66c72f8 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -1425,13 +1425,13 @@
     {
       AllowExternalCallThatCantCauseGC scope(masm);
       __ PrepareCallCFunction(0, 2, scratch2);
-      __ SetCallCDoubleArguments(double_base, double_exponent);
+      __ MovToFloatParameters(double_base, double_exponent);
       __ CallCFunction(
           ExternalReference::power_double_double_function(masm->isolate()),
           0, 2);
     }
     __ pop(ra);
-    __ GetCFunctionDoubleResult(double_result);
+    __ MovFromFloatResult(double_result);
     __ jmp(&done);
 
     __ bind(&int_exponent_convert);
@@ -1509,13 +1509,13 @@
     {
       AllowExternalCallThatCantCauseGC scope(masm);
       __ PrepareCallCFunction(0, 2, scratch);
-      __ SetCallCDoubleArguments(double_base, double_exponent);
+      __ MovToFloatParameters(double_base, double_exponent);
       __ CallCFunction(
           ExternalReference::power_double_double_function(masm->isolate()),
           0, 2);
     }
     __ pop(ra);
-    __ GetCFunctionDoubleResult(double_result);
+    __ MovFromFloatResult(double_result);
 
     __ bind(&done);
     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index d07a6bb..0dd42d6 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -535,9 +535,9 @@
 
   MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
 
-  __ GetFromCDoubleArguments(f12);
+  __ MovFromFloatParameter(f12);
   __ sqrt_d(f0, f12);
-  __ SetForCDoubleResult(f0);
+  __ MovToFloatResult(f0);
   __ Ret();
 
   CodeDesc desc;
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index ddd5037..ac8c04a 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1936,12 +1936,12 @@
       __ MultiPush(saved_regs);
 
       __ PrepareCallCFunction(0, 2, scratch0());
-      __ SetCallCDoubleArguments(left, right);
+      __ MovToFloatParameters(left, right);
       __ CallCFunction(
           ExternalReference::mod_two_doubles_operation(isolate()),
           0, 2);
       // Move the result in the double result register.
-      __ GetCFunctionDoubleResult(result);
+      __ MovFromFloatResult(result);
 
       // Restore saved register.
       __ MultiPop(saved_regs);
@@ -3856,10 +3856,10 @@
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   __ PrepareCallCFunction(0, 1, scratch0());
-  __ SetCallCDoubleArguments(ToDoubleRegister(instr->value()));
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
   __ CallCFunction(ExternalReference::math_log_double_function(isolate()),
                    0, 1);
-  __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
 
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 116cb05..c64fe2a 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -3517,7 +3517,7 @@
 }
 
 
-void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
+void MacroAssembler::MovFromFloatResult(DoubleRegister dst) {
   if (IsMipsSoftFloatABI) {
     Move(dst, v0, v1);
   } else {
@@ -3526,7 +3526,7 @@
 }
 
 
-void MacroAssembler::GetFromCDoubleArguments(const DoubleRegister dst) {
+void MacroAssembler::MovFromFloatParameter(DoubleRegister dst) {
   if (IsMipsSoftFloatABI) {
     Move(dst, a0, a1);
   } else {
@@ -3535,50 +3535,38 @@
 }
 
 
-void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
+void MacroAssembler::MovToFloatParameter(DoubleRegister src) {
   if (!IsMipsSoftFloatABI) {
-    Move(f12, dreg);
+    Move(f12, src);
   } else {
-    Move(a0, a1, dreg);
+    Move(a0, a1, src);
   }
 }
 
 
-void MacroAssembler::SetForCDoubleResult(DoubleRegister dreg) {
+void MacroAssembler::MovToFloatResult(DoubleRegister src) {
   if (!IsMipsSoftFloatABI) {
-    Move(f0, dreg);
+    Move(f0, src);
   } else {
-    Move(v0, v1, dreg);
+    Move(v0, v1, src);
   }
 }
 
 
-void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
-                                             DoubleRegister dreg2) {
+void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
+                                          DoubleRegister src2) {
   if (!IsMipsSoftFloatABI) {
-    if (dreg2.is(f12)) {
-      ASSERT(!dreg1.is(f14));
-      Move(f14, dreg2);
-      Move(f12, dreg1);
+    if (src2.is(f12)) {
+      ASSERT(!src1.is(f14));
+      Move(f14, src2);
+      Move(f12, src1);
     } else {
-      Move(f12, dreg1);
-      Move(f14, dreg2);
+      Move(f12, src1);
+      Move(f14, src2);
     }
   } else {
-    Move(a0, a1, dreg1);
-    Move(a2, a3, dreg2);
-  }
-}
-
-
-void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
-                                             Register reg) {
-  if (!IsMipsSoftFloatABI) {
-    Move(f12, dreg);
-    Move(a2, reg);
-  } else {
-    Move(a2, reg);
-    Move(a0, a1, dreg);
+    Move(a0, a1, src1);
+    Move(a2, a3, src2);
   }
 }
 
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index c3f265f..8fc5d9d 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -1277,17 +1277,16 @@
   void CallCFunction(Register function,
                      int num_reg_arguments,
                      int num_double_arguments);
-  void GetCFunctionDoubleResult(const DoubleRegister dst);
-  void GetFromCDoubleArguments(const DoubleRegister dst);
+  void MovFromFloatResult(DoubleRegister dst);
+  void MovFromFloatParameter(DoubleRegister dst);
 
   // There are two ways of passing double arguments on MIPS, depending on
   // whether soft or hard floating point ABI is used. These functions
   // abstract parameter passing for the three different ways we call
   // C functions from generated code.
-  void SetCallCDoubleArguments(DoubleRegister dreg);
-  void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
-  void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
-  void SetForCDoubleResult(DoubleRegister dreg);
+  void MovToFloatParameter(DoubleRegister src);
+  void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
+  void MovToFloatResult(DoubleRegister src);
 
   // Calls an API function.  Allocates HandleScope, extracts returned value
   // from handle and propagates exceptions.  Restores context.  stack_space
diff --git a/src/objects-inl.h b/src/objects-inl.h
index bcfb598..49e4d69 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -48,6 +48,7 @@
 #include "factory.h"
 #include "incremental-marking.h"
 #include "transitions-inl.h"
+#include "objects-visiting.h"
 
 namespace v8 {
 namespace internal {
@@ -1304,9 +1305,8 @@
   set_transition_info(Smi::FromInt(0));
   SetElementsKind(GetInitialFastElementsKind());
   set_nested_site(Smi::FromInt(0));
-  set_memento_create_count(Smi::FromInt(0));
-  set_memento_found_count(Smi::FromInt(0));
-  set_pretenure_decision(Smi::FromInt(0));
+  set_pretenure_data(Smi::FromInt(0));
+  set_pretenure_create_count(Smi::FromInt(0));
   set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
                      SKIP_WRITE_BARRIER);
 }
@@ -1315,7 +1315,7 @@
 void AllocationSite::MarkZombie() {
   ASSERT(!IsZombie());
   Initialize();
-  set_pretenure_decision(Smi::FromInt(kZombie));
+  set_pretenure_decision(kZombie);
 }
 
 
@@ -1367,35 +1367,50 @@
 }
 
 
+inline void AllocationSite::set_memento_found_count(int count) {
+  int value = pretenure_data()->value();
+  // Verify that we can count more mementos than we can possibly find in one
+  // new space collection.
+  ASSERT((GetHeap()->MaxSemiSpaceSize() /
+          (StaticVisitorBase::kMinObjectSizeInWords * kPointerSize +
+           AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
+  ASSERT(count < MementoFoundCountBits::kMax);
+  set_pretenure_data(
+      Smi::FromInt(MementoFoundCountBits::update(value, count)),
+      SKIP_WRITE_BARRIER);
+}
+
 inline bool AllocationSite::IncrementMementoFoundCount() {
   if (IsZombie()) return false;
 
-  int value = memento_found_count()->value();
-  set_memento_found_count(Smi::FromInt(value + 1));
+  int value = memento_found_count();
+  set_memento_found_count(value + 1);
   return value == 0;
 }
 
 
 inline void AllocationSite::IncrementMementoCreateCount() {
   ASSERT(FLAG_allocation_site_pretenuring);
-  int value = memento_create_count()->value();
-  set_memento_create_count(Smi::FromInt(value + 1));
+  int value = memento_create_count();
+  set_memento_create_count(value + 1);
 }
 
 
 inline bool AllocationSite::DigestPretenuringFeedback() {
   bool decision_made = false;
-  int create_count = memento_create_count()->value();
+  int create_count = memento_create_count();
   if (create_count >= kPretenureMinimumCreated) {
-    int found_count = memento_found_count()->value();
+    int found_count = memento_found_count();
     double ratio = static_cast<double>(found_count) / create_count;
     if (FLAG_trace_track_allocation_sites) {
       PrintF("AllocationSite: %p (created, found, ratio) (%d, %d, %f)\n",
              static_cast<void*>(this), create_count, found_count, ratio);
     }
     int current_mode = GetPretenureMode();
-    int result = ratio >= kPretenureRatio ? kTenure : kDontTenure;
-    set_pretenure_decision(Smi::FromInt(result));
+    PretenureDecision result = ratio >= kPretenureRatio
+        ? kTenure
+        : kDontTenure;
+    set_pretenure_decision(result);
     decision_made = true;
     if (current_mode != GetPretenureMode()) {
       dependent_code()->DeoptimizeDependentCodeGroup(
@@ -1405,8 +1420,8 @@
   }
 
   // Clear feedback calculation fields until the next gc.
-  set_memento_found_count(Smi::FromInt(0));
-  set_memento_create_count(Smi::FromInt(0));
+  set_memento_found_count(0);
+  set_memento_create_count(0);
   return decision_made;
 }
 
@@ -4600,10 +4615,9 @@
 
 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
-ACCESSORS_TO_SMI(AllocationSite, memento_found_count, kMementoFoundCountOffset)
-ACCESSORS_TO_SMI(AllocationSite, memento_create_count,
-                 kMementoCreateCountOffset)
-ACCESSORS_TO_SMI(AllocationSite, pretenure_decision, kPretenureDecisionOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_data, kPretenureDataOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_create_count,
+                 kPretenureCreateCountOffset)
 ACCESSORS(AllocationSite, dependent_code, DependentCode,
           kDependentCodeOffset)
 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 1da9852..219b692 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -1136,11 +1136,11 @@
   PrintF(out, "\n - nested site: ");
   nested_site()->ShortPrint(out);
   PrintF(out, "\n - memento found count: ");
-  memento_found_count()->ShortPrint(out);
+  Smi::FromInt(memento_found_count())->ShortPrint(out);
   PrintF(out, "\n - memento create count: ");
-  memento_create_count()->ShortPrint(out);
+  Smi::FromInt(memento_create_count())->ShortPrint(out);
   PrintF(out, "\n - pretenure decision: ");
-  pretenure_decision()->ShortPrint(out);
+  Smi::FromInt(pretenure_decision())->ShortPrint(out);
   PrintF(out, "\n - transition_info: ");
   if (transition_info()->IsSmi()) {
     ElementsKind kind = GetElementsKind();
diff --git a/src/objects.cc b/src/objects.cc
index 539d4af..23cd6d9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -45,7 +45,6 @@
 #include "isolate-inl.h"
 #include "log.h"
 #include "objects-inl.h"
-#include "objects-visiting.h"
 #include "objects-visiting-inl.h"
 #include "macro-assembler.h"
 #include "mark-compact.h"
@@ -9202,39 +9201,6 @@
 }
 
 
-AllocationMemento* AllocationMemento::FindForHeapObject(HeapObject* object,
-                                                        Heap* heap,
-                                                        bool in_GC) {
-  // AllocationMemento objects are only allocated immediately after objects in
-  // NewSpace. Detecting whether a memento is present involves carefully
-  // checking the object immediately after the current object (if there is one)
-  // to see if it's an AllocationMemento.
-  ASSERT(heap->InNewSpace(object));
-  Address ptr_end = (reinterpret_cast<Address>(object) - kHeapObjectTag) +
-      object->Size();
-  Address top;
-  if (in_GC) {
-    top = heap->new_space()->FromSpacePageHigh();
-  } else {
-    top = heap->NewSpaceTop();
-  }
-  if ((ptr_end + AllocationMemento::kSize) <= top) {
-    // There is room in newspace for allocation info. Do we have some?
-    Map** possible_allocation_memento_map =
-        reinterpret_cast<Map**>(ptr_end);
-    if (*possible_allocation_memento_map ==
-        object->GetHeap()->allocation_memento_map()) {
-      AllocationMemento* memento = AllocationMemento::cast(
-          reinterpret_cast<Object*>(ptr_end + kHeapObjectTag));
-      if (memento->IsValid()) {
-        return memento;
-      }
-    }
-  }
-  return NULL;
-}
-
-
 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
   // For array indexes mix the length into the hash as an array index could
   // be zero.
@@ -12797,14 +12763,14 @@
   dependent_code()->DeoptimizeDependentCodeGroup(
       GetIsolate(),
       DependentCode::kAllocationSiteTenuringChangedGroup);
-  set_pretenure_decision(Smi::FromInt(kUndecided));
-  set_memento_found_count(Smi::FromInt(0));
-  set_memento_create_count(Smi::FromInt(0));
+  set_pretenure_decision(kUndecided);
+  set_memento_found_count(0);
+  set_memento_create_count(0);
 }
 
 
 PretenureFlag AllocationSite::GetPretenureMode() {
-  int mode = pretenure_decision()->value();
+  PretenureDecision mode = pretenure_decision();
   // Zombie objects "decide" to be untenured.
   return (mode == kTenure && GetHeap()->GetPretenureMode() == TENURED)
       ? TENURED : NOT_TENURED;
@@ -12878,22 +12844,16 @@
 }
 
 
-void AllocationSite::AddDependentCompilationInfo(Reason reason,
+// static
+void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site,
+                                                 Reason reason,
                                                  CompilationInfo* info) {
-  DependentCode::DependencyGroup group = ToDependencyGroup(reason);
-  Handle<DependentCode> dep(dependent_code());
+  DependentCode::DependencyGroup group = site->ToDependencyGroup(reason);
+  Handle<DependentCode> dep(site->dependent_code());
   Handle<DependentCode> codes =
       DependentCode::Insert(dep, group, info->object_wrapper());
-  if (*codes != dependent_code()) set_dependent_code(*codes);
-  info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone());
-}
-
-
-void AllocationSite::AddDependentCode(Reason reason, Handle<Code> code) {
-  DependentCode::DependencyGroup group = ToDependencyGroup(reason);
-  Handle<DependentCode> codes = DependentCode::Insert(
-      Handle<DependentCode>(dependent_code()), group, code);
-  if (*codes != dependent_code()) set_dependent_code(*codes);
+  if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
+  info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
 }
 
 
@@ -12905,17 +12865,24 @@
 
 
 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) {
-  if (!IsJSArray()) {
-    return this;
-  }
+  if (!IsJSArray()) return this;
 
   Heap* heap = GetHeap();
   if (!heap->InNewSpace(this)) return this;
 
-  AllocationMemento* memento = AllocationMemento::FindForHeapObject(this, heap);
-  if (memento == NULL || !memento->IsValid()) {
-    return this;
-  }
+  // Either object is the last object in the new space, or there is another
+  // object of at least word size (the header map word) following it, so
+  // suffices to compare ptr and top here.
+  Address ptr = address() + JSArray::kSize;
+  Address top = heap->NewSpaceTop();
+  ASSERT(ptr == top || ptr + HeapObject::kHeaderSize <= top);
+  if (ptr == top) return this;
+
+  HeapObject* candidate = HeapObject::FromAddress(ptr);
+  if (candidate->map() != heap->allocation_memento_map()) return this;
+
+  AllocationMemento* memento = AllocationMemento::cast(candidate);
+  if (!memento->IsValid()) return this;
 
   // Walk through to the Allocation Site
   AllocationSite* site = memento->GetAllocationSite();
@@ -16663,14 +16630,6 @@
 }
 
 
-void PropertyCell::AddDependentCode(Handle<Code> code) {
-  Handle<DependentCode> codes = DependentCode::Insert(
-      Handle<DependentCode>(dependent_code()),
-      DependentCode::kPropertyCellChangedGroup, code);
-  if (*codes != dependent_code()) set_dependent_code(*codes);
-}
-
-
 const char* GetBailoutReason(BailoutReason reason) {
   ASSERT(reason < kLastErrorMessage);
 #define ERROR_MESSAGES_TEXTS(C, T) T,
diff --git a/src/objects.h b/src/objects.h
index 1dc54b2..cdf1e24 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -8125,11 +8125,12 @@
   static const int kPretenureMinimumCreated = 100;
 
   // Values for pretenure decision field.
-  enum {
+  enum PretenureDecision {
     kUndecided = 0,
     kDontTenure = 1,
     kTenure = 2,
-    kZombie = 3
+    kZombie = 3,
+    kLastPretenureDecisionValue = kZombie
   };
 
   DECL_ACCESSORS(transition_info, Object)
@@ -8137,11 +8138,8 @@
   // walked in a particular order. So [[1, 2], 1, 2] will have one
   // nested_site, but [[1, 2], 3, [4]] will have a list of two.
   DECL_ACCESSORS(nested_site, Object)
-  DECL_ACCESSORS(memento_found_count, Smi)
-  DECL_ACCESSORS(memento_create_count, Smi)
-  // TODO(mvstanton): we don't need a whole integer to record pretenure
-  // decision. Consider sharing space with memento_found_count.
-  DECL_ACCESSORS(pretenure_decision, Smi)
+  DECL_ACCESSORS(pretenure_data, Smi)
+  DECL_ACCESSORS(pretenure_create_count, Smi)
   DECL_ACCESSORS(dependent_code, DependentCode)
   DECL_ACCESSORS(weak_next, Object)
 
@@ -8150,10 +8148,16 @@
   // This method is expensive, it should only be called for reporting.
   bool IsNestedSite();
 
+  // transition_info bitfields, for constructed array transition info.
   class ElementsKindBits:       public BitField<ElementsKind, 0,  15> {};
   class UnusedBits:             public BitField<int,          15, 14> {};
   class DoNotInlineBit:         public BitField<bool,         29,  1> {};
 
+  // Bitfields for pretenure_data
+  class MementoFoundCountBits:  public BitField<int,          0, 28> {};
+  class PretenureDecisionBits:  public BitField<PretenureDecision, 28, 2> {};
+  STATIC_ASSERT(PretenureDecisionBits::kMax >= kLastPretenureDecisionValue);
+
   // Increments the mementos found counter and returns true when the first
   // memento was found for a given allocation site.
   inline bool IncrementMementoFoundCount();
@@ -8164,12 +8168,39 @@
 
   void ResetPretenureDecision();
 
+  PretenureDecision pretenure_decision() {
+    int value = pretenure_data()->value();
+    return PretenureDecisionBits::decode(value);
+  }
+
+  void set_pretenure_decision(PretenureDecision decision) {
+    int value = pretenure_data()->value();
+    set_pretenure_data(
+        Smi::FromInt(PretenureDecisionBits::update(value, decision)),
+        SKIP_WRITE_BARRIER);
+  }
+
+  int memento_found_count() {
+    int value = pretenure_data()->value();
+    return MementoFoundCountBits::decode(value);
+  }
+
+  inline void set_memento_found_count(int count);
+
+  int memento_create_count() {
+    return pretenure_create_count()->value();
+  }
+
+  void set_memento_create_count(int count) {
+    set_pretenure_create_count(Smi::FromInt(count), SKIP_WRITE_BARRIER);
+  }
+
   // The pretenuring decision is made during gc, and the zombie state allows
   // us to recognize when an allocation site is just being kept alive because
   // a later traversal of new space may discover AllocationMementos that point
   // to this AllocationSite.
   bool IsZombie() {
-    return pretenure_decision()->value() == kZombie;
+    return pretenure_decision() == kZombie;
   }
 
   inline void MarkZombie();
@@ -8213,8 +8244,9 @@
     TRANSITIONS
   };
 
-  void AddDependentCompilationInfo(Reason reason, CompilationInfo* info);
-  void AddDependentCode(Reason reason, Handle<Code> code);
+  static void AddDependentCompilationInfo(Handle<AllocationSite> site,
+                                          Reason reason,
+                                          CompilationInfo* info);
 
   DECLARE_PRINTER(AllocationSite)
   DECLARE_VERIFIER(AllocationSite)
@@ -8227,13 +8259,11 @@
 
   static const int kTransitionInfoOffset = HeapObject::kHeaderSize;
   static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize;
-  static const int kMementoFoundCountOffset = kNestedSiteOffset + kPointerSize;
-  static const int kMementoCreateCountOffset =
-      kMementoFoundCountOffset + kPointerSize;
-  static const int kPretenureDecisionOffset =
-      kMementoCreateCountOffset + kPointerSize;
+  static const int kPretenureDataOffset = kNestedSiteOffset + kPointerSize;
+  static const int kPretenureCreateCountOffset =
+      kPretenureDataOffset + kPointerSize;
   static const int kDependentCodeOffset =
-      kPretenureDecisionOffset + kPointerSize;
+      kPretenureCreateCountOffset + kPointerSize;
   static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize;
   static const int kSize = kWeakNextOffset + kPointerSize;
 
@@ -8250,7 +8280,7 @@
  private:
   inline DependentCode::DependencyGroup ToDependencyGroup(Reason reason);
   bool PretenuringDecisionMade() {
-    return pretenure_decision()->value() != kUndecided;
+    return pretenure_decision() != kUndecided;
   }
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationSite);
@@ -8276,10 +8306,6 @@
   DECLARE_PRINTER(AllocationMemento)
   DECLARE_VERIFIER(AllocationMemento)
 
-  // Returns NULL if no AllocationMemento is available for object.
-  static AllocationMemento* FindForHeapObject(HeapObject* object,
-                                              Heap* heap,
-                                              bool in_GC = false);
   static inline AllocationMemento* cast(Object* obj);
 
  private:
diff --git a/src/version.cc b/src/version.cc
index 0e8630b..5066b9a 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     24
-#define BUILD_NUMBER      14
+#define BUILD_NUMBER      15
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/zone.cc b/src/zone.cc
index 9ee00ed..417f895 100644
--- a/src/zone.cc
+++ b/src/zone.cc
@@ -185,25 +185,31 @@
   // except that we employ a maximum segment size when we delete. This
   // is to avoid excessive malloc() and free() overhead.
   Segment* head = segment_head_;
-  int old_size = (head == NULL) ? 0 : head->size();
-  static const int kSegmentOverhead = sizeof(Segment) + kAlignment;
-  int new_size_no_overhead = size + (old_size << 1);
-  int new_size = kSegmentOverhead + new_size_no_overhead;
+  const size_t old_size = (head == NULL) ? 0 : head->size();
+  static const size_t kSegmentOverhead = sizeof(Segment) + kAlignment;
+  const size_t new_size_no_overhead = size + (old_size << 1);
+  size_t new_size = kSegmentOverhead + new_size_no_overhead;
+  const size_t min_new_size = kSegmentOverhead + static_cast<size_t>(size);
   // Guard against integer overflow.
-  if (new_size_no_overhead < size || new_size < kSegmentOverhead) {
+  if (new_size_no_overhead < static_cast<size_t>(size) ||
+      new_size < static_cast<size_t>(kSegmentOverhead)) {
     V8::FatalProcessOutOfMemory("Zone");
     return NULL;
   }
-  if (new_size < kMinimumSegmentSize) {
+  if (new_size < static_cast<size_t>(kMinimumSegmentSize)) {
     new_size = kMinimumSegmentSize;
-  } else if (new_size > kMaximumSegmentSize) {
+  } else if (new_size > static_cast<size_t>(kMaximumSegmentSize)) {
     // Limit the size of new segments to avoid growing the segment size
     // exponentially, thus putting pressure on contiguous virtual address space.
     // All the while making sure to allocate a segment large enough to hold the
     // requested size.
-    new_size = Max(kSegmentOverhead + size, kMaximumSegmentSize);
+    new_size = Max(min_new_size, static_cast<size_t>(kMaximumSegmentSize));
   }
-  Segment* segment = NewSegment(new_size);
+  if (new_size > INT_MAX) {
+    V8::FatalProcessOutOfMemory("Zone");
+    return NULL;
+  }
+  Segment* segment = NewSegment(static_cast<int>(new_size));
   if (segment == NULL) {
     V8::FatalProcessOutOfMemory("Zone");
     return NULL;
@@ -213,7 +219,10 @@
   Address result = RoundUp(segment->start(), kAlignment);
   position_ = result + size;
   // Check for address overflow.
-  if (position_ < result) {
+  // (Should not happen since the segment is guaranteed to accomodate
+  // size bytes + header and alignment padding)
+  if (reinterpret_cast<uintptr_t>(position_)
+      < reinterpret_cast<uintptr_t>(result)) {
     V8::FatalProcessOutOfMemory("Zone");
     return NULL;
   }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 00465e3..839ddd9 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -14785,9 +14785,10 @@
   // a workaround for now to make this test not fail.
   v8::V8::Initialize();
   v8::Isolate* isolate = CcTest::isolate();
+  HandleScope handle_scope(isolate);
   const char* script = "function foo(a) { return a+1; }";
-  v8::ScriptData* sd =
-      v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+      isolate, script, v8::String::kNormalString, i::StrLength(script)));
   CHECK_NE(sd->Length(), 0);
   CHECK_NE(sd->Data(), NULL);
   CHECK(!sd->HasError());
@@ -14798,9 +14799,10 @@
 TEST(PreCompileWithError) {
   v8::V8::Initialize();
   v8::Isolate* isolate = CcTest::isolate();
+  HandleScope handle_scope(isolate);
   const char* script = "function foo(a) { return 1 * * 2; }";
-  v8::ScriptData* sd =
-      v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+      isolate, script, v8::String::kNormalString, i::StrLength(script)));
   CHECK(sd->HasError());
   delete sd;
 }
@@ -14809,9 +14811,10 @@
 TEST(Regress31661) {
   v8::V8::Initialize();
   v8::Isolate* isolate = CcTest::isolate();
+  HandleScope handle_scope(isolate);
   const char* script = " The Definintive Guide";
-  v8::ScriptData* sd =
-      v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+      isolate, script, v8::String::kNormalString, i::StrLength(script)));
   CHECK(sd->HasError());
   delete sd;
 }
@@ -14821,9 +14824,10 @@
 TEST(PreCompileSerialization) {
   v8::V8::Initialize();
   v8::Isolate* isolate = CcTest::isolate();
+  HandleScope handle_scope(isolate);
   const char* script = "function foo(a) { return a+1; }";
-  v8::ScriptData* sd =
-      v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+      isolate, script, v8::String::kNormalString, i::StrLength(script)));
 
   // Serialize.
   int serialized_data_length = sd->Length();
@@ -14866,8 +14870,8 @@
 
   const char* script = "function foo(){ return 5;}\n"
       "function bar(){ return 6 + 7;}  foo();";
-  v8::ScriptData* sd =
-      v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+      isolate, script, v8::String::kNormalString, i::StrLength(script)));
   CHECK(!sd->HasError());
   // ScriptDataImpl private implementation details
   const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
@@ -14893,7 +14897,8 @@
   // Overwrite function bar's start position with 200.  The function entry
   // will not be found when searching for it by position and we should fall
   // back on eager compilation.
-  sd = v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+  sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+      isolate, script, v8::String::kNormalString, i::StrLength(script)));
   sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
       200;
@@ -14904,42 +14909,6 @@
 }
 
 
-// Verifies that the Handle<String> and const char* versions of the API produce
-// the same results (at least for one trivial case).
-TEST(PreCompileAPIVariationsAreSame) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-
-  const char* cstring = "function foo(a) { return a+1; }";
-
-  v8::ScriptData* sd_from_cstring =
-      v8::ScriptData::PreCompile(isolate, cstring, i::StrLength(cstring));
-
-  TestAsciiResource* resource = new TestAsciiResource(cstring);
-  v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
-      v8::String::NewExternal(isolate, resource));
-
-  v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
-      v8::String::NewFromUtf8(isolate, cstring));
-
-  CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
-  CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
-                     sd_from_external_string->Data(),
-                     sd_from_cstring->Length()));
-
-  CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
-  CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
-                     sd_from_string->Data(),
-                     sd_from_cstring->Length()));
-
-
-  delete sd_from_cstring;
-  delete sd_from_external_string;
-  delete sd_from_string;
-}
-
-
 // This tests that we do not allow dictionary load/call inline caches
 // to use functions that have not yet been compiled.  The potential
 // problem of loading a function that has not yet been compiled can
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index d5fae58..493cbd3 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -2240,7 +2240,7 @@
   CcTest::heap()->SetNewSpaceHighPromotionModeActive(true);
 
   v8::Local<v8::Value> res = CompileRun(
-      "var number_elements = 3000;"
+      "var number_elements = 30000;"
       "var elements = new Array(number_elements);"
       "function DataObject() {"
       "  this.a = [{}];"
@@ -2345,7 +2345,7 @@
   v8::HandleScope scope(CcTest::isolate());
 
   v8::Local<v8::Value> res = CompileRun(
-      "var number_elements = 20000;"
+      "var number_elements = 30000;"
       "var elements = new Array(number_elements);"
       "function f() {"
       "  for (var i = 0; i < number_elements; i++) {"
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index e53250d..8fbd60d 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -108,6 +108,7 @@
 TEST(ScanHTMLEndComments) {
   v8::V8::Initialize();
   v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handles(isolate);
 
   // Regression test. See:
   //    http://code.google.com/p/chromium/issues/detail?id=53548
@@ -144,15 +145,20 @@
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
 
   for (int i = 0; tests[i]; i++) {
-    v8::ScriptData* data =
-        v8::ScriptData::PreCompile(isolate, tests[i], i::StrLength(tests[i]));
+    v8::Handle<v8::String> source = v8::String::NewFromUtf8(
+        isolate, tests[i], v8::String::kNormalString, i::StrLength(tests[i]));
+    v8::ScriptData* data = v8::ScriptData::PreCompile(source);
     CHECK(data != NULL && !data->HasError());
     delete data;
   }
 
   for (int i = 0; fail_tests[i]; i++) {
-    v8::ScriptData* data = v8::ScriptData::PreCompile(
-        isolate, fail_tests[i], i::StrLength(fail_tests[i]));
+    v8::Handle<v8::String> source =
+        v8::String::NewFromUtf8(isolate,
+                                fail_tests[i],
+                                v8::String::kNormalString,
+                                i::StrLength(fail_tests[i]));
+    v8::ScriptData* data = v8::ScriptData::PreCompile(source);
     CHECK(data == NULL || data->HasError());
     delete data;
   }
@@ -199,8 +205,8 @@
   const char* error_source = "var x = y z;";
   int error_source_length = i::StrLength(error_source);
 
-  v8::ScriptData* preparse =
-      v8::ScriptData::PreCompile(isolate, source, source_length);
+  v8::ScriptData* preparse = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+      isolate, source, v8::String::kNormalString, source_length));
   CHECK(!preparse->HasError());
   bool lazy_flag = i::FLAG_lazy;
   {
@@ -223,8 +229,11 @@
   i::FLAG_lazy = lazy_flag;
 
   // Syntax error.
-  v8::ScriptData* error_preparse =
-      v8::ScriptData::PreCompile(isolate, error_source, error_source_length);
+  v8::ScriptData* error_preparse = v8::ScriptData::PreCompile(
+      v8::String::NewFromUtf8(isolate,
+                              error_source,
+                              v8::String::kNormalString,
+                              error_source_length));
   CHECK(error_preparse->HasError());
   i::ScriptDataImpl *pre_impl =
       reinterpret_cast<i::ScriptDataImpl*>(error_preparse);
diff --git a/test/mjsunit/arguments-apply-deopt.js b/test/mjsunit/arguments-apply-deopt.js
new file mode 100644
index 0000000..b7251af
--- /dev/null
+++ b/test/mjsunit/arguments-apply-deopt.js
@@ -0,0 +1,77 @@
+// 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.
+
+// Flags: --allow-natives-syntax
+
+(function ApplyArgumentsDeoptInReceiverMapCheck() {
+  function invoker(h, r) {
+    return function XXXXX() {
+      var res = h.apply({ fffffff : r(this) }, arguments);
+      return res;
+    };
+  }
+
+  var y = invoker(m, selfOf);
+
+  function selfOf(c) {
+    var sssss = c.self_;
+    return sssss;
+  }
+
+  function m() {
+    return this.fffffff;
+  }
+
+  y.apply({ self_ : 3 });
+  y.apply({ self_ : 3 });
+  y.apply({ self_ : 3 });
+
+  %OptimizeFunctionOnNextCall(y);
+
+  assertEquals(y.apply({ self_ : 3, uuu : 4 }), 3);
+})();
+
+(function ApplyArgumentsDeoptInReceiverExplicit() {
+  function f() { return this + 21; }
+
+  function deopt() {
+    %DeoptimizeFunction(XXXXX);
+    return 21;
+  }
+
+  function XXXXX() {
+    return f.apply(deopt(), arguments);
+  };
+
+  XXXXX();
+  XXXXX();
+  XXXXX();
+
+  %OptimizeFunctionOnNextCall(XXXXX);
+
+  assertEquals(42, XXXXX());
+})();
diff --git a/test/mjsunit/elements-kind.js b/test/mjsunit/elements-kind.js
index 857637c..b02af65 100644
--- a/test/mjsunit/elements-kind.js
+++ b/test/mjsunit/elements-kind.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
-// Flags: --nostress-opt
+// Flags: --nostress-opt --nostress-compaction --gc-interval=-1
 
 // Test element kind of objects.
 // Since --smi-only-arrays affects builtins, its default setting at compile