Upgrade V8 to version 4.9.385.28

https://chromium.googlesource.com/v8/v8/+/4.9.385.28

FPIIM-449

Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/api.cc b/src/api.cc
index a459076..8274a73 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -9,9 +9,14 @@
 #include <sanitizer/asan_interface.h>
 #endif  // V8_USE_ADDRESS_SANITIZER
 #include <cmath>  // For isnan.
+#include <limits>
+#include <vector>
 #include "include/v8-debug.h"
+#include "include/v8-experimental.h"
 #include "include/v8-profiler.h"
 #include "include/v8-testing.h"
+#include "src/api-experimental.h"
+#include "src/api-natives.h"
 #include "src/assert-scope.h"
 #include "src/background-parsing-task.h"
 #include "src/base/functional.h"
@@ -19,80 +24,192 @@
 #include "src/base/platform/time.h"
 #include "src/base/utils/random-number-generator.h"
 #include "src/bootstrapper.h"
+#include "src/char-predicates-inl.h"
 #include "src/code-stubs.h"
 #include "src/compiler.h"
+#include "src/context-measure.h"
+#include "src/contexts.h"
 #include "src/conversions-inl.h"
 #include "src/counters.h"
-#include "src/cpu-profiler.h"
-#include "src/debug.h"
+#include "src/debug/debug.h"
 #include "src/deoptimizer.h"
 #include "src/execution.h"
 #include "src/global-handles.h"
-#include "src/heap-profiler.h"
-#include "src/heap-snapshot-generator-inl.h"
 #include "src/icu_util.h"
-#include "src/json-parser.h"
+#include "src/isolate-inl.h"
 #include "src/messages.h"
-#include "src/natives.h"
-#include "src/parser.h"
-#include "src/profile-generator-inl.h"
+#include "src/parsing/json-parser.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/scanner-character-streams.h"
+#include "src/pending-compilation-error-handler.h"
+#include "src/profiler/cpu-profiler.h"
+#include "src/profiler/heap-profiler.h"
+#include "src/profiler/heap-snapshot-generator-inl.h"
+#include "src/profiler/profile-generator-inl.h"
+#include "src/profiler/sampler.h"
 #include "src/property.h"
+#include "src/property-descriptor.h"
 #include "src/property-details.h"
 #include "src/prototype.h"
 #include "src/runtime/runtime.h"
 #include "src/runtime-profiler.h"
-#include "src/sampler.h"
-#include "src/scanner-character-streams.h"
 #include "src/simulator.h"
-#include "src/snapshot.h"
+#include "src/snapshot/natives.h"
+#include "src/snapshot/snapshot.h"
+#include "src/startup-data-util.h"
 #include "src/unicode-inl.h"
+#include "src/v8.h"
 #include "src/v8threads.h"
 #include "src/version.h"
 #include "src/vm-state-inl.h"
 
 
-#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
-
-#define ENTER_V8(isolate)             \
-  i::VMState<v8::OTHER> __state__((isolate))
-
 namespace v8 {
 
-#define ON_BAILOUT(isolate, location, code)                        \
-  if (IsExecutionTerminatingCheck(isolate)) {                      \
-    code;                                                          \
-    UNREACHABLE();                                                 \
-  }
+#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
 
 
-#define EXCEPTION_PREAMBLE(isolate)                                         \
-  (isolate)->handle_scope_implementer()->IncrementCallDepth();              \
-  DCHECK(!(isolate)->external_caught_exception());                          \
+#define ENTER_V8(isolate) i::VMState<v8::OTHER> __state__((isolate))
+
+
+#define PREPARE_FOR_EXECUTION_GENERIC(isolate, context, function_name, \
+                                      bailout_value, HandleScopeClass, \
+                                      do_callback)                     \
+  if (IsExecutionTerminatingCheck(isolate)) {                          \
+    return bailout_value;                                              \
+  }                                                                    \
+  HandleScopeClass handle_scope(isolate);                              \
+  CallDepthScope call_depth_scope(isolate, context, do_callback);      \
+  LOG_API(isolate, function_name);                                     \
+  ENTER_V8(isolate);                                                   \
   bool has_pending_exception = false
 
 
-#define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback)           \
-  do {                                                                         \
-    i::HandleScopeImplementer* handle_scope_implementer =                      \
-        (isolate)->handle_scope_implementer();                                 \
-    handle_scope_implementer->DecrementCallDepth();                            \
-    if (has_pending_exception) {                                               \
-      bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();   \
-      (isolate)->OptionalRescheduleException(call_depth_is_zero);              \
-      do_callback                                                              \
-      return value;                                                            \
-    }                                                                          \
-    do_callback                                                                \
+#define PREPARE_FOR_EXECUTION_WITH_CONTEXT(                                  \
+    context, function_name, bailout_value, HandleScopeClass, do_callback)    \
+  auto isolate = context.IsEmpty()                                           \
+                     ? i::Isolate::Current()                                 \
+                     : reinterpret_cast<i::Isolate*>(context->GetIsolate()); \
+  PREPARE_FOR_EXECUTION_GENERIC(isolate, context, function_name,             \
+                                bailout_value, HandleScopeClass, do_callback);
+
+
+#define PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, function_name, T)     \
+  PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(), function_name, \
+                                MaybeLocal<T>(), InternalEscapableScope,  \
+                                false);
+
+
+#define PREPARE_FOR_EXECUTION(context, function_name, T)                      \
+  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, function_name, MaybeLocal<T>(), \
+                                     InternalEscapableScope, false)
+
+
+#define PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, function_name, T)        \
+  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, function_name, MaybeLocal<T>(), \
+                                     InternalEscapableScope, true)
+
+
+#define PREPARE_FOR_EXECUTION_PRIMITIVE(context, function_name, T)         \
+  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, function_name, Nothing<T>(), \
+                                     i::HandleScope, false)
+
+
+#define EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, value) \
+  do {                                                 \
+    if (has_pending_exception) {                       \
+      call_depth_scope.Escape();                       \
+      return value;                                    \
+    }                                                  \
   } while (false)
 
 
-#define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value)                    \
-  EXCEPTION_BAILOUT_CHECK_GENERIC(                                             \
-      isolate, value, isolate->FireCallCompletedCallback();)
+#define RETURN_ON_FAILED_EXECUTION(T) \
+  EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, MaybeLocal<T>())
 
 
-#define EXCEPTION_BAILOUT_CHECK(isolate, value)                                \
-  EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;)
+#define RETURN_ON_FAILED_EXECUTION_PRIMITIVE(T) \
+  EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, Nothing<T>())
+
+
+#define RETURN_TO_LOCAL_UNCHECKED(maybe_local, T) \
+  return maybe_local.FromMaybe(Local<T>());
+
+
+#define RETURN_ESCAPED(value) return handle_scope.Escape(value);
+
+
+namespace {
+
+Local<Context> ContextFromHeapObject(i::Handle<i::Object> obj) {
+  return reinterpret_cast<v8::Isolate*>(i::HeapObject::cast(*obj)->GetIsolate())
+      ->GetCurrentContext();
+}
+
+class InternalEscapableScope : public v8::EscapableHandleScope {
+ public:
+  explicit inline InternalEscapableScope(i::Isolate* isolate)
+      : v8::EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {}
+};
+
+
+class CallDepthScope {
+ public:
+  explicit CallDepthScope(i::Isolate* isolate, Local<Context> context,
+                          bool do_callback)
+      : isolate_(isolate),
+        context_(context),
+        escaped_(false),
+        do_callback_(do_callback) {
+    // TODO(dcarney): remove this when blink stops crashing.
+    DCHECK(!isolate_->external_caught_exception());
+    isolate_->IncrementJsCallsFromApiCounter();
+    isolate_->handle_scope_implementer()->IncrementCallDepth();
+    if (!context_.IsEmpty()) context_->Enter();
+  }
+  ~CallDepthScope() {
+    if (!context_.IsEmpty()) context_->Exit();
+    if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth();
+    if (do_callback_) isolate_->FireCallCompletedCallback();
+  }
+
+  void Escape() {
+    DCHECK(!escaped_);
+    escaped_ = true;
+    auto handle_scope_implementer = isolate_->handle_scope_implementer();
+    handle_scope_implementer->DecrementCallDepth();
+    bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();
+    isolate_->OptionalRescheduleException(call_depth_is_zero);
+  }
+
+ private:
+  i::Isolate* const isolate_;
+  Local<Context> context_;
+  bool escaped_;
+  bool do_callback_;
+};
+
+}  // namespace
+
+
+static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate,
+                                             i::Handle<i::Script> script) {
+  i::Handle<i::Object> scriptName(i::Script::GetNameOrSourceURL(script));
+  i::Handle<i::Object> source_map_url(script->source_mapping_url(), isolate);
+  v8::Isolate* v8_isolate =
+      reinterpret_cast<v8::Isolate*>(script->GetIsolate());
+  ScriptOriginOptions options(script->origin_options());
+  v8::ScriptOrigin origin(
+      Utils::ToLocal(scriptName),
+      v8::Integer::New(v8_isolate, script->line_offset()),
+      v8::Integer::New(v8_isolate, script->column_offset()),
+      v8::Boolean::New(v8_isolate, options.IsSharedCrossOrigin()),
+      v8::Integer::New(v8_isolate, script->id()),
+      v8::Boolean::New(v8_isolate, options.IsEmbedderDebugScript()),
+      Utils::ToLocal(source_map_url),
+      v8::Boolean::New(v8_isolate, options.IsOpaque()));
+  return origin;
+}
 
 
 // --- E x c e p t i o n   B e h a v i o r ---
@@ -106,6 +223,12 @@
 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
 // The default fatal error handler is called and execution is stopped.
 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
+  i::Isolate* isolate = i::Isolate::Current();
+  char last_few_messages[Heap::kTraceRingBufferSize + 1];
+  char js_stacktrace[Heap::kStacktraceBufferSize + 1];
+  memset(last_few_messages, 0, Heap::kTraceRingBufferSize + 1);
+  memset(js_stacktrace, 0, Heap::kStacktraceBufferSize + 1);
+
   i::HeapStats heap_stats;
   int start_marker;
   heap_stats.start_marker = &start_marker;
@@ -113,14 +236,10 @@
   heap_stats.new_space_size = &new_space_size;
   int new_space_capacity;
   heap_stats.new_space_capacity = &new_space_capacity;
-  intptr_t old_pointer_space_size;
-  heap_stats.old_pointer_space_size = &old_pointer_space_size;
-  intptr_t old_pointer_space_capacity;
-  heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
-  intptr_t old_data_space_size;
-  heap_stats.old_data_space_size = &old_data_space_size;
-  intptr_t old_data_space_capacity;
-  heap_stats.old_data_space_capacity = &old_data_space_capacity;
+  intptr_t old_space_size;
+  heap_stats.old_space_size = &old_space_size;
+  intptr_t old_space_capacity;
+  heap_stats.old_space_capacity = &old_space_capacity;
   intptr_t code_space_size;
   heap_stats.code_space_size = &code_space_size;
   intptr_t code_space_capacity;
@@ -129,14 +248,6 @@
   heap_stats.map_space_size = &map_space_size;
   intptr_t map_space_capacity;
   heap_stats.map_space_capacity = &map_space_capacity;
-  intptr_t cell_space_size;
-  heap_stats.cell_space_size = &cell_space_size;
-  intptr_t cell_space_capacity;
-  heap_stats.cell_space_capacity = &cell_space_capacity;
-  intptr_t property_cell_space_size;
-  heap_stats.property_cell_space_size = &property_cell_space_size;
-  intptr_t property_cell_space_capacity;
-  heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
   intptr_t lo_space_size;
   heap_stats.lo_space_size = &lo_space_size;
   int global_handle_count;
@@ -159,13 +270,19 @@
   heap_stats.size_per_type = size_per_type;
   int os_error;
   heap_stats.os_error = &os_error;
+  heap_stats.last_few_messages = last_few_messages;
+  heap_stats.js_stacktrace = js_stacktrace;
   int end_marker;
   heap_stats.end_marker = &end_marker;
-  i::Isolate* isolate = i::Isolate::Current();
   if (isolate->heap()->HasBeenSetUp()) {
     // BUG(1718): Don't use the take_snapshot since we don't support
     // HeapIterator here without doing a special GC.
     isolate->heap()->RecordStats(&heap_stats, false);
+    char* first_newline = strchr(last_few_messages, '\n');
+    if (first_newline == NULL || first_newline[1] == '\0')
+      first_newline = last_few_messages;
+    PrintF("\n<--- Last few GCs --->\n%s\n", first_newline);
+    PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace);
   }
   Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
   // If the fatal error handler returns, we stop execution.
@@ -206,30 +323,99 @@
 }
 
 
-StartupData V8::CreateSnapshotDataBlob() {
-  Isolate::CreateParams params;
-  params.enable_serializer = true;
-  Isolate* isolate = v8::Isolate::New(params);
+bool RunExtraCode(Isolate* isolate, Local<Context> context,
+                  const char* utf8_source) {
+  // Run custom script if provided.
+  base::ElapsedTimer timer;
+  timer.Start();
+  TryCatch try_catch(isolate);
+  Local<String> source_string;
+  if (!String::NewFromUtf8(isolate, utf8_source, NewStringType::kNormal)
+           .ToLocal(&source_string)) {
+    return false;
+  }
+  Local<String> resource_name =
+      String::NewFromUtf8(isolate, "<embedded script>", NewStringType::kNormal)
+          .ToLocalChecked();
+  ScriptOrigin origin(resource_name);
+  ScriptCompiler::Source source(source_string, origin);
+  Local<Script> script;
+  if (!ScriptCompiler::Compile(context, &source).ToLocal(&script)) return false;
+  if (script->Run(context).IsEmpty()) return false;
+  if (i::FLAG_profile_deserialization) {
+    i::PrintF("Executing custom snapshot script took %0.3f ms\n",
+              timer.Elapsed().InMillisecondsF());
+  }
+  timer.Stop();
+  CHECK(!try_catch.HasCaught());
+  return true;
+}
+
+
+namespace {
+
+class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
+ public:
+  virtual void* Allocate(size_t length) {
+    void* data = AllocateUninitialized(length);
+    return data == NULL ? data : memset(data, 0, length);
+  }
+  virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
+  virtual void Free(void* data, size_t) { free(data); }
+};
+
+}  // namespace
+
+
+StartupData V8::CreateSnapshotDataBlob(const char* custom_source) {
+  i::Isolate* internal_isolate = new i::Isolate(true);
+  ArrayBufferAllocator allocator;
+  internal_isolate->set_array_buffer_allocator(&allocator);
+  Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
   StartupData result = {NULL, 0};
   {
+    base::ElapsedTimer timer;
+    timer.Start();
     Isolate::Scope isolate_scope(isolate);
-    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+    internal_isolate->Init(NULL);
     Persistent<Context> context;
+    i::Snapshot::Metadata metadata;
     {
       HandleScope handle_scope(isolate);
-      context.Reset(isolate, Context::New(isolate));
+      Local<Context> new_context = Context::New(isolate);
+      context.Reset(isolate, new_context);
+      if (custom_source != NULL) {
+        metadata.set_embeds_script(true);
+        Context::Scope context_scope(new_context);
+        if (!RunExtraCode(isolate, new_context, custom_source)) context.Reset();
+      }
     }
     if (!context.IsEmpty()) {
-      // Make sure all builtin scripts are cached.
-      {
-        HandleScope scope(isolate);
-        for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
-          internal_isolate->bootstrapper()->NativesSourceLookup(i);
-        }
-      }
       // If we don't do this then we end up with a stray root pointing at the
       // context even after we have disposed of the context.
       internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
+
+      // GC may have cleared weak cells, so compact any WeakFixedArrays
+      // found on the heap.
+      i::HeapIterator iterator(internal_isolate->heap(),
+                               i::HeapIterator::kFilterUnreachable);
+      for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
+        if (o->IsPrototypeInfo()) {
+          i::Object* prototype_users =
+              i::PrototypeInfo::cast(o)->prototype_users();
+          if (prototype_users->IsWeakFixedArray()) {
+            i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users);
+            array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>();
+          }
+        } else if (o->IsScript()) {
+          i::Object* shared_list = i::Script::cast(o)->shared_function_infos();
+          if (shared_list->IsWeakFixedArray()) {
+            i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list);
+            array->Compact<i::WeakFixedArray::NullCallback>();
+          }
+        }
+      }
+
       i::Object* raw_context = *v8::Utils::OpenPersistent(context);
       context.Reset();
 
@@ -240,13 +426,15 @@
       i::SnapshotByteSink context_sink;
       i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
       context_ser.Serialize(&raw_context);
-      ser.SerializeWeakReferences();
+      ser.SerializeWeakReferencesAndDeferred();
 
-      i::SnapshotData sd(snapshot_sink, ser);
-      i::SnapshotData csd(context_sink, context_ser);
-
-      result = i::Snapshot::CreateSnapshotBlob(sd.RawData(), csd.RawData());
+      result = i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
     }
+    if (i::FLAG_profile_deserialization) {
+      i::PrintF("Creating snapshot took %0.3f ms\n",
+                timer.Elapsed().InMillisecondsF());
+    }
+    timer.Stop();
   }
   isolate->Dispose();
   return result;
@@ -315,12 +503,10 @@
       max_old_space_size_(0),
       max_executable_size_(0),
       stack_limit_(NULL),
-      max_available_threads_(0),
       code_range_size_(0) { }
 
 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
-                                            uint64_t virtual_memory_limit,
-                                            uint32_t number_of_processors) {
+                                            uint64_t virtual_memory_limit) {
 #if V8_OS_ANDROID
   // Android has higher physical memory requirements before raising the maximum
   // heap size limits since it has no swap space.
@@ -351,8 +537,6 @@
     set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice);
   }
 
-  set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u));
-
   if (virtual_memory_limit > 0 && i::kRequiresCodeRange) {
     // Reserve no more than 1/8 of the memory for the code range, but at most
     // kMaximalCodeRangeSize.
@@ -378,8 +562,6 @@
     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints.stack_limit());
     isolate->stack_guard()->SetStackLimit(limit);
   }
-
-  isolate->set_max_available_threads(constraints.max_available_threads());
 }
 
 
@@ -387,7 +569,9 @@
   LOG_API(isolate, "Persistent::New");
   i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
 #ifdef VERIFY_HEAP
-  (*obj)->ObjectVerify();
+  if (i::FLAG_verify_heap) {
+    (*obj)->ObjectVerify();
+  }
 #endif  // VERIFY_HEAP
   return result.location();
 }
@@ -396,7 +580,9 @@
 i::Object** V8::CopyPersistent(i::Object** obj) {
   i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj);
 #ifdef VERIFY_HEAP
-  (*obj)->ObjectVerify();
+  if (i::FLAG_verify_heap) {
+    (*obj)->ObjectVerify();
+  }
 #endif  // VERIFY_HEAP
   return result.location();
 }
@@ -408,18 +594,29 @@
 }
 
 
-void V8::MakePhantom(i::Object** object, void* parameter,
-                     PhantomCallbackData<void>::Callback weak_callback) {
-  i::GlobalHandles::MakePhantom(object, parameter, weak_callback);
+void V8::MakeWeak(i::Object** object, void* parameter,
+                  int internal_field_index1, int internal_field_index2,
+                  WeakCallbackInfo<void>::Callback weak_callback) {
+  WeakCallbackType type = WeakCallbackType::kParameter;
+  if (internal_field_index1 == 0) {
+    if (internal_field_index2 == 1) {
+      type = WeakCallbackType::kInternalFields;
+    } else {
+      DCHECK_EQ(internal_field_index2, -1);
+      type = WeakCallbackType::kInternalFields;
+    }
+  } else {
+    DCHECK_EQ(internal_field_index1, -1);
+    DCHECK_EQ(internal_field_index2, -1);
+  }
+  i::GlobalHandles::MakeWeak(object, parameter, weak_callback, type);
 }
 
 
-void V8::MakePhantom(
-    i::Object** object,
-    InternalFieldsCallbackData<void, void>::Callback weak_callback,
-    int internal_field_index1, int internal_field_index2) {
-  i::GlobalHandles::MakePhantom(object, weak_callback, internal_field_index1,
-                                internal_field_index2);
+void V8::MakeWeak(i::Object** object, void* parameter,
+                  WeakCallbackInfo<void>::Callback weak_callback,
+                  WeakCallbackType type) {
+  i::GlobalHandles::MakeWeak(object, parameter, weak_callback, type);
 }
 
 
@@ -446,6 +643,23 @@
 }
 
 
+void V8::FromJustIsNothing() {
+  Utils::ApiCheck(false, "v8::FromJust", "Maybe value is Nothing.");
+}
+
+
+void V8::ToLocalEmpty() {
+  Utils::ApiCheck(false, "v8::ToLocalChecked", "Empty MaybeLocal.");
+}
+
+
+void V8::InternalFieldOutOfBounds(int index) {
+  Utils::ApiCheck(0 <= index && index < kInternalFieldsInWeakCallback,
+                  "WeakCallbackInfo::GetInternalField",
+                  "Internal field out of bounds.");
+}
+
+
 // --- H a n d l e s ---
 
 
@@ -459,10 +673,14 @@
   // We do not want to check the correct usage of the Locker class all over the
   // place, so we do it only here: Without a HandleScope, an embedder can do
   // almost nothing, so it is enough to check in this central place.
-  Utils::ApiCheck(!v8::Locker::IsActive() ||
-                  internal_isolate->thread_manager()->IsLockedByCurrentThread(),
-                  "HandleScope::HandleScope",
-                  "Entering the V8 API without proper locking in place");
+  // We make an exception if the serializer is enabled, which means that the
+  // Isolate is exclusively used to create a snapshot.
+  Utils::ApiCheck(
+      !v8::Locker::IsActive() ||
+          internal_isolate->thread_manager()->IsLockedByCurrentThread() ||
+          internal_isolate->serializer_enabled(),
+      "HandleScope::HandleScope",
+      "Entering the V8 API without proper locking in place");
   i::HandleScopeData* current = internal_isolate->handle_scope_data();
   isolate_ = internal_isolate;
   prev_next_ = current->next;
@@ -515,6 +733,27 @@
 }
 
 
+SealHandleScope::SealHandleScope(Isolate* isolate) {
+  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+
+  isolate_ = internal_isolate;
+  i::HandleScopeData* current = internal_isolate->handle_scope_data();
+  prev_limit_ = current->limit;
+  current->limit = current->next;
+  prev_sealed_level_ = current->sealed_level;
+  current->sealed_level = current->level;
+}
+
+
+SealHandleScope::~SealHandleScope() {
+  i::HandleScopeData* current = isolate_->handle_scope_data();
+  DCHECK_EQ(current->next, current->limit);
+  current->limit = prev_limit_;
+  DCHECK_EQ(current->level, current->sealed_level);
+  current->sealed_level = prev_sealed_level_;
+}
+
+
 void Context::Enter() {
   i::Handle<i::Context> env = Utils::OpenHandle(this);
   i::Isolate* isolate = env->GetIsolate();
@@ -559,6 +798,7 @@
                                                 bool can_grow,
                                                 const char* location) {
   i::Handle<i::Context> env = Utils::OpenHandle(context);
+  i::Isolate* isolate = env->GetIsolate();
   bool ok =
       Utils::ApiCheck(env->IsNativeContext(),
                       location,
@@ -571,7 +811,8 @@
     return i::Handle<i::FixedArray>();
   }
   int new_size = i::Max(index, data->length() << 1) + 1;
-  data = i::FixedArray::CopySize(data, new_size);
+  int grow_by = new_size - data->length();
+  data = isolate->factory()->CopyFixedArrayAndGrow(data, grow_by);
   env->set_embedder_data(*data);
   return data;
 }
@@ -586,7 +827,7 @@
 }
 
 
-void Context::SetEmbedderData(int index, v8::Handle<Value> value) {
+void Context::SetEmbedderData(int index, v8::Local<Value> value) {
   const char* location = "v8::Context::SetEmbedderData()";
   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
   if (data.is_null()) return;
@@ -645,8 +886,8 @@
 
 
 i::Object* NeanderArray::get(int offset) {
-  DCHECK(0 <= offset);
-  DCHECK(offset < length());
+  DCHECK_LE(0, offset);
+  DCHECK_LT(offset, length());
   return obj_.get(offset + 1);
 }
 
@@ -681,43 +922,21 @@
 
 
 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
+  that->set_number_of_properties(0);
   that->set_tag(i::Smi::FromInt(type));
 }
 
 
-static void TemplateSet(i::Isolate* isolate,
-                        v8::Template* templ,
-                        int length,
-                        v8::Handle<v8::Data>* data) {
-  i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
-  if (list->IsUndefined()) {
-    list = NeanderArray(isolate).value();
-    Utils::OpenHandle(templ)->set_property_list(*list);
-  }
-  NeanderArray array(list);
-  array.add(isolate, isolate->factory()->NewNumberFromInt(length));
-  for (int i = 0; i < length; i++) {
-    i::Handle<i::Object> value = data[i].IsEmpty() ?
-        i::Handle<i::Object>(isolate->factory()->undefined_value()) :
-        Utils::OpenHandle(*data[i]);
-    array.add(isolate, value);
-  }
-}
-
-
-void Template::Set(v8::Handle<Name> name,
-                   v8::Handle<Data> value,
+void Template::Set(v8::Local<Name> name, v8::Local<Data> value,
                    v8::PropertyAttribute attribute) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  auto templ = Utils::OpenHandle(this);
+  i::Isolate* isolate = templ->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  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)};
-  TemplateSet(isolate, this, kSize, data);
+  // TODO(dcarney): split api to allow values of v8::Value or v8::TemplateInfo.
+  i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
+                                 Utils::OpenHandle(*value),
+                                 static_cast<i::PropertyAttributes>(attribute));
 }
 
 
@@ -729,26 +948,23 @@
     v8::AccessControl access_control) {
   // TODO(verwaest): Remove |access_control|.
   DCHECK_EQ(v8::DEFAULT, access_control);
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  auto templ = Utils::OpenHandle(this);
+  auto isolate = templ->GetIsolate();
   ENTER_V8(isolate);
   DCHECK(!name.IsEmpty());
   DCHECK(!getter.IsEmpty() || !setter.IsEmpty());
   i::HandleScope scope(isolate);
-  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)};
-  TemplateSet(isolate, this, kSize, data);
+  i::ApiNatives::AddAccessorProperty(
+      isolate, templ, Utils::OpenHandle(*name),
+      Utils::OpenHandle(*getter, true), Utils::OpenHandle(*setter, true),
+      static_cast<i::PropertyAttributes>(attribute));
 }
 
 
 // --- F u n c t i o n   T e m p l a t e ---
 static void InitializeFunctionTemplate(
     i::Handle<i::FunctionTemplateInfo> info) {
-  info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
+  InitializeTemplate(info, Consts::FUNCTION_TEMPLATE);
   info->set_flag(0);
 }
 
@@ -767,20 +983,26 @@
 }
 
 
-void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+static void EnsureNotInstantiated(i::Handle<i::FunctionTemplateInfo> info,
+                                  const char* func) {
+  Utils::ApiCheck(!info->instantiated(), func,
+                  "FunctionTemplate already instantiated");
+}
+
+
+void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) {
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::Inherit");
+  i::Isolate* isolate = info->GetIsolate();
   ENTER_V8(isolate);
-  Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
+  info->set_parent_template(*Utils::OpenHandle(*value));
 }
 
 
 static Local<FunctionTemplate> FunctionTemplateNew(
-    i::Isolate* isolate,
-    FunctionCallback callback,
-    v8::Handle<Value> data,
-    v8::Handle<Signature> signature,
-    int length,
-    bool do_not_cache) {
+    i::Isolate* isolate, FunctionCallback callback,
+    experimental::FastAccessorBuilder* fast_handler, v8::Local<Value> data,
+    v8::Local<Signature> signature, int length, bool do_not_cache) {
   i::Handle<i::Struct> struct_obj =
       isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
   i::Handle<i::FunctionTemplateInfo> obj =
@@ -797,223 +1019,71 @@
     if (data.IsEmpty()) {
       data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
     }
-    Utils::ToLocal(obj)->SetCallHandler(callback, data);
+    Utils::ToLocal(obj)->SetCallHandler(callback, data, fast_handler);
   }
   obj->set_length(length);
   obj->set_undetectable(false);
   obj->set_needs_access_check(false);
+  obj->set_accept_any_receiver(true);
   if (!signature.IsEmpty())
     obj->set_signature(*Utils::OpenHandle(*signature));
   return Utils::ToLocal(obj);
 }
 
-Local<FunctionTemplate> FunctionTemplate::New(
-    Isolate* isolate,
-    FunctionCallback callback,
-    v8::Handle<Value> data,
-    v8::Handle<Signature> signature,
-    int length) {
+
+Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate,
+                                              FunctionCallback callback,
+                                              v8::Local<Value> data,
+                                              v8::Local<Signature> signature,
+                                              int length) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   // Changes to the environment cannot be captured in the snapshot. Expect no
   // function templates when the isolate is created for serialization.
   DCHECK(!i_isolate->serializer_enabled());
   LOG_API(i_isolate, "FunctionTemplate::New");
   ENTER_V8(i_isolate);
-  return FunctionTemplateNew(
-      i_isolate, callback, data, signature, length, false);
+  return FunctionTemplateNew(i_isolate, callback, nullptr, data, signature,
+                             length, false);
+}
+
+
+Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler(
+    Isolate* isolate, FunctionCallback callback,
+    experimental::FastAccessorBuilder* fast_handler, v8::Local<Value> data,
+    v8::Local<Signature> signature, int length) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  DCHECK(!i_isolate->serializer_enabled());
+  LOG_API(i_isolate, "FunctionTemplate::NewWithFastHandler");
+  ENTER_V8(i_isolate);
+  return FunctionTemplateNew(i_isolate, callback, fast_handler, data, signature,
+                             length, false);
 }
 
 
 Local<Signature> Signature::New(Isolate* isolate,
-                                Handle<FunctionTemplate> receiver, int argc,
-                                Handle<FunctionTemplate> argv[]) {
-  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Signature::New");
-  ENTER_V8(i_isolate);
-  i::Handle<i::Struct> struct_obj =
-      i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
-  i::Handle<i::SignatureInfo> obj =
-      i::Handle<i::SignatureInfo>::cast(struct_obj);
-  if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
-  if (argc > 0) {
-    i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc);
-    for (int i = 0; i < argc; i++) {
-      if (!argv[i].IsEmpty())
-        args->set(i, *Utils::OpenHandle(*argv[i]));
-    }
-    obj->set_args(*args);
-  }
-  return Utils::ToLocal(obj);
+                                Local<FunctionTemplate> receiver) {
+  return Utils::SignatureToLocal(Utils::OpenHandle(*receiver));
 }
 
 
 Local<AccessorSignature> AccessorSignature::New(
-    Isolate* isolate,
-    Handle<FunctionTemplate> receiver) {
+    Isolate* isolate, Local<FunctionTemplate> receiver) {
   return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
 }
 
 
-template<typename Operation>
-static Local<Operation> NewDescriptor(
-    Isolate* isolate,
-    const i::DeclaredAccessorDescriptorData& data,
-    Data* previous_descriptor) {
-  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  i::Handle<i::DeclaredAccessorDescriptor> previous =
-      i::Handle<i::DeclaredAccessorDescriptor>();
-  if (previous_descriptor != NULL) {
-    previous = Utils::OpenHandle(
-        static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
-  }
-  i::Handle<i::DeclaredAccessorDescriptor> descriptor =
-      i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
-  return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor);
-}
-
-
-Local<RawOperationDescriptor>
-ObjectOperationDescriptor::NewInternalFieldDereference(
-    Isolate* isolate,
-    int internal_field) {
-  i::DeclaredAccessorDescriptorData data;
-  data.type = i::kDescriptorObjectDereference;
-  data.object_dereference_descriptor.internal_field = internal_field;
-  return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL);
-}
-
-
-Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift(
-    Isolate* isolate,
-    int16_t byte_offset) {
-  i::DeclaredAccessorDescriptorData data;
-  data.type = i::kDescriptorPointerShift;
-  data.pointer_shift_descriptor.byte_offset = byte_offset;
-  return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
-}
-
-
-Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference(
-    Isolate* isolate) {
-  i::DeclaredAccessorDescriptorData data;
-  data.type = i::kDescriptorReturnObject;
-  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
-}
-
-
-Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference(
-    Isolate* isolate) {
-  i::DeclaredAccessorDescriptorData data;
-  data.type = i::kDescriptorPointerDereference;
-  return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
-}
-
-
-Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare(
-    Isolate* isolate,
-    void* compare_value) {
-  i::DeclaredAccessorDescriptorData data;
-  data.type = i::kDescriptorPointerCompare;
-  data.pointer_compare_descriptor.compare_value = compare_value;
-  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
-}
-
-
-Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue(
-    Isolate* isolate,
-    DeclaredAccessorDescriptorDataType data_type,
-    uint8_t bool_offset) {
-  i::DeclaredAccessorDescriptorData data;
-  data.type = i::kDescriptorPrimitiveValue;
-  data.primitive_value_descriptor.data_type = data_type;
-  data.primitive_value_descriptor.bool_offset = bool_offset;
-  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
-}
-
-
-template<typename T>
-static Local<DeclaredAccessorDescriptor> NewBitmaskCompare(
-    Isolate* isolate,
-    T bitmask,
-    T compare_value,
-    RawOperationDescriptor* operation) {
-  i::DeclaredAccessorDescriptorData data;
-  data.type = i::kDescriptorBitmaskCompare;
-  data.bitmask_compare_descriptor.bitmask = bitmask;
-  data.bitmask_compare_descriptor.compare_value = compare_value;
-  data.bitmask_compare_descriptor.size = sizeof(T);
-  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation);
-}
-
-
-Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8(
-    Isolate* isolate,
-    uint8_t bitmask,
-    uint8_t compare_value) {
-  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
-}
-
-
-Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16(
-    Isolate* isolate,
-    uint16_t bitmask,
-    uint16_t compare_value) {
-  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
-}
-
-
-Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32(
-    Isolate* isolate,
-    uint32_t bitmask,
-    uint32_t compare_value) {
-  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
-}
-
-
-Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
-  Handle<FunctionTemplate> types[1] = { type };
-  return TypeSwitch::New(1, types);
-}
-
-
-Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
-  i::Isolate* isolate = i::Isolate::Current();
-  LOG_API(isolate, "TypeSwitch::New");
-  ENTER_V8(isolate);
-  i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc);
-  for (int i = 0; i < argc; i++)
-    vector->set(i, *Utils::OpenHandle(*types[i]));
-  i::Handle<i::Struct> struct_obj =
-      isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
-  i::Handle<i::TypeSwitchInfo> obj =
-      i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
-  obj->set_types(*vector);
-  return Utils::ToLocal(obj);
-}
-
-
-int TypeSwitch::match(v8::Handle<Value> value) {
-  i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
-  LOG_API(info->GetIsolate(), "TypeSwitch::match");
-  i::Handle<i::Object> obj = Utils::OpenHandle(*value);
-  i::FixedArray* types = i::FixedArray::cast(info->types());
-  for (int i = 0; i < types->length(); i++) {
-    if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj))
-      return i + 1;
-  }
-  return 0;
-}
-
-
 #define SET_FIELD_WRAPPED(obj, setter, cdata) do {                      \
     i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
     (obj)->setter(*foreign);                                            \
   } while (false)
 
 
-void FunctionTemplate::SetCallHandler(FunctionCallback callback,
-                                      v8::Handle<Value> data) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+void FunctionTemplate::SetCallHandler(
+    FunctionCallback callback, v8::Local<Value> data,
+    experimental::FastAccessorBuilder* fast_handler) {
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler");
+  i::Isolate* isolate = info->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
   i::Handle<i::Struct> struct_obj =
@@ -1021,24 +1091,27 @@
   i::Handle<i::CallHandlerInfo> obj =
       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
   SET_FIELD_WRAPPED(obj, set_callback, callback);
+  i::MaybeHandle<i::Code> code =
+      i::experimental::BuildCodeFromFastAccessorBuilder(fast_handler);
+  if (!code.is_null()) {
+    obj->set_fast_handler(*code.ToHandleChecked());
+  }
   if (data.IsEmpty()) {
     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
   }
   obj->set_data(*Utils::OpenHandle(*data));
-  Utils::OpenHandle(this)->set_call_code(*obj);
+  info->set_call_code(*obj);
 }
 
 
 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
-    i::Handle<i::AccessorInfo> obj,
-    v8::Handle<Name> name,
-    v8::AccessControl settings,
-    v8::PropertyAttribute attributes,
-    v8::Handle<AccessorSignature> signature) {
+    i::Handle<i::AccessorInfo> obj, v8::Local<Name> name,
+    v8::AccessControl settings, v8::PropertyAttribute attributes,
+    v8::Local<AccessorSignature> signature) {
   obj->set_name(*Utils::OpenHandle(*name));
   if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
   if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
-  obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
+  obj->set_property_attributes(static_cast<i::PropertyAttributes>(attributes));
   if (!signature.IsEmpty()) {
     obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
   }
@@ -1046,15 +1119,11 @@
 }
 
 
-template<typename Getter, typename Setter>
+template <typename Getter, typename Setter>
 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
-    v8::Handle<Name> name,
-    Getter getter,
-    Setter setter,
-    v8::Handle<Value> data,
-    v8::AccessControl settings,
-    v8::PropertyAttribute attributes,
-    v8::Handle<AccessorSignature> signature) {
+    v8::Local<Name> name, Getter getter, Setter setter, v8::Local<Value> data,
+    v8::AccessControl settings, v8::PropertyAttribute attributes,
+    v8::Local<AccessorSignature> signature) {
   i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
   i::Handle<i::ExecutableAccessorInfo> obj =
       isolate->factory()->NewExecutableAccessorInfo();
@@ -1068,23 +1137,6 @@
 }
 
 
-static i::Handle<i::AccessorInfo> MakeAccessorInfo(
-    v8::Handle<Name> 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 =
-      isolate->factory()->NewDeclaredAccessorInfo();
-  obj->set_descriptor(*Utils::OpenHandle(*descriptor));
-  return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
-}
-
-
 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
   i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
   if (!Utils::ApiCheck(!handle.is_null(),
@@ -1106,45 +1158,65 @@
 
 
 void FunctionTemplate::SetLength(int length) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::SetLength");
+  auto isolate = info->GetIsolate();
   ENTER_V8(isolate);
-  Utils::OpenHandle(this)->set_length(length);
+  info->set_length(length);
 }
 
 
-void FunctionTemplate::SetClassName(Handle<String> name) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+void FunctionTemplate::SetClassName(Local<String> name) {
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::SetClassName");
+  auto isolate = info->GetIsolate();
   ENTER_V8(isolate);
-  Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
+  info->set_class_name(*Utils::OpenHandle(*name));
+}
+
+
+void FunctionTemplate::SetAcceptAnyReceiver(bool value) {
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::SetAcceptAnyReceiver");
+  auto isolate = info->GetIsolate();
+  ENTER_V8(isolate);
+  info->set_accept_any_receiver(value);
 }
 
 
 void FunctionTemplate::SetHiddenPrototype(bool value) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::SetHiddenPrototype");
+  auto isolate = info->GetIsolate();
   ENTER_V8(isolate);
-  Utils::OpenHandle(this)->set_hidden_prototype(value);
+  info->set_hidden_prototype(value);
 }
 
 
 void FunctionTemplate::ReadOnlyPrototype() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::ReadOnlyPrototype");
+  auto isolate = info->GetIsolate();
   ENTER_V8(isolate);
-  Utils::OpenHandle(this)->set_read_only_prototype(true);
+  info->set_read_only_prototype(true);
 }
 
 
 void FunctionTemplate::RemovePrototype() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  auto info = Utils::OpenHandle(this);
+  EnsureNotInstantiated(info, "v8::FunctionTemplate::RemovePrototype");
+  auto isolate = info->GetIsolate();
   ENTER_V8(isolate);
-  Utils::OpenHandle(this)->set_remove_prototype(true);
+  info->set_remove_prototype(true);
 }
 
 
 // --- O b j e c t T e m p l a t e ---
 
 
-Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) {
-  return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>());
+Local<ObjectTemplate> ObjectTemplate::New(
+    Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
+  return New(reinterpret_cast<i::Isolate*>(isolate), constructor);
 }
 
 
@@ -1154,8 +1226,7 @@
 
 
 Local<ObjectTemplate> ObjectTemplate::New(
-    i::Isolate* isolate,
-    v8::Handle<FunctionTemplate> constructor) {
+    i::Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
   // Changes to the environment cannot be captured in the snapshot. Expect no
   // object templates when the isolate is created for serialization.
   DCHECK(!isolate->serializer_enabled());
@@ -1192,20 +1263,6 @@
 }
 
 
-static inline void AddPropertyToTemplate(
-    i::Handle<i::TemplateInfo> info,
-    i::Handle<i::AccessorInfo> obj) {
-  i::Isolate* isolate = info->GetIsolate();
-  i::Handle<i::Object> list(info->property_accessors(), isolate);
-  if (list->IsUndefined()) {
-    list = NeanderArray(isolate).value();
-    info->set_property_accessors(*list);
-  }
-  NeanderArray array(list);
-  array.add(isolate, obj);
-}
-
-
 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
     i::Isolate* isolate,
     Template* template_obj) {
@@ -1232,34 +1289,22 @@
     AccessControl settings,
     PropertyAttribute attribute,
     v8::Local<AccessorSignature> signature) {
-  i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
+  auto isolate = Utils::OpenHandle(template_obj)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
-      name, getter, setter, data, settings, attribute, signature);
+  auto obj = MakeAccessorInfo(name, getter, setter, data, settings, attribute,
+                              signature);
   if (obj.is_null()) return false;
-  i::Handle<i::TemplateInfo> info = GetTemplateInfo(isolate, template_obj);
-  AddPropertyToTemplate(info, obj);
+  auto info = GetTemplateInfo(isolate, template_obj);
+  i::ApiNatives::AddNativeDataProperty(isolate, info, obj);
   return true;
 }
 
 
-bool Template::SetDeclaredAccessor(
-    Local<Name> name,
-    Local<DeclaredAccessorDescriptor> descriptor,
-    PropertyAttribute attribute,
-    Local<AccessorSignature> signature,
-    AccessControl settings) {
-  void* null = NULL;
-  return TemplateSetAccessor(
-      this, name, descriptor, null, null, settings, attribute, signature);
-}
-
-
 void Template::SetNativeDataProperty(v8::Local<String> name,
                                      AccessorGetterCallback getter,
                                      AccessorSetterCallback setter,
-                                     v8::Handle<Value> data,
+                                     v8::Local<Value> data,
                                      PropertyAttribute attribute,
                                      v8::Local<AccessorSignature> signature,
                                      AccessControl settings) {
@@ -1271,7 +1316,7 @@
 void Template::SetNativeDataProperty(v8::Local<Name> name,
                                      AccessorNameGetterCallback getter,
                                      AccessorNameSetterCallback setter,
-                                     v8::Handle<Value> data,
+                                     v8::Local<Value> data,
                                      PropertyAttribute attribute,
                                      v8::Local<AccessorSignature> signature,
                                      AccessControl settings) {
@@ -1280,25 +1325,35 @@
 }
 
 
-void ObjectTemplate::SetAccessor(v8::Handle<String> name,
+void Template::SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic,
+                                        PropertyAttribute attribute) {
+  auto templ = Utils::OpenHandle(this);
+  i::Isolate* isolate = templ->GetIsolate();
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
+                                 intrinsic,
+                                 static_cast<i::PropertyAttributes>(attribute));
+}
+
+
+void ObjectTemplate::SetAccessor(v8::Local<String> name,
                                  AccessorGetterCallback getter,
                                  AccessorSetterCallback setter,
-                                 v8::Handle<Value> data,
-                                 AccessControl settings,
+                                 v8::Local<Value> data, AccessControl settings,
                                  PropertyAttribute attribute,
-                                 v8::Handle<AccessorSignature> signature) {
+                                 v8::Local<AccessorSignature> signature) {
   TemplateSetAccessor(
       this, name, getter, setter, data, settings, attribute, signature);
 }
 
 
-void ObjectTemplate::SetAccessor(v8::Handle<Name> name,
+void ObjectTemplate::SetAccessor(v8::Local<Name> name,
                                  AccessorNameGetterCallback getter,
                                  AccessorNameSetterCallback setter,
-                                 v8::Handle<Value> data,
-                                 AccessControl settings,
+                                 v8::Local<Value> data, AccessControl settings,
                                  PropertyAttribute attribute,
-                                 v8::Handle<AccessorSignature> signature) {
+                                 v8::Local<AccessorSignature> signature) {
   TemplateSetAccessor(
       this, name, getter, setter, data, settings, attribute, signature);
 }
@@ -1306,29 +1361,33 @@
 
 template <typename Getter, typename Setter, typename Query, typename Deleter,
           typename Enumerator>
-static void ObjectTemplateSetNamedPropertyHandler(
-    ObjectTemplate* templ, Getter getter, Setter setter, Query query,
-    Deleter remover, Enumerator enumerator, Handle<Value> data,
-    bool can_intercept_symbols, PropertyHandlerFlags flags) {
+static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ,
+                                                  Getter getter, Setter setter,
+                                                  Query query, Deleter remover,
+                                                  Enumerator enumerator,
+                                                  Local<Value> data,
+                                                  PropertyHandlerFlags flags) {
   i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  EnsureConstructor(isolate, templ);
-  i::FunctionTemplateInfo* constructor =
-      i::FunctionTemplateInfo::cast(Utils::OpenHandle(templ)->constructor());
-  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  auto cons = EnsureConstructor(isolate, templ);
+  EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler");
   auto obj = i::Handle<i::InterceptorInfo>::cast(
       isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE));
+  obj->set_flags(0);
 
   if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
   if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
   if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
   if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
   if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
-  obj->set_flags(0);
-  obj->set_can_intercept_symbols(can_intercept_symbols);
+  obj->set_can_intercept_symbols(
+      !(static_cast<int>(flags) &
+        static_cast<int>(PropertyHandlerFlags::kOnlyInterceptStrings)));
   obj->set_all_can_read(static_cast<int>(flags) &
                         static_cast<int>(PropertyHandlerFlags::kAllCanRead));
+  obj->set_non_masking(static_cast<int>(flags) &
+                       static_cast<int>(PropertyHandlerFlags::kNonMasking));
 
   if (data.IsEmpty()) {
     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
@@ -1341,10 +1400,10 @@
 void ObjectTemplate::SetNamedPropertyHandler(
     NamedPropertyGetterCallback getter, NamedPropertySetterCallback setter,
     NamedPropertyQueryCallback query, NamedPropertyDeleterCallback remover,
-    NamedPropertyEnumeratorCallback enumerator, Handle<Value> data) {
-  ObjectTemplateSetNamedPropertyHandler(this, getter, setter, query, remover,
-                                        enumerator, data, false,
-                                        PropertyHandlerFlags::kNone);
+    NamedPropertyEnumeratorCallback enumerator, Local<Value> data) {
+  ObjectTemplateSetNamedPropertyHandler(
+      this, getter, setter, query, remover, enumerator, data,
+      PropertyHandlerFlags::kOnlyInterceptStrings);
 }
 
 
@@ -1352,7 +1411,7 @@
     const NamedPropertyHandlerConfiguration& config) {
   ObjectTemplateSetNamedPropertyHandler(
       this, config.getter, config.setter, config.query, config.deleter,
-      config.enumerator, config.data, true, config.flags);
+      config.enumerator, config.data, config.flags);
 }
 
 
@@ -1360,29 +1419,54 @@
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  EnsureConstructor(isolate, this);
-  i::FunctionTemplateInfo* constructor =
-      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
-  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  auto cons = EnsureConstructor(isolate, this);
+  EnsureNotInstantiated(cons, "v8::ObjectTemplate::MarkAsUndetectable");
   cons->set_undetectable(true);
 }
 
 
-void ObjectTemplate::SetAccessCheckCallbacks(
-    NamedSecurityCallback named_callback,
-    IndexedSecurityCallback indexed_callback,
-    Handle<Value> data,
-    bool turned_on_by_default) {
+void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback,
+                                            Local<Value> data) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  EnsureConstructor(isolate, this);
+  auto cons = EnsureConstructor(isolate, this);
+  EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallback");
 
   i::Handle<i::Struct> struct_info =
       isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
   i::Handle<i::AccessCheckInfo> info =
       i::Handle<i::AccessCheckInfo>::cast(struct_info);
 
+  SET_FIELD_WRAPPED(info, set_callback, callback);
+  SET_FIELD_WRAPPED(info, set_named_callback, nullptr);
+  SET_FIELD_WRAPPED(info, set_indexed_callback, nullptr);
+
+  if (data.IsEmpty()) {
+    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+  }
+  info->set_data(*Utils::OpenHandle(*data));
+
+  cons->set_access_check_info(*info);
+  cons->set_needs_access_check(true);
+}
+
+
+void ObjectTemplate::SetAccessCheckCallbacks(
+    NamedSecurityCallback named_callback,
+    IndexedSecurityCallback indexed_callback, Local<Value> data) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  auto cons = EnsureConstructor(isolate, this);
+  EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallbacks");
+
+  i::Handle<i::Struct> struct_info =
+      isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
+  i::Handle<i::AccessCheckInfo> info =
+      i::Handle<i::AccessCheckInfo>::cast(struct_info);
+
+  SET_FIELD_WRAPPED(info, set_callback, nullptr);
   SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
   SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
 
@@ -1391,11 +1475,8 @@
   }
   info->set_data(*Utils::OpenHandle(*data));
 
-  i::FunctionTemplateInfo* constructor =
-      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
-  i::Handle<i::FunctionTemplateInfo> cons(constructor);
   cons->set_access_check_info(*info);
-  cons->set_needs_access_check(turned_on_by_default);
+  cons->set_needs_access_check(true);
 }
 
 
@@ -1404,12 +1485,11 @@
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  EnsureConstructor(isolate, this);
-  i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
-      Utils::OpenHandle(this)->constructor());
-  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  auto cons = EnsureConstructor(isolate, this);
+  EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetHandler");
   auto obj = i::Handle<i::InterceptorInfo>::cast(
       isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE));
+  obj->set_flags(0);
 
   if (config.getter != 0) SET_FIELD_WRAPPED(obj, set_getter, config.getter);
   if (config.setter != 0) SET_FIELD_WRAPPED(obj, set_setter, config.setter);
@@ -1418,7 +1498,6 @@
   if (config.enumerator != 0) {
     SET_FIELD_WRAPPED(obj, set_enumerator, config.enumerator);
   }
-  obj->set_flags(0);
   obj->set_all_can_read(static_cast<int>(config.flags) &
                         static_cast<int>(PropertyHandlerFlags::kAllCanRead));
 
@@ -1432,14 +1511,12 @@
 
 
 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
-                                              Handle<Value> data) {
+                                              Local<Value> data) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  EnsureConstructor(isolate, this);
-  i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
-      Utils::OpenHandle(this)->constructor());
-  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  auto cons = EnsureConstructor(isolate, this);
+  EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler");
   i::Handle<i::Struct> struct_obj =
       isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
   i::Handle<i::CallHandlerInfo> obj =
@@ -1497,6 +1574,12 @@
 }
 
 
+bool ScriptCompiler::ExternalSourceStream::SetBookmark() { return false; }
+
+
+void ScriptCompiler::ExternalSourceStream::ResetToBookmark() { UNREACHABLE(); }
+
+
 ScriptCompiler::StreamedSource::StreamedSource(ExternalSourceStream* stream,
                                                Encoding encoding)
     : impl_(new i::StreamedSource(stream, encoding)) {}
@@ -1516,9 +1599,37 @@
       i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
   i::Handle<i::SharedFunctionInfo>
       function_info(i::SharedFunctionInfo::cast(*obj), obj->GetIsolate());
+  i::Isolate* isolate = obj->GetIsolate();
+
+  i::ScopeInfo* scope_info = function_info->scope_info();
+  i::Handle<i::JSReceiver> global(isolate->native_context()->global_object());
+  for (int i = 0; i < scope_info->StrongModeFreeVariableCount(); ++i) {
+    i::Handle<i::String> name_string(scope_info->StrongModeFreeVariableName(i));
+    i::ScriptContextTable::LookupResult result;
+    i::Handle<i::ScriptContextTable> script_context_table(
+        isolate->native_context()->script_context_table());
+    if (!i::ScriptContextTable::Lookup(script_context_table, name_string,
+                                       &result)) {
+      i::Handle<i::Name> name(scope_info->StrongModeFreeVariableName(i));
+      Maybe<bool> has = i::JSReceiver::HasProperty(global, name);
+      if (has.IsJust() && !has.FromJust()) {
+        i::PendingCompilationErrorHandler pending_error_handler_;
+        pending_error_handler_.ReportMessageAt(
+            scope_info->StrongModeFreeVariableStartPosition(i),
+            scope_info->StrongModeFreeVariableEndPosition(i),
+            i::MessageTemplate::kStrongUnboundGlobal, name_string,
+            i::kReferenceError);
+        i::Handle<i::Script> script(i::Script::cast(function_info->script()));
+        pending_error_handler_.ThrowPendingError(isolate, script);
+        isolate->ReportPendingMessages();
+        isolate->OptionalRescheduleException(true);
+        return Local<Script>();
+      }
+    }
+  }
   i::Handle<i::JSFunction> function =
       obj->GetIsolate()->factory()->NewFunctionFromSharedFunctionInfo(
-          function_info, obj->GetIsolate()->native_context());
+          function_info, isolate->native_context());
   return ToApiHandle<Script>(function);
 }
 
@@ -1527,15 +1638,12 @@
   i::Handle<i::HeapObject> obj =
       i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  ON_BAILOUT(isolate, "v8::UnboundScript::GetId()", return -1);
   LOG_API(isolate, "v8::UnboundScript::GetId");
-  {
-    i::HandleScope scope(isolate);
-    i::Handle<i::SharedFunctionInfo> function_info(
-        i::SharedFunctionInfo::cast(*obj));
-    i::Handle<i::Script> script(i::Script::cast(function_info->script()));
-    return script->id()->value();
-  }
+  i::HandleScope scope(isolate);
+  i::Handle<i::SharedFunctionInfo> function_info(
+      i::SharedFunctionInfo::cast(*obj));
+  i::Handle<i::Script> script(i::Script::cast(function_info->script()));
+  return script->id();
 }
 
 
@@ -1543,7 +1651,6 @@
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  ON_BAILOUT(isolate, "v8::UnboundScript::GetLineNumber()", return -1);
   LOG_API(isolate, "UnboundScript::GetLineNumber");
   if (obj->script()->IsScript()) {
     i::Handle<i::Script> script(i::Script::cast(obj->script()));
@@ -1554,73 +1661,70 @@
 }
 
 
-Handle<Value> UnboundScript::GetScriptName() {
+Local<Value> UnboundScript::GetScriptName() {
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  ON_BAILOUT(isolate, "v8::UnboundScript::GetName()",
-             return Handle<String>());
   LOG_API(isolate, "UnboundScript::GetName");
   if (obj->script()->IsScript()) {
     i::Object* name = i::Script::cast(obj->script())->name();
     return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
   } else {
-    return Handle<String>();
+    return Local<String>();
   }
 }
 
 
-Handle<Value> UnboundScript::GetSourceURL() {
+Local<Value> UnboundScript::GetSourceURL() {
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceURL()",
-             return Handle<String>());
   LOG_API(isolate, "UnboundScript::GetSourceURL");
   if (obj->script()->IsScript()) {
     i::Object* url = i::Script::cast(obj->script())->source_url();
     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
   } else {
-    return Handle<String>();
+    return Local<String>();
   }
 }
 
 
-Handle<Value> UnboundScript::GetSourceMappingURL() {
+Local<Value> UnboundScript::GetSourceMappingURL() {
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceMappingURL()",
-             return Handle<String>());
   LOG_API(isolate, "UnboundScript::GetSourceMappingURL");
   if (obj->script()->IsScript()) {
     i::Object* url = i::Script::cast(obj->script())->source_mapping_url();
     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
   } else {
-    return Handle<String>();
+    return Local<String>();
   }
 }
 
 
+MaybeLocal<Value> Script::Run(Local<Context> context) {
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Script::Run()", Value)
+  i::AggregatingHistogramTimerScope timer(isolate->counters()->compile_lazy());
+  i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
+  auto fun = i::Handle<i::JSFunction>::cast(Utils::OpenHandle(this));
+  i::Handle<i::Object> receiver(isolate->global_proxy(), isolate);
+  Local<Value> result;
+  has_pending_exception =
+      !ToLocal<Value>(i::Execution::Call(isolate, fun, receiver, 0, NULL),
+                      &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
+}
+
+
 Local<Value> Script::Run() {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
+  auto self = Utils::OpenHandle(this, true);
   // If execution is terminating, Compile(..)->Run() requires this
   // check.
-  if (obj.is_null()) return Local<Value>();
-  i::Isolate* isolate = i::Handle<i::HeapObject>::cast(obj)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
-  LOG_API(isolate, "Script::Run");
-  ENTER_V8(isolate);
-  i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> receiver(isolate->global_proxy(), isolate);
-  i::Handle<i::Object> result;
-  has_pending_exception = !i::Execution::Call(
-      isolate, fun, receiver, 0, NULL).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
-  return Utils::ToLocal(scope.CloseAndEscape(result));
+  if (self.is_null()) return Local<Value>();
+  auto context = ContextFromHeapObject(self);
+  RETURN_TO_LOCAL_UNCHECKED(Run(context), Value);
 }
 
 
@@ -1631,22 +1735,12 @@
 }
 
 
-Local<UnboundScript> ScriptCompiler::CompileUnbound(
-    Isolate* v8_isolate,
-    Source* source,
-    CompileOptions options) {
+MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal(
+    Isolate* v8_isolate, Source* source, CompileOptions options,
+    bool is_module) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-  ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()",
-             return Local<UnboundScript>());
-
-  // Support the old API for a transition period:
-  // - kProduceToCache -> kProduceParserCache
-  // - kNoCompileOptions + cached_data != NULL -> kConsumeParserCache
-  if (options == kProduceDataToCache) {
-    options = kProduceParserCache;
-  } else if (options == kNoCompileOptions && source->cached_data) {
-    options = kConsumeParserCache;
-  }
+  PREPARE_FOR_EXECUTION_WITH_ISOLATE(
+      isolate, "v8::ScriptCompiler::CompileUnbound()", UnboundScript);
 
   // Don't try to produce any kind of cache when the debugger is loaded.
   if (isolate->debug()->is_loaded() &&
@@ -1663,14 +1757,13 @@
   }
 
   i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
-  LOG_API(isolate, "ScriptCompiler::CompileUnbound");
-  ENTER_V8(isolate);
-  i::SharedFunctionInfo* raw_result = NULL;
-  { i::HandleScope scope(isolate);
+  i::Handle<i::SharedFunctionInfo> result;
+  {
+    i::HistogramTimerScope total(isolate->counters()->compile_script(), true);
     i::Handle<i::Object> name_obj;
+    i::Handle<i::Object> source_map_url;
     int line_offset = 0;
     int column_offset = 0;
-    bool is_shared_cross_origin = false;
     if (!source->resource_name.IsEmpty()) {
       name_obj = Utils::OpenHandle(*(source->resource_name));
     }
@@ -1681,16 +1774,13 @@
       column_offset =
           static_cast<int>(source->resource_column_offset->Value());
     }
-    if (!source->resource_is_shared_cross_origin.IsEmpty()) {
-      v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
-      is_shared_cross_origin =
-          source->resource_is_shared_cross_origin == v8::True(v8_isolate);
+    if (!source->source_map_url.IsEmpty()) {
+      source_map_url = Utils::OpenHandle(*(source->source_map_url));
     }
-    EXCEPTION_PREAMBLE(isolate);
-    i::Handle<i::SharedFunctionInfo> result = i::Compiler::CompileScript(
-        str, name_obj, line_offset, column_offset, is_shared_cross_origin,
-        isolate->native_context(), NULL, &script_data, options,
-        i::NOT_NATIVES_CODE);
+    result = i::Compiler::CompileScript(
+        str, name_obj, line_offset, column_offset, source->resource_options,
+        source_map_url, isolate->native_context(), NULL, &script_data, options,
+        i::NOT_NATIVES_CODE, is_module);
     has_pending_exception = result.is_null();
     if (has_pending_exception && script_data != NULL) {
       // This case won't happen during normal operation; we have compiled
@@ -1699,8 +1789,7 @@
       delete script_data;
       script_data = NULL;
     }
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
-    raw_result = *result;
+    RETURN_ON_FAILED_EXECUTION(UnboundScript);
 
     if ((options == kProduceParserCache || options == kProduceCodeCache) &&
         script_data != NULL) {
@@ -1714,8 +1803,34 @@
     }
     delete script_data;
   }
-  i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
-  return ToApiHandle<UnboundScript>(result);
+  RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
+}
+
+
+MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundScript(
+    Isolate* v8_isolate, Source* source, CompileOptions options) {
+  return CompileUnboundInternal(v8_isolate, source, options, false);
+}
+
+
+Local<UnboundScript> ScriptCompiler::CompileUnbound(Isolate* v8_isolate,
+                                                    Source* source,
+                                                    CompileOptions options) {
+  RETURN_TO_LOCAL_UNCHECKED(
+      CompileUnboundInternal(v8_isolate, source, options, false),
+      UnboundScript);
+}
+
+
+MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
+                                           Source* source,
+                                           CompileOptions options) {
+  auto isolate = context->GetIsolate();
+  auto maybe = CompileUnboundInternal(isolate, source, options, false);
+  Local<UnboundScript> result;
+  if (!maybe.ToLocal(&result)) return MaybeLocal<Script>();
+  v8::Context::Scope scope(context);
+  return result->BindToCurrentContext();
 }
 
 
@@ -1723,16 +1838,166 @@
     Isolate* v8_isolate,
     Source* source,
     CompileOptions options) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-  ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
-  LOG_API(isolate, "ScriptCompiler::CompiletBound()");
-  ENTER_V8(isolate);
-  Local<UnboundScript> generic = CompileUnbound(v8_isolate, source, options);
-  if (generic.IsEmpty()) return Local<Script>();
+  auto context = v8_isolate->GetCurrentContext();
+  RETURN_TO_LOCAL_UNCHECKED(Compile(context, source, options), Script);
+}
+
+
+MaybeLocal<Script> ScriptCompiler::CompileModule(Local<Context> context,
+                                                 Source* source,
+                                                 CompileOptions options) {
+  CHECK(i::FLAG_harmony_modules);
+  auto isolate = context->GetIsolate();
+  auto maybe = CompileUnboundInternal(isolate, source, options, true);
+  Local<UnboundScript> generic;
+  if (!maybe.ToLocal(&generic)) return MaybeLocal<Script>();
+  v8::Context::Scope scope(context);
   return generic->BindToCurrentContext();
 }
 
 
+class IsIdentifierHelper {
+ public:
+  IsIdentifierHelper() : is_identifier_(false), first_char_(true) {}
+
+  bool Check(i::String* string) {
+    i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
+    if (cons_string == NULL) return is_identifier_;
+    // We don't support cons strings here.
+    return false;
+  }
+  void VisitOneByteString(const uint8_t* chars, int length) {
+    for (int i = 0; i < length; ++i) {
+      if (first_char_) {
+        first_char_ = false;
+        is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]);
+      } else {
+        is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]);
+      }
+    }
+  }
+  void VisitTwoByteString(const uint16_t* chars, int length) {
+    for (int i = 0; i < length; ++i) {
+      if (first_char_) {
+        first_char_ = false;
+        is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]);
+      } else {
+        is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]);
+      }
+    }
+  }
+
+ private:
+  bool is_identifier_;
+  bool first_char_;
+  i::UnicodeCache unicode_cache_;
+  DISALLOW_COPY_AND_ASSIGN(IsIdentifierHelper);
+};
+
+
+MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
+    Local<Context> v8_context, Source* source, size_t arguments_count,
+    Local<String> arguments[], size_t context_extension_count,
+    Local<Object> context_extensions[]) {
+  PREPARE_FOR_EXECUTION(
+      v8_context, "v8::ScriptCompiler::CompileFunctionInContext()", Function);
+  i::Handle<i::String> source_string;
+  auto factory = isolate->factory();
+  if (arguments_count) {
+    source_string = factory->NewStringFromStaticChars("(function(");
+    for (size_t i = 0; i < arguments_count; ++i) {
+      IsIdentifierHelper helper;
+      if (!helper.Check(*Utils::OpenHandle(*arguments[i]))) {
+        return Local<Function>();
+      }
+      has_pending_exception =
+          !factory->NewConsString(source_string,
+                                  Utils::OpenHandle(*arguments[i]))
+               .ToHandle(&source_string);
+      RETURN_ON_FAILED_EXECUTION(Function);
+      if (i + 1 == arguments_count) continue;
+      has_pending_exception =
+          !factory->NewConsString(source_string,
+                                  factory->LookupSingleCharacterStringFromCode(
+                                      ',')).ToHandle(&source_string);
+      RETURN_ON_FAILED_EXECUTION(Function);
+    }
+    auto brackets = factory->NewStringFromStaticChars("){");
+    has_pending_exception = !factory->NewConsString(source_string, brackets)
+                                 .ToHandle(&source_string);
+    RETURN_ON_FAILED_EXECUTION(Function);
+  } else {
+    source_string = factory->NewStringFromStaticChars("(function(){");
+  }
+
+  int scope_position = source_string->length();
+  has_pending_exception =
+      !factory->NewConsString(source_string,
+                              Utils::OpenHandle(*source->source_string))
+           .ToHandle(&source_string);
+  RETURN_ON_FAILED_EXECUTION(Function);
+  // Include \n in case the source contains a line end comment.
+  auto brackets = factory->NewStringFromStaticChars("\n})");
+  has_pending_exception =
+      !factory->NewConsString(source_string, brackets).ToHandle(&source_string);
+  RETURN_ON_FAILED_EXECUTION(Function);
+
+  i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);
+  i::Handle<i::SharedFunctionInfo> outer_info(context->closure()->shared(),
+                                              isolate);
+  for (size_t i = 0; i < context_extension_count; ++i) {
+    i::Handle<i::JSReceiver> extension =
+        Utils::OpenHandle(*context_extensions[i]);
+    if (!extension->IsJSObject()) return Local<Function>();
+    i::Handle<i::JSFunction> closure(context->closure(), isolate);
+    context = factory->NewWithContext(closure, context, extension);
+  }
+
+  i::Handle<i::Object> name_obj;
+  int line_offset = 0;
+  int column_offset = 0;
+  if (!source->resource_name.IsEmpty()) {
+    name_obj = Utils::OpenHandle(*(source->resource_name));
+  }
+  if (!source->resource_line_offset.IsEmpty()) {
+    line_offset = static_cast<int>(source->resource_line_offset->Value());
+  }
+  if (!source->resource_column_offset.IsEmpty()) {
+    column_offset = static_cast<int>(source->resource_column_offset->Value());
+  }
+  i::Handle<i::JSFunction> fun;
+  has_pending_exception = !i::Compiler::GetFunctionFromEval(
+                               source_string, outer_info, context, i::SLOPPY,
+                               i::ONLY_SINGLE_FUNCTION_LITERAL, line_offset,
+                               column_offset - scope_position, name_obj,
+                               source->resource_options).ToHandle(&fun);
+  if (has_pending_exception) {
+    isolate->ReportPendingMessages();
+  }
+  RETURN_ON_FAILED_EXECUTION(Function);
+
+  i::Handle<i::Object> result;
+  has_pending_exception =
+      !i::Execution::Call(isolate, fun,
+                          Utils::OpenHandle(*v8_context->Global()), 0,
+                          nullptr).ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Function);
+  RETURN_ESCAPED(
+      Utils::CallableToLocal(i::Handle<i::JSFunction>::cast(result)));
+}
+
+
+Local<Function> ScriptCompiler::CompileFunctionInContext(
+    Isolate* v8_isolate, Source* source, Local<Context> v8_context,
+    size_t arguments_count, Local<String> arguments[],
+    size_t context_extension_count, Local<Object> context_extensions[]) {
+  RETURN_TO_LOCAL_UNCHECKED(
+      CompileFunctionInContext(v8_context, source, arguments_count, arguments,
+                               context_extension_count, context_extensions),
+      Function);
+}
+
+
 ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreamingScript(
     Isolate* v8_isolate, StreamedSource* source, CompileOptions options) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
@@ -1741,68 +2006,67 @@
 }
 
 
+MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
+                                           StreamedSource* v8_source,
+                                           Local<String> full_source_string,
+                                           const ScriptOrigin& origin) {
+  PREPARE_FOR_EXECUTION(context, "v8::ScriptCompiler::Compile()", Script);
+  i::StreamedSource* source = v8_source->impl();
+  i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string));
+  i::Handle<i::Script> script = isolate->factory()->NewScript(str);
+  if (!origin.ResourceName().IsEmpty()) {
+    script->set_name(*Utils::OpenHandle(*(origin.ResourceName())));
+  }
+  if (!origin.ResourceLineOffset().IsEmpty()) {
+    script->set_line_offset(
+        static_cast<int>(origin.ResourceLineOffset()->Value()));
+  }
+  if (!origin.ResourceColumnOffset().IsEmpty()) {
+    script->set_column_offset(
+        static_cast<int>(origin.ResourceColumnOffset()->Value()));
+  }
+  script->set_origin_options(origin.Options());
+  if (!origin.SourceMapUrl().IsEmpty()) {
+    script->set_source_mapping_url(
+        *Utils::OpenHandle(*(origin.SourceMapUrl())));
+  }
+
+  source->info->set_script(script);
+  source->info->set_context(isolate->native_context());
+
+  // Do the parsing tasks which need to be done on the main thread. This will
+  // also handle parse errors.
+  source->parser->Internalize(isolate, script,
+                              source->info->literal() == nullptr);
+  source->parser->HandleSourceURLComments(isolate, script);
+
+  i::Handle<i::SharedFunctionInfo> result;
+  if (source->info->literal() != nullptr) {
+    // Parsing has succeeded.
+    result = i::Compiler::CompileStreamedScript(script, source->info.get(),
+                                                str->length());
+  }
+  has_pending_exception = result.is_null();
+  if (has_pending_exception) isolate->ReportPendingMessages();
+  RETURN_ON_FAILED_EXECUTION(Script);
+
+  source->info->clear_script();  // because script goes out of scope.
+
+  Local<UnboundScript> generic = ToApiHandle<UnboundScript>(result);
+  if (generic.IsEmpty()) return Local<Script>();
+  Local<Script> bound = generic->BindToCurrentContext();
+  if (bound.IsEmpty()) return Local<Script>();
+  RETURN_ESCAPED(bound);
+}
+
+
 Local<Script> ScriptCompiler::Compile(Isolate* v8_isolate,
                                       StreamedSource* v8_source,
-                                      Handle<String> full_source_string,
+                                      Local<String> full_source_string,
                                       const ScriptOrigin& origin) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-  i::StreamedSource* source = v8_source->impl();
-  ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
-  LOG_API(isolate, "ScriptCompiler::Compile()");
-  ENTER_V8(isolate);
-  i::SharedFunctionInfo* raw_result = NULL;
-
-  {
-    i::HandleScope scope(isolate);
-    i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string));
-    i::Handle<i::Script> script = isolate->factory()->NewScript(str);
-    if (!origin.ResourceName().IsEmpty()) {
-      script->set_name(*Utils::OpenHandle(*(origin.ResourceName())));
-    }
-    if (!origin.ResourceLineOffset().IsEmpty()) {
-      script->set_line_offset(i::Smi::FromInt(
-          static_cast<int>(origin.ResourceLineOffset()->Value())));
-    }
-    if (!origin.ResourceColumnOffset().IsEmpty()) {
-      script->set_column_offset(i::Smi::FromInt(
-          static_cast<int>(origin.ResourceColumnOffset()->Value())));
-    }
-    if (!origin.ResourceIsSharedCrossOrigin().IsEmpty()) {
-      script->set_is_shared_cross_origin(origin.ResourceIsSharedCrossOrigin() ==
-                                         v8::True(v8_isolate));
-    }
-    source->info->set_script(script);
-    source->info->SetContext(isolate->native_context());
-
-    EXCEPTION_PREAMBLE(isolate);
-
-    // Do the parsing tasks which need to be done on the main thread. This will
-    // also handle parse errors.
-    source->parser->Internalize();
-    source->parser->HandleSourceURLComments();
-
-    i::Handle<i::SharedFunctionInfo> result =
-        i::Handle<i::SharedFunctionInfo>::null();
-    if (source->info->function() != NULL) {
-      // Parsing has succeeded.
-      result =
-          i::Compiler::CompileStreamedScript(source->info.get(), str->length());
-    }
-    has_pending_exception = result.is_null();
-    if (has_pending_exception) isolate->ReportPendingMessages();
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
-
-    raw_result = *result;
-    // The Handle<Script> will go out of scope soon; make sure CompilationInfo
-    // doesn't point to it.
-    source->info->set_script(i::Handle<i::Script>());
-  }  // HandleScope goes out of scope.
-  i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
-  Local<UnboundScript> generic = ToApiHandle<UnboundScript>(result);
-  if (generic.IsEmpty()) {
-    return Local<Script>();
-  }
-  return generic->BindToCurrentContext();
+  auto context = v8_isolate->GetCurrentContext();
+  RETURN_TO_LOCAL_UNCHECKED(
+      Compile(context, v8_source, full_source_string, origin), Script);
 }
 
 
@@ -1813,26 +2077,31 @@
 }
 
 
-Local<Script> Script::Compile(v8::Handle<String> source,
-                              v8::ScriptOrigin* origin) {
-  i::Handle<i::String> str = Utils::OpenHandle(*source);
+MaybeLocal<Script> Script::Compile(Local<Context> context, Local<String> source,
+                                   ScriptOrigin* origin) {
   if (origin) {
     ScriptCompiler::Source script_source(source, *origin);
-    return ScriptCompiler::Compile(
-        reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
-        &script_source);
+    return ScriptCompiler::Compile(context, &script_source);
   }
   ScriptCompiler::Source script_source(source);
-  return ScriptCompiler::Compile(
-      reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
-      &script_source);
+  return ScriptCompiler::Compile(context, &script_source);
 }
 
 
-Local<Script> Script::Compile(v8::Handle<String> source,
-                              v8::Handle<String> file_name) {
+Local<Script> Script::Compile(v8::Local<String> source,
+                              v8::ScriptOrigin* origin) {
+  auto str = Utils::OpenHandle(*source);
+  auto context = ContextFromHeapObject(str);
+  RETURN_TO_LOCAL_UNCHECKED(Compile(context, source, origin), Script);
+}
+
+
+Local<Script> Script::Compile(v8::Local<String> source,
+                              v8::Local<String> file_name) {
+  auto str = Utils::OpenHandle(*source);
+  auto context = ContextFromHeapObject(str);
   ScriptOrigin origin(file_name);
-  return Compile(source, &origin);
+  return Compile(context, source, &origin).FromMaybe(Local<Script>());
 }
 
 
@@ -1851,7 +2120,7 @@
   // Special handling for simulators which have a separate JS stack.
   js_stack_comparable_address_ =
       reinterpret_cast<void*>(v8::internal::SimulatorStack::RegisterCTryCatch(
-          v8::internal::GetCurrentStackPosition()));
+          isolate_, v8::internal::GetCurrentStackPosition()));
   isolate_->RegisterTryCatchHandler(this);
 }
 
@@ -1868,7 +2137,7 @@
   // Special handling for simulators which have a separate JS stack.
   js_stack_comparable_address_ =
       reinterpret_cast<void*>(v8::internal::SimulatorStack::RegisterCTryCatch(
-          v8::internal::GetCurrentStackPosition()));
+          isolate_, v8::internal::GetCurrentStackPosition()));
   isolate_->RegisterTryCatchHandler(this);
 }
 
@@ -1881,13 +2150,13 @@
     if (HasCaught() && capture_message_) {
       // If an exception was caught and rethrow_ is indicated, the saved
       // message, script, and location need to be restored to Isolate TLS
-      // for reuse.  capture_message_ needs to be disabled so that DoThrow()
+      // for reuse.  capture_message_ needs to be disabled so that Throw()
       // does not create a new message.
       isolate_->thread_local_top()->rethrowing_message_ = true;
       isolate_->RestorePendingMessageFromTryCatch(this);
     }
     isolate_->UnregisterTryCatchHandler(this);
-    v8::internal::SimulatorStack::UnregisterCTryCatch();
+    v8::internal::SimulatorStack::UnregisterCTryCatch(isolate_);
     reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
     DCHECK(!isolate_->thread_local_top()->rethrowing_message_);
   } else {
@@ -1898,7 +2167,7 @@
       isolate_->CancelScheduledExceptionFromTryCatch(this);
     }
     isolate_->UnregisterTryCatchHandler(this);
-    v8::internal::SimulatorStack::UnregisterCTryCatch();
+    v8::internal::SimulatorStack::UnregisterCTryCatch(isolate_);
   }
 }
 
@@ -1918,7 +2187,7 @@
 }
 
 
-v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
+v8::Local<v8::Value> v8::TryCatch::ReThrow() {
   if (!HasCaught()) return v8::Local<v8::Value>();
   rethrow_ = true;
   return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
@@ -1936,26 +2205,28 @@
 }
 
 
+MaybeLocal<Value> v8::TryCatch::StackTrace(Local<Context> context) const {
+  if (!HasCaught()) return v8::Local<Value>();
+  i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
+  if (!raw_obj->IsJSObject()) return v8::Local<Value>();
+  PREPARE_FOR_EXECUTION(context, "v8::TryCatch::StackTrace", Value);
+  i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
+  i::Handle<i::String> name = isolate->factory()->stack_string();
+  Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
+  has_pending_exception = !maybe.IsJust();
+  RETURN_ON_FAILED_EXECUTION(Value);
+  if (!maybe.FromJust()) return v8::Local<Value>();
+  Local<Value> result;
+  has_pending_exception =
+      !ToLocal<Value>(i::Object::GetProperty(obj, name), &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
+}
+
+
 v8::Local<Value> v8::TryCatch::StackTrace() const {
-  if (HasCaught()) {
-    i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
-    if (!raw_obj->IsJSObject()) return v8::Local<Value>();
-    i::HandleScope scope(isolate_);
-    i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
-    i::Handle<i::String> name = isolate_->factory()->stack_string();
-    EXCEPTION_PREAMBLE(isolate_);
-    Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
-    has_pending_exception = !maybe.has_value;
-    EXCEPTION_BAILOUT_CHECK(isolate_, v8::Local<Value>());
-    if (!maybe.value) return v8::Local<Value>();
-    i::Handle<i::Object> value;
-    if (!i::Object::GetProperty(obj, name).ToHandle(&value)) {
-      return v8::Local<Value>();
-    }
-    return v8::Utils::ToLocal(scope.CloseAndEscape(value));
-  } else {
-    return v8::Local<Value>();
-  }
+  auto context = reinterpret_cast<v8::Isolate*>(isolate_)->GetCurrentContext();
+  RETURN_TO_LOCAL_UNCHECKED(StackTrace(context), Value);
 }
 
 
@@ -1985,9 +2256,6 @@
   i::Object* the_hole = isolate_->heap()->the_hole_value();
   exception_ = the_hole;
   message_obj_ = the_hole;
-  message_script_ = the_hole;
-  message_start_pos_ = 0;
-  message_end_pos_ = 0;
 }
 
 
@@ -2006,7 +2274,6 @@
 
 Local<String> Message::Get() const {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
   ENTER_V8(isolate);
   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
@@ -2018,165 +2285,151 @@
 
 ScriptOrigin Message::GetScriptOrigin() const {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  i::Handle<i::JSMessageObject> message =
-      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
-  i::Handle<i::Object> script_wraper =
-      i::Handle<i::Object>(message->script(), isolate);
-  i::Handle<i::JSValue> script_value =
-      i::Handle<i::JSValue>::cast(script_wraper);
+  auto message = i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+  auto script_wraper = i::Handle<i::Object>(message->script(), isolate);
+  auto script_value = i::Handle<i::JSValue>::cast(script_wraper);
   i::Handle<i::Script> script(i::Script::cast(script_value->value()));
-  i::Handle<i::Object> scriptName(i::Script::GetNameOrSourceURL(script));
-  v8::Isolate* v8_isolate =
-      reinterpret_cast<v8::Isolate*>(script->GetIsolate());
-  v8::ScriptOrigin origin(
-      Utils::ToLocal(scriptName),
-      v8::Integer::New(v8_isolate, script->line_offset()->value()),
-      v8::Integer::New(v8_isolate, script->column_offset()->value()),
-      Handle<Boolean>(),
-      v8::Integer::New(v8_isolate, script->id()->value()));
-  return origin;
+  return GetScriptOriginForScript(isolate, script);
 }
 
 
-v8::Handle<Value> Message::GetScriptResourceName() const {
+v8::Local<Value> Message::GetScriptResourceName() const {
   return GetScriptOrigin().ResourceName();
 }
 
 
-v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
+v8::Local<v8::StackTrace> Message::GetStackTrace() const {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
-  i::Handle<i::JSMessageObject> message =
-      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+  auto message = i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
   i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate);
-  if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
-  i::Handle<i::JSArray> stackTrace =
-      i::Handle<i::JSArray>::cast(stackFramesObj);
+  if (!stackFramesObj->IsJSArray()) return v8::Local<v8::StackTrace>();
+  auto stackTrace = i::Handle<i::JSArray>::cast(stackFramesObj);
   return scope.Escape(Utils::StackTraceToLocal(stackTrace));
 }
 
 
-MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
-    i::Isolate* isolate, const char* name, i::Handle<i::Object> recv, int argc,
-    i::Handle<i::Object> argv[]) {
-  i::Handle<i::Object> object_fun =
-      i::Object::GetProperty(
-          isolate, isolate->js_builtins_object(), name).ToHandleChecked();
-  i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun);
-  return i::Execution::Call(isolate, fun, recv, argc, argv);
-}
-
-
-MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
-    i::Isolate* isolate, const char* name, i::Handle<i::Object> data) {
-  i::Handle<i::Object> argv[] = { data };
-  return CallV8HeapFunction(isolate, name, isolate->js_builtins_object(),
-                            arraysize(argv), argv);
+Maybe<int> Message::GetLineNumber(Local<Context> context) const {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Message::GetLineNumber()", int);
+  i::Handle<i::JSFunction> fun = isolate->message_get_line_number();
+  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
+  i::Handle<i::Object> args[] = {Utils::OpenHandle(this)};
+  i::Handle<i::Object> result;
+  has_pending_exception =
+      !i::Execution::Call(isolate, fun, undefined, arraysize(args), args)
+           .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int);
+  return Just(static_cast<int>(result->Number()));
 }
 
 
 int Message::GetLineNumber() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> result;
-  has_pending_exception =
-      !CallV8HeapFunction(isolate, "GetLineNumber", Utils::OpenHandle(this))
-           .ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, 0);
-  return static_cast<int>(result->Number());
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return GetLineNumber(context).FromMaybe(0);
 }
 
 
 int Message::GetStartPosition() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSMessageObject> message =
-      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
-  return message->start_position();
+  auto self = Utils::OpenHandle(this);
+  return self->start_position();
 }
 
 
 int Message::GetEndPosition() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSMessageObject> message =
-      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
-  return message->end_position();
+  auto self = Utils::OpenHandle(this);
+  return self->end_position();
+}
+
+
+Maybe<int> Message::GetStartColumn(Local<Context> context) const {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Message::GetStartColumn()",
+                                  int);
+  i::Handle<i::JSFunction> fun = isolate->message_get_column_number();
+  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
+  i::Handle<i::Object> args[] = {Utils::OpenHandle(this)};
+  i::Handle<i::Object> result;
+  has_pending_exception =
+      !i::Execution::Call(isolate, fun, undefined, arraysize(args), args)
+           .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int);
+  return Just(static_cast<int>(result->Number()));
 }
 
 
 int Message::GetStartColumn() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Message::GetStartColumn()", return kNoColumnInfo);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> start_col_obj;
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  const int default_value = kNoColumnInfo;
+  return GetStartColumn(context).FromMaybe(default_value);
+}
+
+
+Maybe<int> Message::GetEndColumn(Local<Context> context) const {
+  auto self = Utils::OpenHandle(this);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Message::GetEndColumn()", int);
+  i::Handle<i::JSFunction> fun = isolate->message_get_column_number();
+  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
+  i::Handle<i::Object> args[] = {self};
+  i::Handle<i::Object> result;
   has_pending_exception =
-      !CallV8HeapFunction(isolate, "GetPositionInLine", data_obj)
-           .ToHandle(&start_col_obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, 0);
-  return static_cast<int>(start_col_obj->Number());
+      !i::Execution::Call(isolate, fun, undefined, arraysize(args), args)
+           .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int);
+  int start = self->start_position();
+  int end = self->end_position();
+  return Just(static_cast<int>(result->Number()) + (end - start));
 }
 
 
 int Message::GetEndColumn() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Message::GetEndColumn()", return kNoColumnInfo);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> start_col_obj;
-  has_pending_exception =
-      !CallV8HeapFunction(isolate, "GetPositionInLine", data_obj)
-           .ToHandle(&start_col_obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, 0);
-  i::Handle<i::JSMessageObject> message =
-      i::Handle<i::JSMessageObject>::cast(data_obj);
-  int start = message->start_position();
-  int end = message->end_position();
-  return static_cast<int>(start_col_obj->Number()) + (end - start);
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  const int default_value = kNoColumnInfo;
+  return GetEndColumn(context).FromMaybe(default_value);
 }
 
 
 bool Message::IsSharedCrossOrigin() const {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSMessageObject> message =
-      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
-  i::Handle<i::JSValue> script =
-      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
-                                                       isolate));
-  return i::Script::cast(script->value())->is_shared_cross_origin();
+  auto self = Utils::OpenHandle(this);
+  auto script = i::Handle<i::JSValue>::cast(
+      i::Handle<i::Object>(self->script(), isolate));
+  return i::Script::cast(script->value())
+      ->origin_options()
+      .IsSharedCrossOrigin();
+}
+
+bool Message::IsOpaque() const {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ENTER_V8(isolate);
+  auto self = Utils::OpenHandle(this);
+  auto script = i::Handle<i::JSValue>::cast(
+      i::Handle<i::Object>(self->script(), isolate));
+  return i::Script::cast(script->value())->origin_options().IsOpaque();
+}
+
+
+MaybeLocal<String> Message::GetSourceLine(Local<Context> context) const {
+  PREPARE_FOR_EXECUTION(context, "v8::Message::GetSourceLine()", String);
+  i::Handle<i::JSFunction> fun = isolate->message_get_source_line();
+  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
+  i::Handle<i::Object> args[] = {Utils::OpenHandle(this)};
+  i::Handle<i::Object> result;
+  has_pending_exception =
+      !i::Execution::Call(isolate, fun, undefined, arraysize(args), args)
+           .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(String);
+  Local<String> str;
+  if (result->IsString()) {
+    str = Utils::ToLocal(i::Handle<i::String>::cast(result));
+  }
+  RETURN_ESCAPED(str);
 }
 
 
 Local<String> Message::GetSourceLine() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
-  ENTER_V8(isolate);
-  EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> result;
-  has_pending_exception =
-      !CallV8HeapFunction(isolate, "GetSourceLine", Utils::OpenHandle(this))
-           .ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
-  if (result->IsString()) {
-    return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result)));
-  } else {
-    return Local<String>();
-  }
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(GetSourceLine(context), String)
 }
 
 
@@ -2193,24 +2446,19 @@
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
-  i::Handle<i::JSArray> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> obj =
-      i::Object::GetElement(isolate, self, index).ToHandleChecked();
-  i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj);
+  auto self = Utils::OpenHandle(this);
+  auto obj = i::Object::GetElement(isolate, self, index).ToHandleChecked();
+  auto jsobj = i::Handle<i::JSObject>::cast(obj);
   return scope.Escape(Utils::StackFrameToLocal(jsobj));
 }
 
 
 int StackTrace::GetFrameCount() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
   return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
 }
 
 
 Local<Array> StackTrace::AsArray() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
   return Utils::ToLocal(Utils::OpenHandle(this));
 }
 
@@ -2306,23 +2554,124 @@
 }
 
 
-// --- J S O N ---
+// --- N a t i v e W e a k M a p ---
 
-Local<Value> JSON::Parse(Local<String> json_string) {
-  i::Handle<i::String> string = Utils::OpenHandle(*json_string);
-  i::Isolate* isolate = string->GetIsolate();
+Local<NativeWeakMap> NativeWeakMap::New(Isolate* v8_isolate) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  ENTER_V8(isolate);
+  i::Handle<i::JSWeakMap> weakmap = isolate->factory()->NewJSWeakMap();
+  i::JSWeakCollection::Initialize(weakmap, isolate);
+  return Utils::NativeWeakMapToLocal(weakmap);
+}
+
+
+void NativeWeakMap::Set(Local<Value> v8_key, Local<Value> v8_value) {
+  i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this);
+  i::Isolate* isolate = weak_collection->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
+  i::Handle<i::Object> key = Utils::OpenHandle(*v8_key);
+  i::Handle<i::Object> value = Utils::OpenHandle(*v8_value);
+  if (!key->IsJSReceiver() && !key->IsSymbol()) {
+    DCHECK(false);
+    return;
+  }
+  i::Handle<i::ObjectHashTable> table(
+      i::ObjectHashTable::cast(weak_collection->table()));
+  if (!table->IsKey(*key)) {
+    DCHECK(false);
+    return;
+  }
+  int32_t hash = i::Object::GetOrCreateHash(isolate, key)->value();
+  i::JSWeakCollection::Set(weak_collection, key, value, hash);
+}
+
+
+Local<Value> NativeWeakMap::Get(Local<Value> v8_key) {
+  i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this);
+  i::Isolate* isolate = weak_collection->GetIsolate();
+  ENTER_V8(isolate);
+  i::Handle<i::Object> key = Utils::OpenHandle(*v8_key);
+  if (!key->IsJSReceiver() && !key->IsSymbol()) {
+    DCHECK(false);
+    return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+  }
+  i::Handle<i::ObjectHashTable> table(
+      i::ObjectHashTable::cast(weak_collection->table()));
+  if (!table->IsKey(*key)) {
+    DCHECK(false);
+    return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+  }
+  i::Handle<i::Object> lookup(table->Lookup(key), isolate);
+  if (lookup->IsTheHole())
+    return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+  return Utils::ToLocal(lookup);
+}
+
+
+bool NativeWeakMap::Has(Local<Value> v8_key) {
+  i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this);
+  i::Isolate* isolate = weak_collection->GetIsolate();
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  i::Handle<i::Object> key = Utils::OpenHandle(*v8_key);
+  if (!key->IsJSReceiver() && !key->IsSymbol()) {
+    DCHECK(false);
+    return false;
+  }
+  i::Handle<i::ObjectHashTable> table(
+      i::ObjectHashTable::cast(weak_collection->table()));
+  if (!table->IsKey(*key)) {
+    DCHECK(false);
+    return false;
+  }
+  i::Handle<i::Object> lookup(table->Lookup(key), isolate);
+  return !lookup->IsTheHole();
+}
+
+
+bool NativeWeakMap::Delete(Local<Value> v8_key) {
+  i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this);
+  i::Isolate* isolate = weak_collection->GetIsolate();
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  i::Handle<i::Object> key = Utils::OpenHandle(*v8_key);
+  if (!key->IsJSReceiver() && !key->IsSymbol()) {
+    DCHECK(false);
+    return false;
+  }
+  i::Handle<i::ObjectHashTable> table(
+      i::ObjectHashTable::cast(weak_collection->table()));
+  if (!table->IsKey(*key)) {
+    DCHECK(false);
+    return false;
+  }
+  int32_t hash = i::Object::GetOrCreateHash(isolate, key)->value();
+  return i::JSWeakCollection::Delete(weak_collection, key, hash);
+}
+
+
+// --- J S O N ---
+
+MaybeLocal<Value> JSON::Parse(Isolate* v8_isolate, Local<String> json_string) {
+  auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, "JSON::Parse", Value);
+  i::Handle<i::String> string = Utils::OpenHandle(*json_string);
   i::Handle<i::String> source = i::String::Flatten(string);
-  EXCEPTION_PREAMBLE(isolate);
-  i::MaybeHandle<i::Object> maybe_result =
-      source->IsSeqOneByteString() ? i::JsonParser<true>::Parse(source)
-                                   : i::JsonParser<false>::Parse(source);
-  i::Handle<i::Object> result;
-  has_pending_exception = !maybe_result.ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
-  return Utils::ToLocal(
-      i::Handle<i::Object>::cast(scope.CloseAndEscape(result)));
+  auto maybe = source->IsSeqOneByteString()
+                   ? i::JsonParser<true>::Parse(source)
+                   : i::JsonParser<false>::Parse(source);
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(maybe, &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<Value> JSON::Parse(Local<String> json_string) {
+  auto isolate = reinterpret_cast<v8::Isolate*>(
+      Utils::OpenHandle(*json_string)->GetIsolate());
+  RETURN_TO_LOCAL_UNCHECKED(Parse(isolate, json_string), Value);
 }
 
 
@@ -2352,9 +2701,7 @@
 }
 
 
-bool Value::IsFunction() const {
-  return Utils::OpenHandle(this)->IsJSFunction();
-}
+bool Value::IsFunction() const { return Utils::OpenHandle(this)->IsCallable(); }
 
 
 bool Value::IsName() const {
@@ -2380,7 +2727,8 @@
 
 
 bool Value::IsArrayBuffer() const {
-  return Utils::OpenHandle(this)->IsJSArrayBuffer();
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->IsJSArrayBuffer() && !i::JSArrayBuffer::cast(*obj)->is_shared();
 }
 
 
@@ -2394,13 +2742,14 @@
 }
 
 
-#define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size)            \
-  bool Value::Is##Type##Array() const {                                    \
-    i::Handle<i::Object> obj = Utils::OpenHandle(this);                    \
-    return obj->IsJSTypedArray() &&                                        \
-           i::JSTypedArray::cast(*obj)->type() == kExternal##Type##Array;  \
+#define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size)              \
+  bool Value::Is##Type##Array() const {                                      \
+    i::Handle<i::Object> obj = Utils::OpenHandle(this);                      \
+    return obj->IsJSTypedArray() &&                                          \
+           i::JSTypedArray::cast(*obj)->type() == i::kExternal##Type##Array; \
   }
 
+
 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)
 
 #undef VALUE_IS_TYPED_ARRAY
@@ -2411,16 +2760,23 @@
 }
 
 
-bool Value::IsObject() const {
-  return Utils::OpenHandle(this)->IsJSObject();
+bool Value::IsSharedArrayBuffer() const {
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->IsJSArrayBuffer() && i::JSArrayBuffer::cast(*obj)->is_shared();
 }
 
 
+bool Value::IsObject() const { return Utils::OpenHandle(this)->IsJSReceiver(); }
+
+
 bool Value::IsNumber() const {
   return Utils::OpenHandle(this)->IsNumber();
 }
 
 
+bool Value::IsProxy() const { return Utils::OpenHandle(this)->IsJSProxy(); }
+
+
 #define VALUE_IS_SPECIFIC_TYPE(Type, Class)                            \
   bool Value::Is##Type() const {                                       \
     i::Handle<i::Object> obj = Utils::OpenHandle(this);                \
@@ -2477,34 +2833,23 @@
 }
 
 
-static bool CheckConstructor(i::Isolate* isolate,
-                             i::Handle<i::JSObject> obj,
-                             const char* class_name) {
-  i::Handle<i::Object> constr(obj->map()->constructor(), isolate);
-  if (!constr->IsJSFunction()) return false;
-  i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(constr);
-  return func->shared()->native() && constr.is_identical_to(
-      i::Object::GetProperty(isolate,
-                             isolate->js_builtins_object(),
-                             class_name).ToHandleChecked());
-}
-
-
 bool Value::IsNativeError() const {
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  if (obj->IsJSObject()) {
-    i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
-    i::Isolate* isolate = js_obj->GetIsolate();
-    return CheckConstructor(isolate, js_obj, "$Error") ||
-        CheckConstructor(isolate, js_obj, "$EvalError") ||
-        CheckConstructor(isolate, js_obj, "$RangeError") ||
-        CheckConstructor(isolate, js_obj, "$ReferenceError") ||
-        CheckConstructor(isolate, js_obj, "$SyntaxError") ||
-        CheckConstructor(isolate, js_obj, "$TypeError") ||
-        CheckConstructor(isolate, js_obj, "$URIError");
-  } else {
-    return false;
-  }
+  if (!obj->IsJSObject()) return false;
+  i::Handle<i::JSObject> js_obj = i::Handle<i::JSObject>::cast(obj);
+  i::Isolate* isolate = js_obj->GetIsolate();
+  i::Handle<i::Object> constructor(js_obj->map()->GetConstructor(), isolate);
+  if (!constructor->IsJSFunction()) return false;
+  i::Handle<i::JSFunction> function =
+      i::Handle<i::JSFunction>::cast(constructor);
+  if (!function->shared()->native()) return false;
+  return function.is_identical_to(isolate->error_function()) ||
+         function.is_identical_to(isolate->eval_error_function()) ||
+         function.is_identical_to(isolate->range_error_function()) ||
+         function.is_identical_to(isolate->reference_error_function()) ||
+         function.is_identical_to(isolate->syntax_error_function()) ||
+         function.is_identical_to(isolate->type_error_function()) ||
+         function.is_identical_to(isolate->uri_error_function());
 }
 
 
@@ -2537,108 +2882,146 @@
 }
 
 
-Local<String> Value::ToString(Isolate* v8_isolate) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  i::Handle<i::Object> str;
-  if (obj->IsString()) {
-    str = obj;
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToString");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToString(
-        isolate, obj).ToHandle(&str);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
-  }
-  return ToApiHandle<String>(str);
+bool Value::IsPromise() const {
+  auto self = Utils::OpenHandle(this);
+  return i::Object::IsPromise(self);
 }
 
 
-Local<String> Value::ToDetailString(Isolate* v8_isolate) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  i::Handle<i::Object> str;
-  if (obj->IsString()) {
-    str = obj;
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToDetailString");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToDetailString(
-        isolate, obj).ToHandle(&str);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
-  }
-  return ToApiHandle<String>(str);
+MaybeLocal<String> Value::ToString(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsString()) return ToApiHandle<String>(obj);
+  PREPARE_FOR_EXECUTION(context, "ToString", String);
+  Local<String> result;
+  has_pending_exception =
+      !ToLocal<String>(i::Object::ToString(isolate, obj), &result);
+  RETURN_ON_FAILED_EXECUTION(String);
+  RETURN_ESCAPED(result);
 }
 
 
-Local<v8::Object> Value::ToObject(Isolate* v8_isolate) const {
+Local<String> Value::ToString(Isolate* isolate) const {
+  RETURN_TO_LOCAL_UNCHECKED(ToString(isolate->GetCurrentContext()), String);
+}
+
+
+MaybeLocal<String> Value::ToDetailString(Local<Context> context) const {
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  i::Handle<i::Object> val;
-  if (obj->IsJSObject()) {
-    val = obj;
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToObject");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToObject(
-        isolate, obj).ToHandle(&val);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
-  }
-  return ToApiHandle<Object>(val);
+  if (obj->IsString()) return ToApiHandle<String>(obj);
+  PREPARE_FOR_EXECUTION(context, "ToDetailString", String);
+  Local<String> result;
+  i::Handle<i::Object> args[] = {obj};
+  has_pending_exception = !ToLocal<String>(
+      i::Execution::TryCall(isolate, isolate->no_side_effects_to_string_fun(),
+                            isolate->factory()->undefined_value(),
+                            arraysize(args), args),
+      &result);
+  RETURN_ON_FAILED_EXECUTION(String);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<String> Value::ToDetailString(Isolate* isolate) const {
+  RETURN_TO_LOCAL_UNCHECKED(ToDetailString(isolate->GetCurrentContext()),
+                            String);
+}
+
+
+MaybeLocal<Object> Value::ToObject(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsJSObject()) return ToApiHandle<Object>(obj);
+  PREPARE_FOR_EXECUTION(context, "ToObject", Object);
+  Local<Object> result;
+  has_pending_exception =
+      !ToLocal<Object>(i::Execution::ToObject(isolate, obj), &result);
+  RETURN_ON_FAILED_EXECUTION(Object);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<v8::Object> Value::ToObject(Isolate* isolate) const {
+  RETURN_TO_LOCAL_UNCHECKED(ToObject(isolate->GetCurrentContext()), Object);
+}
+
+
+MaybeLocal<Boolean> Value::ToBoolean(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsBoolean()) return ToApiHandle<Boolean>(obj);
+  auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
+  auto val = isolate->factory()->ToBoolean(obj->BooleanValue());
+  return ToApiHandle<Boolean>(val);
 }
 
 
 Local<Boolean> Value::ToBoolean(Isolate* v8_isolate) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  if (obj->IsBoolean()) {
-    return ToApiHandle<Boolean>(obj);
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToBoolean");
-    ENTER_V8(isolate);
-    i::Handle<i::Object> val =
-        isolate->factory()->ToBoolean(obj->BooleanValue());
-    return ToApiHandle<Boolean>(val);
-  }
+  return ToBoolean(v8_isolate->GetCurrentContext()).ToLocalChecked();
 }
 
 
-Local<Number> Value::ToNumber(Isolate* v8_isolate) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  i::Handle<i::Object> num;
-  if (obj->IsNumber()) {
-    num = obj;
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToNumber");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToNumber(
-        isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
-  }
-  return ToApiHandle<Number>(num);
+MaybeLocal<Number> Value::ToNumber(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsNumber()) return ToApiHandle<Number>(obj);
+  PREPARE_FOR_EXECUTION(context, "ToNumber", Number);
+  Local<Number> result;
+  has_pending_exception = !ToLocal<Number>(i::Object::ToNumber(obj), &result);
+  RETURN_ON_FAILED_EXECUTION(Number);
+  RETURN_ESCAPED(result);
 }
 
 
-Local<Integer> Value::ToInteger(Isolate* v8_isolate) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  i::Handle<i::Object> num;
-  if (obj->IsSmi()) {
-    num = obj;
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToInteger");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToInteger(
-        isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
-  }
-  return ToApiHandle<Integer>(num);
+Local<Number> Value::ToNumber(Isolate* isolate) const {
+  RETURN_TO_LOCAL_UNCHECKED(ToNumber(isolate->GetCurrentContext()), Number);
+}
+
+
+MaybeLocal<Integer> Value::ToInteger(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) return ToApiHandle<Integer>(obj);
+  PREPARE_FOR_EXECUTION(context, "ToInteger", Integer);
+  Local<Integer> result;
+  has_pending_exception =
+      !ToLocal<Integer>(i::Object::ToInteger(isolate, obj), &result);
+  RETURN_ON_FAILED_EXECUTION(Integer);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<Integer> Value::ToInteger(Isolate* isolate) const {
+  RETURN_TO_LOCAL_UNCHECKED(ToInteger(isolate->GetCurrentContext()), Integer);
+}
+
+
+MaybeLocal<Int32> Value::ToInt32(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) return ToApiHandle<Int32>(obj);
+  Local<Int32> result;
+  PREPARE_FOR_EXECUTION(context, "ToInt32", Int32);
+  has_pending_exception =
+      !ToLocal<Int32>(i::Object::ToInt32(isolate, obj), &result);
+  RETURN_ON_FAILED_EXECUTION(Int32);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<Int32> Value::ToInt32(Isolate* isolate) const {
+  RETURN_TO_LOCAL_UNCHECKED(ToInt32(isolate->GetCurrentContext()), Int32);
+}
+
+
+MaybeLocal<Uint32> Value::ToUint32(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) return ToApiHandle<Uint32>(obj);
+  Local<Uint32> result;
+  PREPARE_FOR_EXECUTION(context, "ToUint32", Uint32);
+  has_pending_exception =
+      !ToLocal<Uint32>(i::Object::ToUint32(isolate, obj), &result);
+  RETURN_ON_FAILED_EXECUTION(Uint32);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<Uint32> Value::ToUint32(Isolate* isolate) const {
+  RETURN_TO_LOCAL_UNCHECKED(ToUint32(isolate->GetCurrentContext()), Uint32);
 }
 
 
@@ -2660,20 +3043,26 @@
 
 void v8::Object::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsJSObject(),
-                  "v8::Object::Cast()",
+  Utils::ApiCheck(obj->IsJSReceiver(), "v8::Object::Cast()",
                   "Could not convert to object");
 }
 
 
 void v8::Function::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsJSFunction(),
-                  "v8::Function::Cast()",
+  Utils::ApiCheck(obj->IsCallable(), "v8::Function::Cast()",
                   "Could not convert to function");
 }
 
 
+void v8::Boolean::CheckCast(v8::Value* that) {
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  Utils::ApiCheck(obj->IsBoolean(),
+                  "v8::Boolean::Cast()",
+                  "Could not convert to boolean");
+}
+
+
 void v8::Name::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   Utils::ApiCheck(obj->IsName(),
@@ -2714,6 +3103,18 @@
 }
 
 
+void v8::Int32::CheckCast(v8::Value* that) {
+  Utils::ApiCheck(that->IsInt32(), "v8::Int32::Cast()",
+                  "Could not convert to 32-bit signed integer");
+}
+
+
+void v8::Uint32::CheckCast(v8::Value* that) {
+  Utils::ApiCheck(that->IsUint32(), "v8::Uint32::Cast()",
+                  "Could not convert to 32-bit unsigned integer");
+}
+
+
 void v8::Array::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   Utils::ApiCheck(obj->IsJSArray(),
@@ -2722,6 +3123,20 @@
 }
 
 
+void v8::Map::CheckCast(Value* that) {
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  Utils::ApiCheck(obj->IsJSMap(), "v8::Map::Cast()",
+                  "Could not convert to Map");
+}
+
+
+void v8::Set::CheckCast(Value* that) {
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  Utils::ApiCheck(obj->IsJSSet(), "v8::Set::Cast()",
+                  "Could not convert to Set");
+}
+
+
 void v8::Promise::CheckCast(Value* that) {
   Utils::ApiCheck(that->IsPromise(),
                   "v8::Promise::Cast()",
@@ -2736,11 +3151,17 @@
 }
 
 
+void v8::Proxy::CheckCast(Value* that) {
+  Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast()",
+                  "Could not convert to proxy");
+}
+
+
 void v8::ArrayBuffer::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsJSArrayBuffer(),
-                  "v8::ArrayBuffer::Cast()",
-                  "Could not convert to ArrayBuffer");
+  Utils::ApiCheck(
+      obj->IsJSArrayBuffer() && !i::JSArrayBuffer::cast(*obj)->is_shared(),
+      "v8::ArrayBuffer::Cast()", "Could not convert to ArrayBuffer");
 }
 
 
@@ -2763,11 +3184,10 @@
 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size)             \
   void v8::Type##Array::CheckCast(Value* that) {                              \
     i::Handle<i::Object> obj = Utils::OpenHandle(that);                       \
-    Utils::ApiCheck(obj->IsJSTypedArray() &&                                  \
-                    i::JSTypedArray::cast(*obj)->type() ==                    \
-                        kExternal##Type##Array,                               \
-                    "v8::" #Type "Array::Cast()",                             \
-                    "Could not convert to " #Type "Array");                   \
+    Utils::ApiCheck(                                                          \
+        obj->IsJSTypedArray() &&                                              \
+            i::JSTypedArray::cast(*obj)->type() == i::kExternal##Type##Array, \
+        "v8::" #Type "Array::Cast()", "Could not convert to " #Type "Array"); \
   }
 
 
@@ -2784,6 +3204,15 @@
 }
 
 
+void v8::SharedArrayBuffer::CheckCast(Value* that) {
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  Utils::ApiCheck(
+      obj->IsJSArrayBuffer() && i::JSArrayBuffer::cast(*obj)->is_shared(),
+      "v8::SharedArrayBuffer::Cast()",
+      "Could not convert to SharedArrayBuffer");
+}
+
+
 void v8::Date::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   i::Isolate* isolate = NULL;
@@ -2847,100 +3276,112 @@
 }
 
 
+Maybe<bool> Value::BooleanValue(Local<Context> context) const {
+  return Just(Utils::OpenHandle(this)->BooleanValue());
+}
+
+
 bool Value::BooleanValue() const {
   return Utils::OpenHandle(this)->BooleanValue();
 }
 
 
+Maybe<double> Value::NumberValue(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsNumber()) return Just(obj->Number());
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "NumberValue", double);
+  i::Handle<i::Object> num;
+  has_pending_exception = !i::Object::ToNumber(obj).ToHandle(&num);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(double);
+  return Just(num->Number());
+}
+
+
 double Value::NumberValue() const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsNumber()) return obj->Number();
+  return NumberValue(ContextFromHeapObject(obj))
+      .FromMaybe(std::numeric_limits<double>::quiet_NaN());
+}
+
+
+Maybe<int64_t> Value::IntegerValue(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
   i::Handle<i::Object> num;
   if (obj->IsNumber()) {
     num = obj;
   } else {
-    i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
-    LOG_API(isolate, "NumberValue");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToNumber(
-        isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, base::OS::nan_value());
+    PREPARE_FOR_EXECUTION_PRIMITIVE(context, "IntegerValue", int64_t);
+    has_pending_exception = !i::Object::ToInteger(isolate, obj).ToHandle(&num);
+    RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int64_t);
   }
-  return num->Number();
+  return Just(num->IsSmi() ? static_cast<int64_t>(i::Smi::cast(*num)->value())
+                           : static_cast<int64_t>(num->Number()));
 }
 
 
 int64_t Value::IntegerValue() const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  i::Handle<i::Object> num;
+  auto obj = Utils::OpenHandle(this);
   if (obj->IsNumber()) {
-    num = obj;
-  } else {
-    i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
-    LOG_API(isolate, "IntegerValue");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToInteger(
-        isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, 0);
+    if (obj->IsSmi()) {
+      return i::Smi::cast(*obj)->value();
+    } else {
+      return static_cast<int64_t>(obj->Number());
+    }
   }
-  if (num->IsSmi()) {
-    return i::Smi::cast(*num)->value();
-  } else {
-    return static_cast<int64_t>(num->Number());
-  }
+  return IntegerValue(ContextFromHeapObject(obj)).FromMaybe(0);
 }
 
 
-Local<Int32> Value::ToInt32(Isolate* v8_isolate) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+Maybe<int32_t> Value::Int32Value(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsNumber()) return Just(NumberToInt32(*obj));
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Int32Value", int32_t);
   i::Handle<i::Object> num;
-  if (obj->IsSmi()) {
-    num = obj;
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToInt32");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
-  }
-  return ToApiHandle<Int32>(num);
+  has_pending_exception = !i::Object::ToInt32(isolate, obj).ToHandle(&num);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int32_t);
+  return Just(num->IsSmi() ? i::Smi::cast(*num)->value()
+                           : static_cast<int32_t>(num->Number()));
 }
 
 
-Local<Uint32> Value::ToUint32(Isolate* v8_isolate) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+int32_t Value::Int32Value() const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsNumber()) return NumberToInt32(*obj);
+  return Int32Value(ContextFromHeapObject(obj)).FromMaybe(0);
+}
+
+
+Maybe<uint32_t> Value::Uint32Value(Local<Context> context) const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsNumber()) return Just(NumberToUint32(*obj));
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Uint32Value", uint32_t);
   i::Handle<i::Object> num;
-  if (obj->IsSmi()) {
-    num = obj;
-  } else {
-    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-    LOG_API(isolate, "ToUInt32");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToUint32(
-        isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
-  }
-  return ToApiHandle<Uint32>(num);
+  has_pending_exception = !i::Object::ToUint32(isolate, obj).ToHandle(&num);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(uint32_t);
+  return Just(num->IsSmi() ? static_cast<uint32_t>(i::Smi::cast(*num)->value())
+                           : static_cast<uint32_t>(num->Number()));
 }
 
 
-Local<Uint32> Value::ToArrayIndex() const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  if (obj->IsSmi()) {
-    if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
+uint32_t Value::Uint32Value() const {
+  auto obj = Utils::OpenHandle(this);
+  if (obj->IsNumber()) return NumberToUint32(*obj);
+  return Uint32Value(ContextFromHeapObject(obj)).FromMaybe(0);
+}
+
+
+MaybeLocal<Uint32> Value::ToArrayIndex(Local<Context> context) const {
+  auto self = Utils::OpenHandle(this);
+  if (self->IsSmi()) {
+    if (i::Smi::cast(*self)->value() >= 0) return Utils::Uint32ToLocal(self);
     return Local<Uint32>();
   }
-  i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
-  LOG_API(isolate, "ToArrayIndex");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
+  PREPARE_FOR_EXECUTION(context, "ToArrayIndex", Uint32);
   i::Handle<i::Object> string_obj;
-  has_pending_exception = !i::Execution::ToString(
-      isolate, obj).ToHandle(&string_obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
+  has_pending_exception =
+      !i::Object::ToString(isolate, self).ToHandle(&string_obj);
+  RETURN_ON_FAILED_EXECUTION(Uint32);
   i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
   uint32_t index;
   if (str->AsArrayIndex(&index)) {
@@ -2950,1300 +3391,1091 @@
     } else {
       value = isolate->factory()->NewNumber(index);
     }
-    return Utils::Uint32ToLocal(value);
+    RETURN_ESCAPED(Utils::Uint32ToLocal(value));
   }
   return Local<Uint32>();
 }
 
 
-int32_t Value::Int32Value() const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  if (obj->IsSmi()) {
-    return i::Smi::cast(*obj)->value();
-  } else {
-    i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
-    LOG_API(isolate, "Int32Value (slow)");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    i::Handle<i::Object> num;
-    has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, 0);
-    if (num->IsSmi()) {
-      return i::Smi::cast(*num)->value();
-    } else {
-      return static_cast<int32_t>(num->Number());
-    }
+Local<Uint32> Value::ToArrayIndex() const {
+  auto self = Utils::OpenHandle(this);
+  if (self->IsSmi()) {
+    if (i::Smi::cast(*self)->value() >= 0) return Utils::Uint32ToLocal(self);
+    return Local<Uint32>();
   }
+  auto context = ContextFromHeapObject(self);
+  RETURN_TO_LOCAL_UNCHECKED(ToArrayIndex(context), Uint32);
 }
 
 
-bool Value::Equals(Handle<Value> that) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
-  i::Handle<i::Object> other = Utils::OpenHandle(*that);
-  if (obj->IsSmi() && other->IsSmi()) {
-    return obj->Number() == other->Number();
-  }
-  i::Object* ho = obj->IsSmi() ? *other : *obj;
-  i::Isolate* isolate = i::HeapObject::cast(ho)->GetIsolate();
-  if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
-                       "v8::Value::Equals()",
-                       "Reading from empty handle")) {
-    return false;
-  }
-  LOG_API(isolate, "Equals");
-  ENTER_V8(isolate);
-  // If both obj and other are JSObjects, we'd better compare by identity
-  // immediately when going into JS builtin.  The reason is Invoke
-  // would overwrite global object receiver with global proxy.
-  if (obj->IsJSObject() && other->IsJSObject()) {
-    return *obj == *other;
-  }
-  i::Handle<i::Object> args[] = { other };
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> result;
-  has_pending_exception =
-      !CallV8HeapFunction(isolate, "EQUALS", obj, arraysize(args), args)
-           .ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return *result == i::Smi::FromInt(i::EQUAL);
+Maybe<bool> Value::Equals(Local<Context> context, Local<Value> that) const {
+  auto self = Utils::OpenHandle(this);
+  auto other = Utils::OpenHandle(*that);
+  return i::Object::Equals(self, other);
 }
 
 
-bool Value::StrictEquals(Handle<Value> that) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
-  i::Handle<i::Object> other = Utils::OpenHandle(*that);
-  if (obj->IsSmi()) {
-    return other->IsNumber() && obj->Number() == other->Number();
+bool Value::Equals(Local<Value> that) const {
+  auto self = Utils::OpenHandle(this);
+  auto other = Utils::OpenHandle(*that);
+  if (self->IsSmi() && other->IsSmi()) {
+    return self->Number() == other->Number();
   }
-  i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
-  if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
-                       "v8::Value::StrictEquals()",
-                       "Reading from empty handle")) {
-    return false;
+  if (self->IsJSObject() && other->IsJSObject()) {
+    return *self == *other;
   }
-  LOG_API(isolate, "StrictEquals");
-  // Must check HeapNumber first, since NaN !== NaN.
-  if (obj->IsHeapNumber()) {
-    if (!other->IsNumber()) return false;
-    double x = obj->Number();
-    double y = other->Number();
-    // Must check explicitly for NaN:s on Windows, but -0 works fine.
-    return x == y && !std::isnan(x) && !std::isnan(y);
-  } else if (*obj == *other) {  // Also covers Booleans.
-    return true;
-  } else if (obj->IsSmi()) {
-    return other->IsNumber() && obj->Number() == other->Number();
-  } else if (obj->IsString()) {
-    return other->IsString() &&
-        i::String::Equals(i::Handle<i::String>::cast(obj),
-                          i::Handle<i::String>::cast(other));
-  } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
-    return other->IsUndefined() || other->IsUndetectableObject();
-  } else {
-    return false;
-  }
+  auto heap_object = self->IsSmi() ? other : self;
+  auto context = ContextFromHeapObject(heap_object);
+  return Equals(context, that).FromMaybe(false);
 }
 
 
-bool Value::SameValue(Handle<Value> that) const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
-  if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
-                       "v8::Value::SameValue()",
-                       "Reading from empty handle")) {
-    return false;
-  }
-  i::Handle<i::Object> other = Utils::OpenHandle(*that);
-  return obj->SameValue(*other);
+bool Value::StrictEquals(Local<Value> that) const {
+  auto self = Utils::OpenHandle(this);
+  auto other = Utils::OpenHandle(*that);
+  return self->StrictEquals(*other);
 }
 
 
-uint32_t Value::Uint32Value() const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  if (obj->IsSmi()) {
-    return i::Smi::cast(*obj)->value();
-  } else {
-    i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
-    LOG_API(isolate, "Uint32Value");
-    ENTER_V8(isolate);
-    EXCEPTION_PREAMBLE(isolate);
-    i::Handle<i::Object> num;
-    has_pending_exception = !i::Execution::ToUint32(
-        isolate, obj).ToHandle(&num);
-    EXCEPTION_BAILOUT_CHECK(isolate, 0);
-    if (num->IsSmi()) {
-      return i::Smi::cast(*num)->value();
-    } else {
-      return static_cast<uint32_t>(num->Number());
-    }
-  }
+bool Value::SameValue(Local<Value> that) const {
+  auto self = Utils::OpenHandle(this);
+  auto other = Utils::OpenHandle(*that);
+  return self->SameValue(*other);
 }
 
 
-bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::Set()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::Object> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
-  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  EXCEPTION_PREAMBLE(isolate);
+Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context,
+                            v8::Local<Value> key, v8::Local<Value> value) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Set()", bool);
+  auto self = Utils::OpenHandle(this);
+  auto key_obj = Utils::OpenHandle(*key);
+  auto value_obj = Utils::OpenHandle(*value);
   has_pending_exception =
       i::Runtime::SetObjectProperty(isolate, self, key_obj, value_obj,
                                     i::SLOPPY).is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return true;
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(true);
 }
 
 
-bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::Set()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+bool v8::Object::Set(v8::Local<Value> key, v8::Local<Value> value) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return Set(context, key, value).FromMaybe(false);
+}
+
+
+Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context, uint32_t index,
+                            v8::Local<Value> value) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Set()", bool);
+  auto self = Utils::OpenHandle(this);
+  auto value_obj = Utils::OpenHandle(*value);
+  has_pending_exception = i::Object::SetElement(isolate, self, index, value_obj,
+                                                i::SLOPPY).is_null();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(true);
+}
+
+
+bool v8::Object::Set(uint32_t index, v8::Local<Value> value) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return Set(context, index, value).FromMaybe(false);
+}
+
+
+Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
+                                           v8::Local<Name> key,
+                                           v8::Local<Value> value) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::CreateDataProperty()",
+                                  bool);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  EXCEPTION_PREAMBLE(isolate);
-  has_pending_exception = i::JSObject::SetElement(
-      self, index, value_obj, NONE, i::SLOPPY).is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return true;
+
+  i::LookupIterator it = i::LookupIterator::PropertyOrElement(
+      isolate, self, key_obj, i::LookupIterator::OWN);
+  Maybe<bool> result =
+      i::JSReceiver::CreateDataProperty(&it, value_obj, i::Object::DONT_THROW);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
 }
 
 
-bool v8::Object::ForceSet(v8::Handle<Value> key,
-                          v8::Handle<Value> value,
+Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
+                                           uint32_t index,
+                                           v8::Local<Value> value) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::CreateDataProperty()",
+                                  bool);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+
+  i::LookupIterator it(isolate, self, index, i::LookupIterator::OWN);
+  Maybe<bool> result =
+      i::JSReceiver::CreateDataProperty(&it, value_obj, i::Object::DONT_THROW);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
+}
+
+
+Maybe<bool> v8::Object::DefineOwnProperty(v8::Local<v8::Context> context,
+                                          v8::Local<Name> key,
+                                          v8::Local<Value> value,
+                                          v8::PropertyAttribute attributes) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::DefineOwnProperty()",
+                                  bool);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
+  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+
+  if (self->IsAccessCheckNeeded() &&
+      !isolate->MayAccess(handle(isolate->context()),
+                          i::Handle<i::JSObject>::cast(self))) {
+    isolate->ReportFailedAccessCheck(i::Handle<i::JSObject>::cast(self));
+    return Nothing<bool>();
+  }
+
+  i::PropertyDescriptor desc;
+  desc.set_writable(!(attributes & v8::ReadOnly));
+  desc.set_enumerable(!(attributes & v8::DontEnum));
+  desc.set_configurable(!(attributes & v8::DontDelete));
+  desc.set_value(value_obj);
+  Maybe<bool> success = i::JSReceiver::DefineOwnProperty(
+      isolate, self, key_obj, &desc, i::Object::DONT_THROW);
+  // Even though we said DONT_THROW, there might be accessors that do throw.
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return success;
+}
+
+
+MUST_USE_RESULT
+static i::MaybeHandle<i::Object> DefineObjectProperty(
+    i::Handle<i::JSObject> js_object, i::Handle<i::Object> key,
+    i::Handle<i::Object> value, i::PropertyAttributes attrs) {
+  i::Isolate* isolate = js_object->GetIsolate();
+  bool success = false;
+  i::LookupIterator it = i::LookupIterator::PropertyOrElement(
+      isolate, js_object, key, &success, i::LookupIterator::OWN);
+  if (!success) return i::MaybeHandle<i::Object>();
+
+  return i::JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attrs);
+}
+
+
+Maybe<bool> v8::Object::ForceSet(v8::Local<v8::Context> context,
+                                 v8::Local<Value> key, v8::Local<Value> value,
+                                 v8::PropertyAttribute attribs) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::ForceSet()", bool);
+  auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+  auto key_obj = Utils::OpenHandle(*key);
+  auto value_obj = Utils::OpenHandle(*value);
+  has_pending_exception =
+      DefineObjectProperty(self, key_obj, value_obj,
+                           static_cast<i::PropertyAttributes>(attribs))
+          .is_null();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(true);
+}
+
+
+bool v8::Object::ForceSet(v8::Local<Value> key, v8::Local<Value> value,
                           v8::PropertyAttribute attribs) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(),
+                                "v8::Object::ForceSet", false, i::HandleScope,
+                                false);
+  i::Handle<i::JSObject> self =
+      i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  EXCEPTION_PREAMBLE(isolate);
-  has_pending_exception = i::Runtime::DefineObjectProperty(
-      self,
-      key_obj,
-      value_obj,
-      static_cast<PropertyAttributes>(attribs)).is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
+  has_pending_exception =
+      DefineObjectProperty(self, key_obj, value_obj,
+                           static_cast<i::PropertyAttributes>(attribs))
+          .is_null();
+  EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, false);
   return true;
 }
 
 
-bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) {
-  return ForceSet(v8::Handle<Value>(reinterpret_cast<Value*>(*key)),
-                  value, DontEnum);
+Maybe<bool> v8::Object::SetPrivate(Local<Context> context, Local<Private> key,
+                                   Local<Value> value) {
+  return DefineOwnProperty(context, Local<Name>(reinterpret_cast<Name*>(*key)),
+                           value, DontEnum);
 }
 
 
-i::MaybeHandle<i::Object> DeleteObjectProperty(
-    i::Isolate* isolate, i::Handle<i::JSReceiver> receiver,
-    i::Handle<i::Object> key, i::JSReceiver::DeleteMode mode) {
-  // Check if the given key is an array index.
-  uint32_t index;
-  if (key->ToArrayIndex(&index)) {
-    // In Firefox/SpiderMonkey, Safari and Opera you can access the
-    // characters of a string using [] notation.  In the case of a
-    // String object we just need to redirect the deletion to the
-    // underlying string if the index is in range.  Since the
-    // underlying string does nothing with the deletion, we can ignore
-    // such deletions.
-    if (receiver->IsStringObjectWithCharacterAt(index)) {
-      return isolate->factory()->true_value();
-    }
-
-    return i::JSReceiver::DeleteElement(receiver, index, mode);
-  }
-
-  i::Handle<i::Name> name;
-  if (key->IsName()) {
-    name = i::Handle<i::Name>::cast(key);
-  } else {
-    // Call-back into JavaScript to convert the key to a string.
-    i::Handle<i::Object> converted;
-    if (!i::Execution::ToString(isolate, key).ToHandle(&converted)) {
-      return i::MaybeHandle<i::Object>();
-    }
-    name = i::Handle<i::String>::cast(converted);
-  }
-
-  if (name->IsString()) {
-    name = i::String::Flatten(i::Handle<i::String>::cast(name));
-  }
-  return i::JSReceiver::DeleteProperty(receiver, name, mode);
-}
-
-
-bool v8::Object::ForceDelete(v8::Handle<Value> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
-
-  // When deleting a property on the global object using ForceDelete
-  // deoptimize all functions as optimized code does not check for the hole
-  // value with DontDelete properties.  We have to deoptimize all contexts
-  // because of possible cross-context inlined functions.
-  if (self->IsJSGlobalProxy() || self->IsGlobalObject()) {
-    i::Deoptimizer::DeoptimizeAll(isolate);
-  }
-
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> obj;
-  has_pending_exception =
-      !DeleteObjectProperty(isolate, self, key_obj,
-                            i::JSReceiver::FORCE_DELETION).ToHandle(&obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return obj->IsTrue();
-}
-
-
-Local<Value> v8::Object::Get(v8::Handle<Value> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
-  ENTER_V8(isolate);
-  i::Handle<i::Object> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
-  EXCEPTION_PREAMBLE(isolate);
+MaybeLocal<Value> v8::Object::Get(Local<v8::Context> context,
+                                  Local<Value> key) {
+  PREPARE_FOR_EXECUTION(context, "v8::Object::Get()", Value);
+  auto self = Utils::OpenHandle(this);
+  auto key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> result;
   has_pending_exception =
       !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
-  return Utils::ToLocal(result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(Utils::ToLocal(result));
+}
+
+
+Local<Value> v8::Object::Get(v8::Local<Value> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(Get(context, key), Value);
+}
+
+
+MaybeLocal<Value> v8::Object::Get(Local<Context> context, uint32_t index) {
+  PREPARE_FOR_EXECUTION(context, "v8::Object::Get()", Value);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> result;
+  has_pending_exception =
+      !i::Object::GetElement(isolate, self, index).ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(Utils::ToLocal(result));
 }
 
 
 Local<Value> v8::Object::Get(uint32_t index) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> result;
-  has_pending_exception =
-      !i::Object::GetElement(isolate, self, index).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
-  return Utils::ToLocal(result);
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(Get(context, index), Value);
 }
 
 
-Local<Value> v8::Object::GetPrivate(v8::Handle<Private> key) {
-  return Get(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
+MaybeLocal<Value> v8::Object::GetPrivate(Local<Context> context,
+                                         Local<Private> key) {
+  return Get(context, Local<Value>(reinterpret_cast<Value*>(*key)));
 }
 
 
-PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetPropertyAttributes()",
-             return static_cast<PropertyAttribute>(NONE));
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+Maybe<PropertyAttribute> v8::Object::GetPropertyAttributes(
+    Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(
+      context, "v8::Object::GetPropertyAttributes()", PropertyAttribute);
+  auto self = Utils::OpenHandle(this);
+  auto key_obj = Utils::OpenHandle(*key);
   if (!key_obj->IsName()) {
-    EXCEPTION_PREAMBLE(isolate);
-    has_pending_exception = !i::Execution::ToString(
-        isolate, key_obj).ToHandle(&key_obj);
-    EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
+    has_pending_exception =
+        !i::Object::ToString(isolate, key_obj).ToHandle(&key_obj);
+    RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
   }
-  i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
-  EXCEPTION_PREAMBLE(isolate);
-  Maybe<PropertyAttributes> result =
-      i::JSReceiver::GetPropertyAttributes(self, key_name);
-  has_pending_exception = !result.has_value;
-  EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
-  if (result.value == ABSENT) return static_cast<PropertyAttribute>(NONE);
-  return static_cast<PropertyAttribute>(result.value);
+  auto key_name = i::Handle<i::Name>::cast(key_obj);
+  auto result = i::JSReceiver::GetPropertyAttributes(self, key_name);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
+  if (result.FromJust() == i::ABSENT) {
+    return Just(static_cast<PropertyAttribute>(i::NONE));
+  }
+  return Just(static_cast<PropertyAttribute>(result.FromJust()));
+}
+
+
+PropertyAttribute v8::Object::GetPropertyAttributes(v8::Local<Value> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return GetPropertyAttributes(context, key)
+      .FromMaybe(static_cast<PropertyAttribute>(i::NONE));
+}
+
+
+MaybeLocal<Value> v8::Object::GetOwnPropertyDescriptor(Local<Context> context,
+                                                       Local<String> key) {
+  PREPARE_FOR_EXECUTION(context, "v8::Object::GetOwnPropertyDescriptor()",
+                        Value);
+  i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
+  i::Handle<i::String> key_name = Utils::OpenHandle(*key);
+
+  i::PropertyDescriptor desc;
+  Maybe<bool> found =
+      i::JSReceiver::GetOwnPropertyDescriptor(isolate, obj, key_name, &desc);
+  has_pending_exception = found.IsNothing();
+  RETURN_ON_FAILED_EXECUTION(Value);
+  if (!found.FromJust()) {
+    return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+  }
+  RETURN_ESCAPED(Utils::ToLocal(desc.ToObject(isolate)));
 }
 
 
 Local<Value> v8::Object::GetOwnPropertyDescriptor(Local<String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyDescriptor()",
-             return Local<Value>());
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  i::Handle<i::Name> key_name = Utils::OpenHandle(*key);
-  i::Handle<i::Object> args[] = { obj, key_name };
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> result;
-  has_pending_exception =
-      !CallV8HeapFunction(isolate, "ObjectGetOwnPropertyDescriptor",
-                          isolate->factory()->undefined_value(),
-                          arraysize(args), args).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
-  return Utils::ToLocal(result);
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyDescriptor(context, key), Value);
 }
 
 
 Local<Value> v8::Object::GetPrototype() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>());
-  ENTER_V8(isolate);
-  i::Handle<i::Object> self = Utils::OpenHandle(this);
+  auto isolate = Utils::OpenHandle(this)->GetIsolate();
+  auto self = Utils::OpenHandle(this);
   i::PrototypeIterator iter(isolate, self);
   return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
 }
 
 
-bool v8::Object::SetPrototype(Handle<Value> value) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+Maybe<bool> v8::Object::SetPrototype(Local<Context> context,
+                                     Local<Value> value) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::SetPrototype()", bool);
+  auto self = Utils::OpenHandle(this);
+  auto value_obj = Utils::OpenHandle(*value);
   // We do not allow exceptions thrown while setting the prototype
   // to propagate outside.
-  TryCatch try_catch;
-  EXCEPTION_PREAMBLE(isolate);
-  i::MaybeHandle<i::Object> result =
-      i::JSObject::SetPrototype(self, value_obj, false);
-  has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return true;
+  TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
+  auto result = i::JSReceiver::SetPrototype(self, value_obj, false,
+                                            i::Object::THROW_ON_ERROR);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(true);
+}
+
+
+bool v8::Object::SetPrototype(Local<Value> value) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return SetPrototype(context, value).FromMaybe(false);
 }
 
 
 Local<Object> v8::Object::FindInstanceInPrototypeChain(
-    v8::Handle<FunctionTemplate> tmpl) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate,
-             "v8::Object::FindInstanceInPrototypeChain()",
-             return Local<v8::Object>());
-  ENTER_V8(isolate);
+    v8::Local<FunctionTemplate> tmpl) {
+  auto isolate = Utils::OpenHandle(this)->GetIsolate();
   i::PrototypeIterator iter(isolate, *Utils::OpenHandle(this),
                             i::PrototypeIterator::START_AT_RECEIVER);
-  i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
+  auto tmpl_info = *Utils::OpenHandle(*tmpl);
   while (!tmpl_info->IsTemplateFor(iter.GetCurrent())) {
     iter.Advance();
     if (iter.IsAtEnd()) {
       return Local<Object>();
     }
   }
-  return Utils::ToLocal(
-      i::handle(i::JSObject::cast(iter.GetCurrent()), isolate));
+  // IsTemplateFor() ensures that iter.GetCurrent() can't be a Proxy here.
+  return Utils::ToLocal(i::handle(iter.GetCurrent<i::JSObject>(), isolate));
+}
+
+
+MaybeLocal<Array> v8::Object::GetPropertyNames(Local<Context> context) {
+  PREPARE_FOR_EXECUTION(context, "v8::Object::GetPropertyNames()", Array);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::FixedArray> value;
+  has_pending_exception =
+      !i::JSReceiver::GetKeys(self, i::JSReceiver::INCLUDE_PROTOS,
+                              i::ENUMERABLE_STRINGS)
+           .ToHandle(&value);
+  RETURN_ON_FAILED_EXECUTION(Array);
+  // Because we use caching to speed up enumeration it is important
+  // to never change the result of the basic enumeration function so
+  // we clone the result.
+  auto elms = isolate->factory()->CopyFixedArray(value);
+  auto result = isolate->factory()->NewJSArrayWithElements(elms);
+  RETURN_ESCAPED(Utils::ToLocal(result));
 }
 
 
 Local<Array> v8::Object::GetPropertyNames() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
-             return Local<v8::Array>());
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE(isolate);
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(GetPropertyNames(context), Array);
+}
+
+
+MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) {
+  PREPARE_FOR_EXECUTION(context, "v8::Object::GetOwnPropertyNames()", Array);
+  auto self = Utils::OpenHandle(this);
   i::Handle<i::FixedArray> value;
-  has_pending_exception = !i::JSReceiver::GetKeys(
-      self, i::JSReceiver::INCLUDE_PROTOS).ToHandle(&value);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
+  has_pending_exception = !i::JSReceiver::GetKeys(self, i::JSReceiver::OWN_ONLY,
+                                                  i::ENUMERABLE_STRINGS)
+                               .ToHandle(&value);
+  RETURN_ON_FAILED_EXECUTION(Array);
   // Because we use caching to speed up enumeration it is important
   // to never change the result of the basic enumeration function so
   // we clone the result.
-  i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
-  i::Handle<i::JSArray> result =
-      isolate->factory()->NewJSArrayWithElements(elms);
-  return Utils::ToLocal(scope.CloseAndEscape(result));
+  auto elms = isolate->factory()->CopyFixedArray(value);
+  auto result = isolate->factory()->NewJSArrayWithElements(elms);
+  RETURN_ESCAPED(Utils::ToLocal(result));
 }
 
 
 Local<Array> v8::Object::GetOwnPropertyNames() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()",
-             return Local<v8::Array>());
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::FixedArray> value;
-  has_pending_exception = !i::JSReceiver::GetKeys(
-      self, i::JSReceiver::OWN_ONLY).ToHandle(&value);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
-  // Because we use caching to speed up enumeration it is important
-  // to never change the result of the basic enumeration function so
-  // we clone the result.
-  i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
-  i::Handle<i::JSArray> result =
-      isolate->factory()->NewJSArrayWithElements(elms);
-  return Utils::ToLocal(scope.CloseAndEscape(result));
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyNames(context), Array);
 }
 
 
-static bool GetPredefinedToString(i::Handle<i::String> tag,
-                                  Local<String>* result) {
-  i::Isolate* i_isolate = tag->GetIsolate();
-  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
-  i::Factory* factory = i_isolate->factory();
-
-  if (i::String::Equals(tag, factory->Arguments_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Arguments]");
-  } else if (i::String::Equals(tag, factory->Array_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Array]");
-  } else if (i::String::Equals(tag, factory->Boolean_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Boolean]");
-  } else if (i::String::Equals(tag, factory->Date_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Date]");
-  } else if (i::String::Equals(tag, factory->Error_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Error]");
-  } else if (i::String::Equals(tag, factory->Function_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Function]");
-  } else if (i::String::Equals(tag, factory->Number_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Number]");
-  } else if (i::String::Equals(tag, factory->RegExp_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~RegExp]");
-  } else if (i::String::Equals(tag, factory->String_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~String]");
-  } else {
-    return false;
-  }
-  return true;
+MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) {
+  PREPARE_FOR_EXECUTION(context, "v8::Object::ObjectProtoToString", String);
+  auto obj = Utils::OpenHandle(this);
+  Local<String> result;
+  has_pending_exception =
+      !ToLocal<String>(i::JSObject::ObjectProtoToString(isolate, obj), &result);
+  RETURN_ON_FAILED_EXECUTION(String);
+  RETURN_ESCAPED(result);
 }
 
 
 Local<String> v8::Object::ObjectProtoToString() {
-  i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
-  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
-  ON_BAILOUT(i_isolate, "v8::Object::ObjectProtoToString()",
-             return Local<v8::String>());
-  ENTER_V8(i_isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-
-  i::Handle<i::Object> name(self->class_name(), i_isolate);
-  i::Handle<i::Object> tag;
-
-  // Native implementation of Object.prototype.toString (v8natives.js):
-  //   var c = %_ClassOf(this);
-  //   if (c === 'Arguments') c  = 'Object';
-  //   return "[object " + c + "]";
-
-  if (!name->IsString()) {
-    return v8::String::NewFromUtf8(isolate, "[object ]");
-  } else {
-    i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
-    if (i::String::Equals(class_name,
-                          i_isolate->factory()->Arguments_string())) {
-      return v8::String::NewFromUtf8(isolate, "[object Object]");
-    } else {
-      if (internal::FLAG_harmony_tostring) {
-        i::Handle<i::Symbol> toStringTag =
-            Utils::OpenHandle(*Symbol::GetToStringTag(isolate));
-        EXCEPTION_PREAMBLE(i_isolate);
-        has_pending_exception =
-            !i::Runtime::GetObjectProperty(i_isolate, self, toStringTag)
-                 .ToHandle(&tag);
-        EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::String>());
-
-        if (!tag->IsUndefined()) {
-          if (!tag->IsString())
-            return v8::String::NewFromUtf8(isolate, "[object ???]");
-          i::Handle<i::String> tag_name = i::Handle<i::String>::cast(tag);
-          if (!i::String::Equals(class_name, tag_name)) {
-            Local<String> result;
-            if (GetPredefinedToString(tag_name, &result)) return result;
-
-            class_name = tag_name;
-          }
-        }
-      }
-      const char* prefix = "[object ";
-      Local<String> str = Utils::ToLocal(class_name);
-      const char* postfix = "]";
-
-      int prefix_len = i::StrLength(prefix);
-      int str_len = str->Utf8Length();
-      int postfix_len = i::StrLength(postfix);
-
-      int buf_len = prefix_len + str_len + postfix_len;
-      i::ScopedVector<char> buf(buf_len);
-
-      // Write prefix.
-      char* ptr = buf.start();
-      i::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize);
-      ptr += prefix_len;
-
-      // Write real content.
-      str->WriteUtf8(ptr, str_len);
-      ptr += str_len;
-
-      // Write postfix.
-      i::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize);
-
-      // Copy the buffer into a heap-allocated string and return it.
-      Local<String> result = v8::String::NewFromUtf8(
-          isolate, buf.start(), String::kNormalString, buf_len);
-      return result;
-    }
-  }
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(ObjectProtoToString(context), String);
 }
 
 
 Local<String> v8::Object::GetConstructorName() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
-             return Local<v8::String>());
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  i::Handle<i::String> name(self->constructor_name());
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::String> name = i::JSReceiver::GetConstructorName(self);
   return Utils::ToLocal(name);
 }
 
 
-bool v8::Object::Delete(v8::Handle<Value> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> obj;
-  has_pending_exception =
-      !DeleteObjectProperty(isolate, self, key_obj,
-                            i::JSReceiver::NORMAL_DELETION).ToHandle(&obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return obj->IsTrue();
+Maybe<bool> v8::Object::Delete(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Delete()", bool);
+  auto self = Utils::OpenHandle(this);
+  auto key_obj = Utils::OpenHandle(*key);
+  Maybe<bool> result =
+      i::Runtime::DeleteObjectProperty(isolate, self, key_obj, i::SLOPPY);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
 }
 
 
-bool v8::Object::DeletePrivate(v8::Handle<Private> key) {
-  return Delete(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
+bool v8::Object::Delete(v8::Local<Value> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return Delete(context, key).FromMaybe(false);
 }
 
 
-bool v8::Object::Has(v8::Handle<Value> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::Has()", return false);
-  ENTER_V8(isolate);
-  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
-  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
-  EXCEPTION_PREAMBLE(isolate);
-  Maybe<bool> maybe;
+Maybe<bool> v8::Object::DeletePrivate(Local<Context> context,
+                                      Local<Private> key) {
+  return Delete(context, Local<Value>(reinterpret_cast<Value*>(*key)));
+}
+
+
+Maybe<bool> v8::Object::Has(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Get()", bool);
+  auto self = Utils::OpenHandle(this);
+  auto key_obj = Utils::OpenHandle(*key);
+  Maybe<bool> maybe = Nothing<bool>();
   // Check if the given key is an array index.
-  uint32_t index;
+  uint32_t index = 0;
   if (key_obj->ToArrayIndex(&index)) {
     maybe = i::JSReceiver::HasElement(self, index);
   } else {
     // Convert the key to a name - possibly by calling back into JavaScript.
     i::Handle<i::Name> name;
-    if (i::Runtime::ToName(isolate, key_obj).ToHandle(&name)) {
+    if (i::Object::ToName(isolate, key_obj).ToHandle(&name)) {
       maybe = i::JSReceiver::HasProperty(self, name);
     }
   }
-  if (!maybe.has_value) has_pending_exception = true;
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  DCHECK(maybe.has_value);
-  return maybe.value;
+  has_pending_exception = maybe.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return maybe;
 }
 
 
-bool v8::Object::HasPrivate(v8::Handle<Private> key) {
-  // TODO(rossberg): this should use HasOwnProperty, but we'd need to
-  // generalise that to a (noy yet existant) Name argument first.
-  return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
+bool v8::Object::Has(v8::Local<Value> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return Has(context, key).FromMaybe(false);
+}
+
+
+Maybe<bool> v8::Object::HasPrivate(Local<Context> context, Local<Private> key) {
+  return HasOwnProperty(context, Local<Name>(reinterpret_cast<Name*>(*key)));
+}
+
+
+Maybe<bool> v8::Object::Delete(Local<Context> context, uint32_t index) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::DeleteProperty()",
+                                  bool);
+  auto self = Utils::OpenHandle(this);
+  Maybe<bool> result = i::JSReceiver::DeleteElement(self, index);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
 }
 
 
 bool v8::Object::Delete(uint32_t index) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
-             return false);
-  ENTER_V8(isolate);
-  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return Delete(context, index).FromMaybe(false);
+}
 
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> obj;
-  has_pending_exception =
-      !i::JSReceiver::DeleteElement(self, index).ToHandle(&obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return obj->IsTrue();
+
+Maybe<bool> v8::Object::Has(Local<Context> context, uint32_t index) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Get()", bool);
+  auto self = Utils::OpenHandle(this);
+  auto maybe = i::JSReceiver::HasElement(self, index);
+  has_pending_exception = maybe.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return maybe;
 }
 
 
 bool v8::Object::Has(uint32_t index) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE(isolate);
-  Maybe<bool> maybe = i::JSReceiver::HasElement(self, index);
-  has_pending_exception = !maybe.has_value;
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return maybe.value;
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return Has(context, index).FromMaybe(false);
 }
 
 
-template<typename Getter, typename Setter, typename Data>
-static inline bool ObjectSetAccessor(Object* obj,
-                                     Handle<Name> name,
-                                     Getter getter,
-                                     Setter setter,
-                                     Data data,
+template <typename Getter, typename Setter, typename Data>
+static Maybe<bool> ObjectSetAccessor(Local<Context> context, Object* self,
+                                     Local<Name> name, Getter getter,
+                                     Setter setter, Data data,
                                      AccessControl settings,
                                      PropertyAttribute attributes) {
-  i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  v8::Handle<AccessorSignature> signature;
-  i::Handle<i::AccessorInfo> info = MakeAccessorInfo(
-      name, getter, setter, data, settings, attributes, signature);
-  if (info.is_null()) return false;
-  bool fast = Utils::OpenHandle(obj)->HasFastProperties();
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::SetAccessor()", bool);
+  if (!Utils::OpenHandle(self)->IsJSObject()) return Just(false);
+  i::Handle<i::JSObject> obj =
+      i::Handle<i::JSObject>::cast(Utils::OpenHandle(self));
+  v8::Local<AccessorSignature> signature;
+  auto info = MakeAccessorInfo(name, getter, setter, data, settings, attributes,
+                               signature);
+  if (info.is_null()) return Nothing<bool>();
+  bool fast = obj->HasFastProperties();
   i::Handle<i::Object> result;
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-      isolate, result,
-      i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
-      false);
-  if (result->IsUndefined()) return false;
+  has_pending_exception =
+      !i::JSObject::SetAccessor(obj, info).ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  if (result->IsUndefined()) return Nothing<bool>();
   if (fast) {
-    i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0, "APISetAccessor");
+    i::JSObject::MigrateSlowToFast(obj, 0, "APISetAccessor");
   }
-  return true;
+  return Just(true);
 }
 
 
-bool Object::SetAccessor(Handle<String> name,
-                         AccessorGetterCallback getter,
-                         AccessorSetterCallback setter,
-                         v8::Handle<Value> data,
-                         AccessControl settings,
-                         PropertyAttribute attributes) {
-  return ObjectSetAccessor(
-      this, name, getter, setter, data, settings, attributes);
+Maybe<bool> Object::SetAccessor(Local<Context> context, Local<Name> name,
+                                AccessorNameGetterCallback getter,
+                                AccessorNameSetterCallback setter,
+                                MaybeLocal<Value> data, AccessControl settings,
+                                PropertyAttribute attribute) {
+  return ObjectSetAccessor(context, this, name, getter, setter,
+                           data.FromMaybe(Local<Value>()), settings, attribute);
 }
 
 
-bool Object::SetAccessor(Handle<Name> name,
-                         AccessorNameGetterCallback getter,
+bool Object::SetAccessor(Local<String> name, AccessorGetterCallback getter,
+                         AccessorSetterCallback setter, v8::Local<Value> data,
+                         AccessControl settings, PropertyAttribute attributes) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return ObjectSetAccessor(context, this, name, getter, setter, data, settings,
+                           attributes).FromMaybe(false);
+}
+
+
+bool Object::SetAccessor(Local<Name> name, AccessorNameGetterCallback getter,
                          AccessorNameSetterCallback setter,
-                         v8::Handle<Value> data,
-                         AccessControl settings,
+                         v8::Local<Value> data, AccessControl settings,
                          PropertyAttribute attributes) {
-  return ObjectSetAccessor(
-      this, name, getter, setter, data, settings, attributes);
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return ObjectSetAccessor(context, this, name, getter, setter, data, settings,
+                           attributes).FromMaybe(false);
 }
 
 
-bool Object::SetDeclaredAccessor(Local<Name> name,
-                                 Local<DeclaredAccessorDescriptor> descriptor,
-                                 PropertyAttribute attributes,
-                                 AccessControl settings) {
-  void* null = NULL;
-  return ObjectSetAccessor(
-      this, name, descriptor, null, null, settings, attributes);
-}
-
-
-void Object::SetAccessorProperty(Local<Name> name,
-                                 Local<Function> getter,
-                                 Handle<Function> setter,
+void Object::SetAccessorProperty(Local<Name> name, Local<Function> getter,
+                                 Local<Function> setter,
                                  PropertyAttribute attribute,
                                  AccessControl settings) {
   // TODO(verwaest): Remove |settings|.
   DCHECK_EQ(v8::DEFAULT, settings);
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::SetAccessorProperty()", return);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return;
   i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
   i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
   if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
-  i::JSObject::DefineAccessor(v8::Utils::OpenHandle(this),
-                              v8::Utils::OpenHandle(*name),
-                              getter_i,
-                              setter_i,
-                              static_cast<PropertyAttributes>(attribute));
+  i::JSObject::DefineAccessor(i::Handle<i::JSObject>::cast(self),
+                              v8::Utils::OpenHandle(*name), getter_i, setter_i,
+                              static_cast<i::PropertyAttributes>(attribute));
 }
 
 
-bool v8::Object::HasOwnProperty(Handle<String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
-             return false);
-  EXCEPTION_PREAMBLE(isolate);
-  Maybe<bool> maybe = i::JSReceiver::HasOwnProperty(Utils::OpenHandle(this),
-                                                    Utils::OpenHandle(*key));
-  has_pending_exception = !maybe.has_value;
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return maybe.value;
+Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context,
+                                       Local<Name> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::HasOwnProperty()",
+                                  bool);
+  auto self = Utils::OpenHandle(this);
+  auto key_val = Utils::OpenHandle(*key);
+  auto result = i::JSReceiver::HasOwnProperty(self, key_val);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
 }
 
 
-bool v8::Object::HasRealNamedProperty(Handle<String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
-             return false);
-  EXCEPTION_PREAMBLE(isolate);
-  Maybe<bool> maybe = i::JSObject::HasRealNamedProperty(
-      Utils::OpenHandle(this), Utils::OpenHandle(*key));
-  has_pending_exception = !maybe.has_value;
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return maybe.value;
+bool v8::Object::HasOwnProperty(Local<String> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return HasOwnProperty(context, key).FromMaybe(false);
+}
+
+
+Maybe<bool> v8::Object::HasRealNamedProperty(Local<Context> context,
+                                             Local<Name> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::HasRealNamedProperty()",
+                                  bool);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return Just(false);
+  auto key_val = Utils::OpenHandle(*key);
+  auto result = i::JSObject::HasRealNamedProperty(
+      i::Handle<i::JSObject>::cast(self), key_val);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
+}
+
+
+bool v8::Object::HasRealNamedProperty(Local<String> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return HasRealNamedProperty(context, key).FromMaybe(false);
+}
+
+
+Maybe<bool> v8::Object::HasRealIndexedProperty(Local<Context> context,
+                                               uint32_t index) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context,
+                                  "v8::Object::HasRealIndexedProperty()", bool);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return Just(false);
+  auto result = i::JSObject::HasRealElementProperty(
+      i::Handle<i::JSObject>::cast(self), index);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
 }
 
 
 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()",
-             return false);
-  EXCEPTION_PREAMBLE(isolate);
-  Maybe<bool> maybe =
-      i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
-  has_pending_exception = !maybe.has_value;
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return maybe.value;
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return HasRealIndexedProperty(context, index).FromMaybe(false);
 }
 
 
-bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate,
-             "v8::Object::HasRealNamedCallbackProperty()",
-             return false);
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  Maybe<bool> maybe = i::JSObject::HasRealNamedCallbackProperty(
-      Utils::OpenHandle(this), Utils::OpenHandle(*key));
-  has_pending_exception = !maybe.has_value;
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return maybe.value;
+Maybe<bool> v8::Object::HasRealNamedCallbackProperty(Local<Context> context,
+                                                     Local<Name> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(
+      context, "v8::Object::HasRealNamedCallbackProperty()", bool);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return Just(false);
+  auto key_val = Utils::OpenHandle(*key);
+  auto result = i::JSObject::HasRealNamedCallbackProperty(
+      i::Handle<i::JSObject>::cast(self), key_val);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
+}
+
+
+bool v8::Object::HasRealNamedCallbackProperty(Local<String> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return HasRealNamedCallbackProperty(context, key).FromMaybe(false);
 }
 
 
 bool v8::Object::HasNamedLookupInterceptor() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
-             return false);
-  return Utils::OpenHandle(this)->HasNamedInterceptor();
+  auto self = Utils::OpenHandle(this);
+  return self->IsJSObject() &&
+         i::Handle<i::JSObject>::cast(self)->HasNamedInterceptor();
 }
 
 
 bool v8::Object::HasIndexedLookupInterceptor() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
-             return false);
-  return Utils::OpenHandle(this)->HasIndexedInterceptor();
+  auto self = Utils::OpenHandle(this);
+  return self->IsJSObject() &&
+         i::Handle<i::JSObject>::cast(self)->HasIndexedInterceptor();
 }
 
 
-static Local<Value> GetPropertyByLookup(i::LookupIterator* it) {
-  // If the property being looked up is a callback, it can throw an exception.
-  EXCEPTION_PREAMBLE(it->isolate());
-  i::Handle<i::Object> result;
-  has_pending_exception = !i::Object::GetProperty(it).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(it->isolate(), Local<Value>());
-
-  if (it->IsFound()) return Utils::ToLocal(result);
-  return Local<Value>();
+MaybeLocal<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
+    Local<Context> context, Local<Name> key) {
+  PREPARE_FOR_EXECUTION(
+      context, "v8::Object::GetRealNamedPropertyInPrototypeChain()", Value);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return MaybeLocal<Value>();
+  i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
+  i::PrototypeIterator iter(isolate, self);
+  if (iter.IsAtEnd()) return MaybeLocal<Value>();
+  i::Handle<i::JSReceiver> proto =
+      i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter);
+  i::LookupIterator it = i::LookupIterator::PropertyOrElement(
+      isolate, self, key_obj, proto,
+      i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  if (!it.IsFound()) return MaybeLocal<Value>();
+  RETURN_ESCAPED(result);
 }
 
 
 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
-    Handle<String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate,
-             "v8::Object::GetRealNamedPropertyInPrototypeChain()",
-             return Local<Value>());
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
-  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
-  i::PrototypeIterator iter(isolate, self_obj);
-  if (iter.IsAtEnd()) return Local<Value>();
-  i::Handle<i::Object> proto = i::PrototypeIterator::GetCurrent(iter);
-  i::LookupIterator it(self_obj, key_obj, i::Handle<i::JSReceiver>::cast(proto),
-                       i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
-  return GetPropertyByLookup(&it);
+    Local<String> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(GetRealNamedPropertyInPrototypeChain(context, key),
+                            Value);
 }
 
 
-Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
-             return Local<Value>());
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
-  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
-  i::LookupIterator it(self_obj, key_obj,
-                       i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
-  return GetPropertyByLookup(&it);
+Maybe<PropertyAttribute>
+v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(
+    Local<Context> context, Local<Name> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(
+      context, "v8::Object::GetRealNamedPropertyAttributesInPrototypeChain()",
+      PropertyAttribute);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return Nothing<PropertyAttribute>();
+  i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
+  i::PrototypeIterator iter(isolate, self);
+  if (iter.IsAtEnd()) return Nothing<PropertyAttribute>();
+  i::Handle<i::JSReceiver> proto =
+      i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter);
+  i::LookupIterator it = i::LookupIterator::PropertyOrElement(
+      isolate, self, key_obj, proto,
+      i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
+  Maybe<i::PropertyAttributes> result =
+      i::JSReceiver::GetPropertyAttributes(&it);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
+  if (!it.IsFound()) return Nothing<PropertyAttribute>();
+  if (result.FromJust() == i::ABSENT) return Just(None);
+  return Just(static_cast<PropertyAttribute>(result.FromJust()));
 }
 
 
-// Turns on access checks by copying the map and setting the check flag.
-// Because the object gets a new map, existing inline cache caching
-// the old map of this object will fail.
-void v8::Object::TurnOnAccessCheck() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+Maybe<PropertyAttribute>
+v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(Local<String> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return GetRealNamedPropertyAttributesInPrototypeChain(context, key);
+}
 
-  // When turning on access checks for a global object deoptimize all functions
-  // as optimized code does not always handle access checks.
-  i::Deoptimizer::DeoptimizeGlobalObject(*obj);
 
-  i::Handle<i::Map> new_map =
-      i::Map::Copy(i::Handle<i::Map>(obj->map()), "APITurnOnAccessCheck");
-  new_map->set_is_access_check_needed(true);
-  i::JSObject::MigrateToMap(obj, new_map);
+MaybeLocal<Value> v8::Object::GetRealNamedProperty(Local<Context> context,
+                                                   Local<Name> key) {
+  PREPARE_FOR_EXECUTION(context, "v8::Object::GetRealNamedProperty()", Value);
+  auto self = Utils::OpenHandle(this);
+  auto key_obj = Utils::OpenHandle(*key);
+  i::LookupIterator it = i::LookupIterator::PropertyOrElement(
+      isolate, self, key_obj,
+      i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  if (!it.IsFound()) return MaybeLocal<Value>();
+  RETURN_ESCAPED(result);
+}
+
+
+Local<Value> v8::Object::GetRealNamedProperty(Local<String> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(GetRealNamedProperty(context, key), Value);
+}
+
+
+Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes(
+    Local<Context> context, Local<Name> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(
+      context, "v8::Object::GetRealNamedPropertyAttributes()",
+      PropertyAttribute);
+  auto self = Utils::OpenHandle(this);
+  auto key_obj = Utils::OpenHandle(*key);
+  i::LookupIterator it = i::LookupIterator::PropertyOrElement(
+      isolate, self, key_obj,
+      i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
+  auto result = i::JSReceiver::GetPropertyAttributes(&it);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
+  if (!it.IsFound()) return Nothing<PropertyAttribute>();
+  if (result.FromJust() == i::ABSENT) {
+    return Just(static_cast<PropertyAttribute>(i::NONE));
+  }
+  return Just<PropertyAttribute>(
+      static_cast<PropertyAttribute>(result.FromJust()));
+}
+
+
+Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes(
+    Local<String> key) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  return GetRealNamedPropertyAttributes(context, key);
 }
 
 
 Local<v8::Object> v8::Object::Clone() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
+  auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+  auto isolate = self->GetIsolate();
   ENTER_V8(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self);
-  has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
+  auto result = isolate->factory()->CopyJSObject(self);
+  CHECK(!result.is_null());
   return Utils::ToLocal(result);
 }
 
 
 Local<v8::Context> v8::Object::CreationContext() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate,
-             "v8::Object::CreationContext()", return Local<v8::Context>());
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  i::Context* context = self->GetCreationContext();
-  return Utils::ToLocal(i::Handle<i::Context>(context));
+  auto self = Utils::OpenHandle(this);
+  auto context = handle(self->GetCreationContext());
+  return Utils::ToLocal(context);
 }
 
 
 int v8::Object::GetIdentityHash() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
-  ENTER_V8(isolate);
+  auto isolate = Utils::OpenHandle(this)->GetIsolate();
   i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  auto self = Utils::OpenHandle(this);
   return i::JSReceiver::GetOrCreateIdentityHash(self)->value();
 }
 
 
-bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
-                                v8::Handle<v8::Value> value) {
+bool v8::Object::SetHiddenValue(v8::Local<v8::String> key,
+                                v8::Local<v8::Value> value) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
-  if (value.IsEmpty()) return DeleteHiddenValue(key);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return false;
   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::String> key_string =
       isolate->factory()->InternalizeString(key_obj);
+  if (value.IsEmpty()) {
+    i::JSObject::DeleteHiddenProperty(i::Handle<i::JSObject>::cast(self),
+                                      key_string);
+    return true;
+  }
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  i::Handle<i::Object> result =
-      i::JSObject::SetHiddenProperty(self, key_string, value_obj);
+  i::Handle<i::Object> result = i::JSObject::SetHiddenProperty(
+      i::Handle<i::JSObject>::cast(self), key_string, value_obj);
   return *result == *self;
 }
 
 
-v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
+v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Local<v8::String> key) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
-             return Local<v8::Value>());
   ENTER_V8(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return v8::Local<v8::Value>();
   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::String> key_string =
       isolate->factory()->InternalizeString(key_obj);
-  i::Handle<i::Object> result(self->GetHiddenProperty(key_string), isolate);
+  i::Handle<i::Object> result(
+      i::Handle<i::JSObject>::cast(self)->GetHiddenProperty(key_string),
+      isolate);
   if (result->IsTheHole()) return v8::Local<v8::Value>();
   return Utils::ToLocal(result);
 }
 
 
-bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
+bool v8::Object::DeleteHiddenValue(v8::Local<v8::String> key) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return false;
   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::String> key_string =
       isolate->factory()->InternalizeString(key_obj);
-  i::JSObject::DeleteHiddenProperty(self, key_string);
+  i::JSObject::DeleteHiddenProperty(i::Handle<i::JSObject>::cast(self),
+                                    key_string);
   return true;
 }
 
 
-namespace {
-
-static i::ElementsKind GetElementsKindFromExternalArrayType(
-    ExternalArrayType array_type) {
-  switch (array_type) {
-#define ARRAY_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size)            \
-    case kExternal##Type##Array:                                              \
-      return i::EXTERNAL_##TYPE##_ELEMENTS;
-
-    TYPED_ARRAYS(ARRAY_TYPE_TO_ELEMENTS_KIND)
-#undef ARRAY_TYPE_TO_ELEMENTS_KIND
-  }
-  UNREACHABLE();
-  return i::DICTIONARY_ELEMENTS;
-}
-
-
-void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
-                                  void* data,
-                                  ExternalArrayType array_type,
-                                  int length) {
-  i::Isolate* isolate = object->GetIsolate();
-  i::Handle<i::ExternalArray> array =
-      isolate->factory()->NewExternalArray(length, array_type, data);
-
-  i::Handle<i::Map> external_array_map =
-      i::JSObject::GetElementsTransitionMap(
-          object,
-          GetElementsKindFromExternalArrayType(array_type));
-
-  i::JSObject::SetMapAndElements(object, external_array_map, array);
-}
-
-}  // namespace
-
-
-void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  if (!Utils::ApiCheck(length >= 0 &&
-                       length <= i::ExternalUint8ClampedArray::kMaxLength,
-                       "v8::Object::SetIndexedPropertiesToPixelData()",
-                       "length exceeds max acceptable value")) {
-    return;
-  }
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  if (!Utils::ApiCheck(!self->IsJSArray(),
-                       "v8::Object::SetIndexedPropertiesToPixelData()",
-                       "JSArray is not supported")) {
-    return;
-  }
-  PrepareExternalArrayElements(self, data, kExternalUint8ClampedArray, length);
-}
-
-
-bool v8::Object::HasIndexedPropertiesInPixelData() {
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
-             return false);
-  return self->HasExternalUint8ClampedElements();
-}
-
-
-uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
-             return NULL);
-  if (self->HasExternalUint8ClampedElements()) {
-    return i::ExternalUint8ClampedArray::cast(self->elements())->
-        external_uint8_clamped_pointer();
-  } else {
-    return NULL;
-  }
-}
-
-
-int v8::Object::GetIndexedPropertiesPixelDataLength() {
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
-             return -1);
-  if (self->HasExternalUint8ClampedElements()) {
-    return i::ExternalUint8ClampedArray::cast(self->elements())->length();
-  } else {
-    return -1;
-  }
-}
-
-
-void v8::Object::SetIndexedPropertiesToExternalArrayData(
-    void* data,
-    ExternalArrayType array_type,
-    int length) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  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 (!Utils::ApiCheck(!self->IsJSArray(),
-                       "v8::Object::SetIndexedPropertiesToExternalArrayData()",
-                       "JSArray is not supported")) {
-    return;
-  }
-  PrepareExternalArrayElements(self, data, array_type, length);
-}
-
-
-bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  ON_BAILOUT(self->GetIsolate(),
-             "v8::HasIndexedPropertiesInExternalArrayData()",
-             return false);
-  return self->HasExternalArrayElements();
-}
-
-
-void* v8::Object::GetIndexedPropertiesExternalArrayData() {
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  ON_BAILOUT(self->GetIsolate(),
-             "v8::GetIndexedPropertiesExternalArrayData()",
-             return NULL);
-  if (self->HasExternalArrayElements()) {
-    return i::ExternalArray::cast(self->elements())->external_pointer();
-  } else {
-    return NULL;
-  }
-}
-
-
-ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  ON_BAILOUT(self->GetIsolate(),
-             "v8::GetIndexedPropertiesExternalArrayDataType()",
-             return static_cast<ExternalArrayType>(-1));
-  switch (self->elements()->map()->instance_type()) {
-#define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
-    case i::EXTERNAL_##TYPE##_ARRAY_TYPE:                                     \
-      return kExternal##Type##Array;
-    TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
-#undef INSTANCE_TYPE_TO_ARRAY_TYPE
-    default:
-      return static_cast<ExternalArrayType>(-1);
-  }
-}
-
-
-int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  ON_BAILOUT(self->GetIsolate(),
-             "v8::GetIndexedPropertiesExternalArrayDataLength()",
-             return 0);
-  if (self->HasExternalArrayElements()) {
-    return i::ExternalArray::cast(self->elements())->length();
-  } else {
-    return -1;
-  }
-}
-
-
 bool v8::Object::IsCallable() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  return obj->IsCallable();
+  auto self = Utils::OpenHandle(this);
+  return self->IsCallable();
 }
 
 
-Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv,
-                                        int argc,
-                                        v8::Handle<v8::Value> argv[]) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::CallAsFunction()",
-             return Local<v8::Value>());
-  LOG_API(isolate, "Object::CallAsFunction");
-  ENTER_V8(isolate);
+MaybeLocal<Value> Object::CallAsFunction(Local<Context> context,
+                                         Local<Value> recv, int argc,
+                                         Local<Value> argv[]) {
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Object::CallAsFunction()",
+                                      Value);
   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
-  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
+  auto self = Utils::OpenHandle(this);
+  auto recv_obj = Utils::OpenHandle(*recv);
+  STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**));
   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
-  i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>();
-  if (obj->IsJSFunction()) {
-    fun = i::Handle<i::JSFunction>::cast(obj);
-  } else {
-    EXCEPTION_PREAMBLE(isolate);
-    i::Handle<i::Object> delegate;
-    has_pending_exception = !i::Execution::TryGetFunctionDelegate(
-        isolate, obj).ToHandle(&delegate);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
-    fun = i::Handle<i::JSFunction>::cast(delegate);
-    recv_obj = obj;
-  }
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> returned;
-  has_pending_exception = !i::Execution::Call(
-      isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
-  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
-  return Utils::ToLocal(scope.CloseAndEscape(returned));
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(
+      i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<v8::Value> Object::CallAsFunction(v8::Local<v8::Value> recv, int argc,
+                                        v8::Local<v8::Value> argv[]) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  Local<Value>* argv_cast = reinterpret_cast<Local<Value>*>(argv);
+  RETURN_TO_LOCAL_UNCHECKED(CallAsFunction(context, recv, argc, argv_cast),
+                            Value);
+}
+
+
+MaybeLocal<Value> Object::CallAsConstructor(Local<Context> context, int argc,
+                                            Local<Value> argv[]) {
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context,
+                                      "v8::Object::CallAsConstructor()", Value);
+  i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
+  auto self = Utils::OpenHandle(this);
+  STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**));
+  i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(
+      i::Execution::New(isolate, self, self, argc, args), &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
 }
 
 
 Local<v8::Value> Object::CallAsConstructor(int argc,
-                                           v8::Handle<v8::Value> argv[]) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()",
-             return Local<v8::Object>());
-  LOG_API(isolate, "Object::CallAsConstructor");
-  ENTER_V8(isolate);
-  i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
-  i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
-  if (obj->IsJSFunction()) {
-    i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
-    EXCEPTION_PREAMBLE(isolate);
-    i::Handle<i::Object> returned;
-    has_pending_exception = !i::Execution::New(
-        fun, argc, args).ToHandle(&returned);
-    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
-    return Utils::ToLocal(scope.CloseAndEscape(
-        i::Handle<i::JSObject>::cast(returned)));
-  }
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> delegate;
-  has_pending_exception = !i::Execution::TryGetConstructorDelegate(
-      isolate, obj).ToHandle(&delegate);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
-  if (!delegate->IsUndefined()) {
-    i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
-    EXCEPTION_PREAMBLE(isolate);
-    i::Handle<i::Object> returned;
-    has_pending_exception = !i::Execution::Call(
-        isolate, fun, obj, argc, args).ToHandle(&returned);
-    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
-    DCHECK(!delegate->IsUndefined());
-    return Utils::ToLocal(scope.CloseAndEscape(returned));
-  }
-  return Local<v8::Object>();
+                                           v8::Local<v8::Value> argv[]) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  Local<Value>* argv_cast = reinterpret_cast<Local<Value>*>(argv);
+  RETURN_TO_LOCAL_UNCHECKED(CallAsConstructor(context, argc, argv_cast), Value);
 }
 
 
-Local<Function> Function::New(Isolate* v8_isolate,
-                              FunctionCallback callback,
-                              Local<Value> data,
-                              int length) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+MaybeLocal<Function> Function::New(Local<Context> context,
+                                   FunctionCallback callback, Local<Value> data,
+                                   int length) {
+  i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate();
   LOG_API(isolate, "Function::New");
   ENTER_V8(isolate);
-  return FunctionTemplateNew(
-      isolate, callback, data, Local<Signature>(), length, true)->
-      GetFunction();
+  return FunctionTemplateNew(isolate, callback, nullptr, data,
+                             Local<Signature>(), length, true)
+      ->GetFunction(context);
+}
+
+
+Local<Function> Function::New(Isolate* v8_isolate, FunctionCallback callback,
+                              Local<Value> data, int length) {
+  return Function::New(v8_isolate->GetCurrentContext(), callback, data, length)
+      .FromMaybe(Local<Function>());
 }
 
 
 Local<v8::Object> Function::NewInstance() const {
-  return NewInstance(0, NULL);
+  return NewInstance(Isolate::GetCurrent()->GetCurrentContext(), 0, NULL)
+      .FromMaybe(Local<Object>());
+}
+
+
+MaybeLocal<Object> Function::NewInstance(Local<Context> context, int argc,
+                                         v8::Local<v8::Value> argv[]) const {
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Function::NewInstance()",
+                                      Object);
+  i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
+  auto self = Utils::OpenHandle(this);
+  STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**));
+  i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
+  Local<Object> result;
+  has_pending_exception = !ToLocal<Object>(
+      i::Execution::New(isolate, self, self, argc, args), &result);
+  RETURN_ON_FAILED_EXECUTION(Object);
+  RETURN_ESCAPED(result);
 }
 
 
 Local<v8::Object> Function::NewInstance(int argc,
-                                        v8::Handle<v8::Value> argv[]) const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Function::NewInstance()",
-             return Local<v8::Object>());
-  LOG_API(isolate, "Function::NewInstance");
-  ENTER_V8(isolate);
-  i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
-  EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
-  i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
-  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
-  i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> returned;
-  has_pending_exception = !i::Execution::New(
-      function, argc, args).ToHandle(&returned);
-  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
-  return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
+                                        v8::Local<v8::Value> argv[]) const {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(NewInstance(context, argc, argv), Object);
 }
 
 
-Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc,
-                                v8::Handle<v8::Value> argv[]) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
-  LOG_API(isolate, "Function::Call");
-  ENTER_V8(isolate);
+MaybeLocal<v8::Value> Function::Call(Local<Context> context,
+                                     v8::Local<v8::Value> recv, int argc,
+                                     v8::Local<v8::Value> argv[]) {
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Function::Call()", Value);
   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+  auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
-  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
+  STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**));
   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> returned;
-  has_pending_exception = !i::Execution::Call(
-      isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
-  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
-  return Utils::ToLocal(scope.CloseAndEscape(returned));
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(
+      i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
 }
 
 
-void Function::SetName(v8::Handle<v8::String> name) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
-  USE(isolate);
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+Local<v8::Value> Function::Call(v8::Local<v8::Value> recv, int argc,
+                                v8::Local<v8::Value> argv[]) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(Call(context, recv, argc, argv), Value);
+}
+
+
+void Function::SetName(v8::Local<v8::String> name) {
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) return;
+  auto func = i::Handle<i::JSFunction>::cast(self);
   func->shared()->set_name(*Utils::OpenHandle(*name));
 }
 
 
-Handle<Value> Function::GetName() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
-  return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(),
-                                             func->GetIsolate()));
+Local<Value> Function::GetName() const {
+  auto self = Utils::OpenHandle(this);
+  if (self->IsJSBoundFunction()) {
+    auto func = i::Handle<i::JSBoundFunction>::cast(self);
+    return Utils::ToLocal(handle(func->name(), func->GetIsolate()));
+  }
+  if (self->IsJSFunction()) {
+    auto func = i::Handle<i::JSFunction>::cast(self);
+    return Utils::ToLocal(handle(func->shared()->name(), func->GetIsolate()));
+  }
+  return ToApiHandle<Primitive>(
+      self->GetIsolate()->factory()->undefined_value());
 }
 
 
-Handle<Value> Function::GetInferredName() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+Local<Value> Function::GetInferredName() const {
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return ToApiHandle<Primitive>(
+        self->GetIsolate()->factory()->undefined_value());
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(),
                                              func->GetIsolate()));
 }
 
 
-Handle<Value> Function::GetDisplayName() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
-             return ToApiHandle<Primitive>(
-                 isolate->factory()->undefined_value()));
-  ENTER_V8(isolate);
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
-  i::Handle<i::String> property_name =
-      isolate->factory()->InternalizeOneByteString(
-          STATIC_CHAR_VECTOR("displayName"));
+Local<Value> Function::GetDebugName() const {
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return ToApiHandle<Primitive>(
+        self->GetIsolate()->factory()->undefined_value());
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
+  i::Handle<i::String> name = i::JSFunction::GetDebugName(func);
+  return Utils::ToLocal(i::Handle<i::Object>(*name, name->GetIsolate()));
+}
 
+
+Local<Value> Function::GetDisplayName() const {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ENTER_V8(isolate);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
+  i::Handle<i::String> property_name =
+      isolate->factory()->NewStringFromStaticChars("displayName");
   i::Handle<i::Object> value =
-      i::JSObject::GetDataProperty(func, property_name);
+      i::JSReceiver::GetDataProperty(func, property_name);
   if (value->IsString()) {
     i::Handle<i::String> name = i::Handle<i::String>::cast(value);
     if (name->length() > 0) return Utils::ToLocal(name);
   }
-
   return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
 }
 
 
 ScriptOrigin Function::GetScriptOrigin() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return v8::ScriptOrigin(Local<Value>());
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
   if (func->shared()->script()->IsScript()) {
     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
-    i::Handle<i::Object> scriptName = i::Script::GetNameOrSourceURL(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()));
-    return origin;
+    return GetScriptOriginForScript(func->GetIsolate(), script);
   }
-  return v8::ScriptOrigin(Handle<Value>());
+  return v8::ScriptOrigin(Local<Value>());
 }
 
 
@@ -4251,7 +4483,11 @@
 
 
 int Function::GetScriptLineNumber() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return kLineOffsetNotFound;
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
   if (func->shared()->script()->IsScript()) {
     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
     return i::Script::GetLineNumber(script, func->shared()->start_position());
@@ -4261,7 +4497,11 @@
 
 
 int Function::GetScriptColumnNumber() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return kLineOffsetNotFound;
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
   if (func->shared()->script()->IsScript()) {
     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
     return i::Script::GetColumnNumber(script, func->shared()->start_position());
@@ -4271,41 +4511,43 @@
 
 
 bool Function::IsBuiltin() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
-  return func->IsBuiltin();
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return false;
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
+  return func->shared()->IsBuiltin();
 }
 
 
 int Function::ScriptId() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+  auto self = Utils::OpenHandle(this);
+  if (!self->IsJSFunction()) {
+    return v8::UnboundScript::kNoScriptId;
+  }
+  auto func = i::Handle<i::JSFunction>::cast(self);
   if (!func->shared()->script()->IsScript()) {
     return v8::UnboundScript::kNoScriptId;
   }
   i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
-  return script->id()->value();
+  return script->id();
 }
 
 
 Local<v8::Value> Function::GetBoundFunction() const {
-  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
-  if (!func->shared()->bound()) {
-    return v8::Undefined(reinterpret_cast<v8::Isolate*>(func->GetIsolate()));
+  auto self = Utils::OpenHandle(this);
+  if (self->IsJSBoundFunction()) {
+    auto bound_function = i::Handle<i::JSBoundFunction>::cast(self);
+    auto bound_target_function = i::handle(
+        bound_function->bound_target_function(), bound_function->GetIsolate());
+    return Utils::CallableToLocal(bound_target_function);
   }
-  i::Handle<i::FixedArray> bound_args = i::Handle<i::FixedArray>(
-      i::FixedArray::cast(func->function_bindings()));
-  i::Handle<i::Object> original(
-      bound_args->get(i::JSFunction::kBoundFunctionIndex),
-      func->GetIsolate());
-  return Utils::ToLocal(i::Handle<i::JSFunction>::cast(original));
+  return v8::Undefined(reinterpret_cast<v8::Isolate*>(self->GetIsolate()));
 }
 
 
 int Name::GetIdentityHash() {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Name::GetIdentityHash()", return 0);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::Name> self = Utils::OpenHandle(this);
+  auto self = Utils::OpenHandle(this);
   return static_cast<int>(self->Hash());
 }
 
@@ -4560,7 +4802,7 @@
   }
 
   static int Calculate(i::ConsString* current, uint8_t* state_out) {
-    using namespace internal;
+    using internal::ConsString;
     int total_length = 0;
     uint8_t state = kInitialState;
     while (true) {
@@ -4660,26 +4902,22 @@
                                int remaining,
                                char* const buffer,
                                bool replace_invalid_utf8) {
-    using namespace unibrow;
-    DCHECK(remaining > 0);
+    DCHECK_GT(remaining, 0);
     // We can't use a local buffer here because Encode needs to modify
     // previous characters in the stream.  We know, however, that
     // exactly one character will be advanced.
-    if (Utf16::IsSurrogatePair(last_character, character)) {
-      int written = Utf8::Encode(buffer,
-                                 character,
-                                 last_character,
-                                 replace_invalid_utf8);
-      DCHECK(written == 1);
+    if (unibrow::Utf16::IsSurrogatePair(last_character, character)) {
+      int written = unibrow::Utf8::Encode(buffer, character, last_character,
+                                          replace_invalid_utf8);
+      DCHECK_EQ(written, 1);
       return written;
     }
     // Use a scratch buffer to check the required characters.
-    char temp_buffer[Utf8::kMaxEncodedSize];
+    char temp_buffer[unibrow::Utf8::kMaxEncodedSize];
     // Can't encode using last_character as gcc has array bounds issues.
-    int written = Utf8::Encode(temp_buffer,
-                               character,
-                               Utf16::kNoPreviousCharacter,
-                               replace_invalid_utf8);
+    int written = unibrow::Utf8::Encode(temp_buffer, character,
+                                        unibrow::Utf16::kNoPreviousCharacter,
+                                        replace_invalid_utf8);
     // Won't fit.
     if (written > remaining) return 0;
     // Copy over the character from temp_buffer.
@@ -4701,13 +4939,13 @@
   // unit, or all units have been written out.
   template<typename Char>
   void Visit(const Char* chars, const int length) {
-    using namespace unibrow;
     DCHECK(!early_termination_);
     if (length == 0) return;
     // Copy state to stack.
     char* buffer = buffer_;
-    int last_character =
-        sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_;
+    int last_character = sizeof(Char) == 1
+                             ? unibrow::Utf16::kNoPreviousCharacter
+                             : last_character_;
     int i = 0;
     // Do a fast loop where there is no exit capacity check.
     while (true) {
@@ -4717,7 +4955,8 @@
       } else {
         int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
         // Need enough space to write everything but one character.
-        STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
+        STATIC_ASSERT(unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit ==
+                      3);
         int max_size_per_char =  sizeof(Char) == 1 ? 2 : 3;
         int writable_length =
             (remaining_capacity - max_size_per_char)/max_size_per_char;
@@ -4729,17 +4968,15 @@
       // Write the characters to the stream.
       if (sizeof(Char) == 1) {
         for (; i < fast_length; i++) {
-          buffer +=
-              Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++));
+          buffer += unibrow::Utf8::EncodeOneByte(
+              buffer, static_cast<uint8_t>(*chars++));
           DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
         }
       } else {
         for (; i < fast_length; i++) {
           uint16_t character = *chars++;
-          buffer += Utf8::Encode(buffer,
-                                 character,
-                                 last_character,
-                                 replace_invalid_utf8_);
+          buffer += unibrow::Utf8::Encode(buffer, character, last_character,
+                                          replace_invalid_utf8_);
           last_character = character;
           DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
         }
@@ -4756,12 +4993,12 @@
     DCHECK(!skip_capacity_check_);
     // Slow loop. Must check capacity on each iteration.
     int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
-    DCHECK(remaining_capacity >= 0);
+    DCHECK_GE(remaining_capacity, 0);
     for (; i < length && remaining_capacity > 0; i++) {
       uint16_t character = *chars++;
       // remaining_capacity is <= 3 bytes at this point, so we do not write out
       // an umatched lead surrogate.
-      if (replace_invalid_utf8_ && Utf16::IsLeadSurrogate(character)) {
+      if (replace_invalid_utf8_ && unibrow::Utf16::IsLeadSurrogate(character)) {
         early_termination_ = true;
         break;
       }
@@ -4905,7 +5142,6 @@
   ENTER_V8(isolate);
   DCHECK(start >= 0 && length >= -1);
   i::Handle<i::String> str = Utils::OpenHandle(string);
-  isolate->string_tracker()->RecordWrite(str);
   if (options & String::HINT_MANY_WRITES_EXPECTED) {
     // Flatten the string for efficiency.  This applies whether we are
     // using StringCharacterStream or Get(i) to access the characters.
@@ -5058,52 +5294,56 @@
 
 
 int v8::Object::InternalFieldCount() {
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  return obj->GetInternalFieldCount();
+  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
+  if (!self->IsJSObject()) return 0;
+  return i::Handle<i::JSObject>::cast(self)->GetInternalFieldCount();
 }
 
 
-static bool InternalFieldOK(i::Handle<i::JSObject> obj,
-                            int index,
+static bool InternalFieldOK(i::Handle<i::JSReceiver> obj, int index,
                             const char* location) {
-  return Utils::ApiCheck(index < obj->GetInternalFieldCount(),
-                         location,
-                         "Internal field out of bounds");
+  return Utils::ApiCheck(
+      obj->IsJSObject() &&
+          (index < i::Handle<i::JSObject>::cast(obj)->GetInternalFieldCount()),
+      location, "Internal field out of bounds");
 }
 
 
 Local<Value> v8::Object::SlowGetInternalField(int index) {
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
   const char* location = "v8::Object::GetInternalField()";
   if (!InternalFieldOK(obj, index, location)) return Local<Value>();
-  i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate());
+  i::Handle<i::Object> value(
+      i::Handle<i::JSObject>::cast(obj)->GetInternalField(index),
+      obj->GetIsolate());
   return Utils::ToLocal(value);
 }
 
 
-void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+void v8::Object::SetInternalField(int index, v8::Local<Value> value) {
+  i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
   const char* location = "v8::Object::SetInternalField()";
   if (!InternalFieldOK(obj, index, location)) return;
   i::Handle<i::Object> val = Utils::OpenHandle(*value);
-  obj->SetInternalField(index, *val);
-  DCHECK_EQ(value, GetInternalField(index));
+  i::Handle<i::JSObject>::cast(obj)->SetInternalField(index, *val);
 }
 
 
 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
   const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
   if (!InternalFieldOK(obj, index, location)) return NULL;
-  return DecodeSmiToAligned(obj->GetInternalField(index), location);
+  return DecodeSmiToAligned(
+      i::Handle<i::JSObject>::cast(obj)->GetInternalField(index), location);
 }
 
 
 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
   const char* location = "v8::Object::SetAlignedPointerInInternalField()";
   if (!InternalFieldOK(obj, index, location)) return;
-  obj->SetInternalField(index, EncodeAlignedAsSmi(value, location));
+  i::Handle<i::JSObject>::cast(obj)
+      ->SetInternalField(index, EncodeAlignedAsSmi(value, location));
   DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
 }
 
@@ -5128,12 +5368,12 @@
   i::V8::ShutdownPlatform();
 }
 
-v8::Platform* v8::V8::GetCurrentPlatform() {
-  return i::V8::GetCurrentPlatform();
-}
 
 bool v8::V8::Initialize() {
   i::V8::Initialize();
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+  i::ReadNatives();
+#endif
   return true;
 }
 
@@ -5145,21 +5385,15 @@
 
 void v8::V8::SetReturnAddressLocationResolver(
     ReturnAddressLocationResolver return_address_resolver) {
-  i::V8::SetReturnAddressLocationResolver(return_address_resolver);
-}
-
-void v8::V8::SetArrayBufferAllocator(
-    ArrayBuffer::Allocator* allocator) {
-  if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
-                       "v8::V8::SetArrayBufferAllocator",
-                       "ArrayBufferAllocator might only be set once"))
-    return;
-  i::V8::SetArrayBufferAllocator(allocator);
+  i::StackFrame::SetReturnAddressLocationResolver(return_address_resolver);
 }
 
 
 bool v8::V8::Dispose() {
   i::V8::TearDown();
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+  i::DisposeNatives();
+#endif
   return true;
 }
 
@@ -5171,27 +5405,51 @@
                                   heap_size_limit_(0) { }
 
 
+HeapSpaceStatistics::HeapSpaceStatistics(): space_name_(0),
+                                            space_size_(0),
+                                            space_used_size_(0),
+                                            space_available_size_(0),
+                                            physical_space_size_(0) { }
+
+
+HeapObjectStatistics::HeapObjectStatistics()
+    : object_type_(nullptr),
+      object_sub_type_(nullptr),
+      object_count_(0),
+      object_size_(0) {}
+
+
 bool v8::V8::InitializeICU(const char* icu_data_file) {
   return i::InitializeICU(icu_data_file);
 }
 
 
+void v8::V8::InitializeExternalStartupData(const char* directory_path) {
+  i::InitializeExternalStartupData(directory_path);
+}
+
+
+void v8::V8::InitializeExternalStartupData(const char* natives_blob,
+                                           const char* snapshot_blob) {
+  i::InitializeExternalStartupData(natives_blob, snapshot_blob);
+}
+
+
 const char* v8::V8::GetVersion() {
   return i::Version::GetVersion();
 }
 
 
 static i::Handle<i::Context> CreateEnvironment(
-    i::Isolate* isolate,
-    v8::ExtensionConfiguration* extensions,
-    v8::Handle<ObjectTemplate> global_template,
-    v8::Handle<Value> maybe_global_proxy) {
+    i::Isolate* isolate, v8::ExtensionConfiguration* extensions,
+    v8::Local<ObjectTemplate> global_template,
+    v8::Local<Value> maybe_global_proxy) {
   i::Handle<i::Context> env;
 
   // Enter V8 via an ENTER_V8 scope.
   {
     ENTER_V8(isolate);
-    v8::Handle<ObjectTemplate> proxy_template = global_template;
+    v8::Local<ObjectTemplate> proxy_template = global_template;
     i::Handle<i::FunctionTemplateInfo> proxy_constructor;
     i::Handle<i::FunctionTemplateInfo> global_constructor;
 
@@ -5247,28 +5505,29 @@
   return env;
 }
 
-Local<Context> v8::Context::New(
-    v8::Isolate* external_isolate,
-    v8::ExtensionConfiguration* extensions,
-    v8::Handle<ObjectTemplate> global_template,
-    v8::Handle<Value> global_object) {
+Local<Context> v8::Context::New(v8::Isolate* external_isolate,
+                                v8::ExtensionConfiguration* extensions,
+                                v8::Local<ObjectTemplate> global_template,
+                                v8::Local<Value> global_object) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
   LOG_API(isolate, "Context::New");
-  ON_BAILOUT(isolate, "v8::Context::New()", return Local<Context>());
   i::HandleScope scope(isolate);
   ExtensionConfiguration no_extensions;
   if (extensions == NULL) extensions = &no_extensions;
   i::Handle<i::Context> env =
       CreateEnvironment(isolate, extensions, global_template, global_object);
-  if (env.is_null()) return Local<Context>();
+  if (env.is_null()) {
+    if (isolate->has_pending_exception()) {
+      isolate->OptionalRescheduleException(true);
+    }
+    return Local<Context>();
+  }
   return Utils::ToLocal(scope.CloseAndEscape(env));
 }
 
 
-void v8::Context::SetSecurityToken(Handle<Value> token) {
+void v8::Context::SetSecurityToken(Local<Value> token) {
   i::Handle<i::Context> env = Utils::OpenHandle(this);
-  i::Isolate* isolate = env->GetIsolate();
-  ENTER_V8(isolate);
   i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
   env->set_security_token(*token_handle);
 }
@@ -5276,13 +5535,11 @@
 
 void v8::Context::UseDefaultSecurityToken() {
   i::Handle<i::Context> env = Utils::OpenHandle(this);
-  i::Isolate* isolate = env->GetIsolate();
-  ENTER_V8(isolate);
   env->set_security_token(env->global_object());
 }
 
 
-Handle<Value> v8::Context::GetSecurityToken() {
+Local<Value> v8::Context::GetSecurityToken() {
   i::Handle<i::Context> env = Utils::OpenHandle(this);
   i::Isolate* isolate = env->GetIsolate();
   i::Object* security_token = env->security_token();
@@ -5319,6 +5576,14 @@
 }
 
 
+Local<v8::Object> Context::GetExtrasBindingObject() {
+  i::Handle<i::Context> context = Utils::OpenHandle(this);
+  i::Isolate* isolate = context->GetIsolate();
+  i::Handle<i::JSObject> binding(context->extras_binding_object(), isolate);
+  return Utils::ToLocal(binding);
+}
+
+
 void Context::AllowCodeGenerationFromStrings(bool allow) {
   i::Handle<i::Context> context = Utils::OpenHandle(this);
   i::Isolate* isolate = context->GetIsolate();
@@ -5334,51 +5599,58 @@
 }
 
 
-void Context::SetErrorMessageForCodeGenerationFromStrings(
-    Handle<String> error) {
+void Context::SetErrorMessageForCodeGenerationFromStrings(Local<String> error) {
   i::Handle<i::Context> context = Utils::OpenHandle(this);
   i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
   context->set_error_message_for_code_gen_from_strings(*error_handle);
 }
 
 
+size_t Context::EstimatedSize() {
+  return static_cast<size_t>(
+      i::ContextMeasure(*Utils::OpenHandle(this)).Size());
+}
+
+
+MaybeLocal<v8::Object> ObjectTemplate::NewInstance(Local<Context> context) {
+  PREPARE_FOR_EXECUTION(context, "v8::ObjectTemplate::NewInstance()", Object);
+  auto self = Utils::OpenHandle(this);
+  Local<Object> result;
+  has_pending_exception =
+      !ToLocal<Object>(i::ApiNatives::InstantiateObject(self), &result);
+  RETURN_ON_FAILED_EXECUTION(Object);
+  RETURN_ESCAPED(result);
+}
+
+
 Local<v8::Object> ObjectTemplate::NewInstance() {
-  i::Handle<i::ObjectTemplateInfo> info = Utils::OpenHandle(this);
-  i::Isolate* isolate = info->GetIsolate();
-  ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
-             return Local<v8::Object>());
-  LOG_API(isolate, "ObjectTemplate::NewInstance");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> obj;
-  has_pending_exception = !i::Execution::InstantiateObject(info).ToHandle(&obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
-  return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(NewInstance(context), Object);
+}
+
+
+MaybeLocal<v8::Function> FunctionTemplate::GetFunction(Local<Context> context) {
+  PREPARE_FOR_EXECUTION(context, "v8::FunctionTemplate::GetFunction()",
+                        Function);
+  auto self = Utils::OpenHandle(this);
+  Local<Function> result;
+  has_pending_exception =
+      !ToLocal<Function>(i::ApiNatives::InstantiateFunction(self), &result);
+  RETURN_ON_FAILED_EXECUTION(Function);
+  RETURN_ESCAPED(result);
 }
 
 
 Local<v8::Function> FunctionTemplate::GetFunction() {
-  i::Handle<i::FunctionTemplateInfo> info = Utils::OpenHandle(this);
-  i::Isolate* isolate = info->GetIsolate();
-  ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
-             return Local<v8::Function>());
-  LOG_API(isolate, "FunctionTemplate::GetFunction");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> obj;
-  has_pending_exception =
-      !i::Execution::InstantiateFunction(info).ToHandle(&obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
-  return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(GetFunction(context), Function);
 }
 
 
-bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
-  i::Handle<i::FunctionTemplateInfo> info = Utils::OpenHandle(this);
-  i::Isolate* isolate = info->GetIsolate();
-  ON_BAILOUT(isolate, "v8::FunctionTemplate::HasInstanceOf()", return false);
-  i::Object* obj = *Utils::OpenHandle(*value);
-  return info->IsTemplateFor(obj);
+bool FunctionTemplate::HasInstance(v8::Local<v8::Value> value) {
+  auto self = Utils::OpenHandle(this);
+  auto obj = Utils::OpenHandle(*value);
+  return self->IsTemplateFor(*obj);
 }
 
 
@@ -5420,9 +5692,9 @@
 
 MUST_USE_RESULT
 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
-                                           String::NewStringType type,
+                                           v8::NewStringType type,
                                            i::Vector<const char> string) {
-  if (type == String::kInternalizedString) {
+  if (type == v8::NewStringType::kInternalized) {
     return factory->InternalizeUtf8String(string);
   }
   return factory->NewStringFromUtf8(string);
@@ -5431,9 +5703,9 @@
 
 MUST_USE_RESULT
 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
-                                           String::NewStringType type,
+                                           v8::NewStringType type,
                                            i::Vector<const uint8_t> string) {
-  if (type == String::kInternalizedString) {
+  if (type == v8::NewStringType::kInternalized) {
     return factory->InternalizeOneByteString(string);
   }
   return factory->NewStringFromOneByte(string);
@@ -5442,37 +5714,32 @@
 
 MUST_USE_RESULT
 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
-                                           String::NewStringType type,
+                                           v8::NewStringType type,
                                            i::Vector<const uint16_t> string) {
-  if (type == String::kInternalizedString) {
+  if (type == v8::NewStringType::kInternalized) {
     return factory->InternalizeTwoByteString(string);
   }
   return factory->NewStringFromTwoByte(string);
 }
 
 
-template<typename Char>
-inline Local<String> NewString(Isolate* v8_isolate,
-                               const char* location,
-                               const char* env,
-                               const Char* data,
-                               String::NewStringType type,
-                               int length) {
+STATIC_ASSERT(v8::String::kMaxLength == i::String::kMaxLength);
+
+
+template <typename Char>
+inline MaybeLocal<String> NewString(Isolate* v8_isolate, const char* location,
+                                    const char* env, const Char* data,
+                                    v8::NewStringType type, int length) {
   i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
-  LOG_API(isolate, env);
-  if (length == 0 && type != String::kUndetectableString) {
-    return String::Empty(v8_isolate);
-  }
+  if (length == 0) return String::Empty(v8_isolate);
+  // TODO(dcarney): throw a context free exception.
+  if (length > i::String::kMaxLength) return MaybeLocal<String>();
   ENTER_V8(isolate);
-  if (length == -1) length = StringLength(data);
-  // We do not expect this to fail. Change this if it does.
-  i::Handle<i::String> result = NewString(
-      isolate->factory(),
-      type,
-      i::Vector<const Char>(data, length)).ToHandleChecked();
-  if (type == String::kUndetectableString) {
-    result->MarkAsUndetectable();
-  }
+  LOG_API(isolate, env);
+  if (length < 0) length = StringLength(data);
+  i::Handle<i::String> result =
+      NewString(isolate->factory(), type, i::Vector<const Char>(data, length))
+          .ToHandleChecked();
   return Utils::ToLocal(result);
 }
 
@@ -5483,12 +5750,17 @@
                                   const char* data,
                                   NewStringType type,
                                   int length) {
-  return NewString(isolate,
-                   "v8::String::NewFromUtf8()",
-                   "String::NewFromUtf8",
-                   data,
-                   type,
-                   length);
+  RETURN_TO_LOCAL_UNCHECKED(
+      NewString(isolate, "v8::String::NewFromUtf8()", "String::NewFromUtf8",
+                data, static_cast<v8::NewStringType>(type), length),
+      String);
+}
+
+
+MaybeLocal<String> String::NewFromUtf8(Isolate* isolate, const char* data,
+                                       v8::NewStringType type, int length) {
+  return NewString(isolate, "v8::String::NewFromUtf8()", "String::NewFromUtf8",
+                   data, type, length);
 }
 
 
@@ -5496,12 +5768,18 @@
                                      const uint8_t* data,
                                      NewStringType type,
                                      int length) {
-  return NewString(isolate,
-                   "v8::String::NewFromOneByte()",
-                   "String::NewFromOneByte",
-                   data,
-                   type,
-                   length);
+  RETURN_TO_LOCAL_UNCHECKED(
+      NewString(isolate, "v8::String::NewFromOneByte()",
+                "String::NewFromOneByte", data,
+                static_cast<v8::NewStringType>(type), length),
+      String);
+}
+
+
+MaybeLocal<String> String::NewFromOneByte(Isolate* isolate, const uint8_t* data,
+                                          v8::NewStringType type, int length) {
+  return NewString(isolate, "v8::String::NewFromOneByte()",
+                   "String::NewFromOneByte", data, type, length);
 }
 
 
@@ -5509,20 +5787,27 @@
                                      const uint16_t* data,
                                      NewStringType type,
                                      int length) {
-  return NewString(isolate,
-                   "v8::String::NewFromTwoByte()",
-                   "String::NewFromTwoByte",
-                   data,
-                   type,
-                   length);
+  RETURN_TO_LOCAL_UNCHECKED(
+      NewString(isolate, "v8::String::NewFromTwoByte()",
+                "String::NewFromTwoByte", data,
+                static_cast<v8::NewStringType>(type), length),
+      String);
 }
 
 
-Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
+MaybeLocal<String> String::NewFromTwoByte(Isolate* isolate,
+                                          const uint16_t* data,
+                                          v8::NewStringType type, int length) {
+  return NewString(isolate, "v8::String::NewFromTwoByte()",
+                   "String::NewFromTwoByte", data, type, length);
+}
+
+
+Local<String> v8::String::Concat(Local<String> left, Local<String> right) {
   i::Handle<i::String> left_string = Utils::OpenHandle(*left);
   i::Isolate* isolate = left_string->GetIsolate();
-  LOG_API(isolate, "String::New(char)");
   ENTER_V8(isolate);
+  LOG_API(isolate, "v8::String::Concat");
   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
   // If we are steering towards a range error, do not wait for the error to be
   // thrown, and return the null handle instead.
@@ -5535,35 +5820,54 @@
 }
 
 
-static i::MaybeHandle<i::String> NewExternalStringHandle(
-    i::Isolate* isolate, v8::String::ExternalStringResource* resource) {
-  return isolate->factory()->NewExternalStringFromTwoByte(resource);
-}
-
-
-static i::MaybeHandle<i::String> NewExternalOneByteStringHandle(
-    i::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
-  return isolate->factory()->NewExternalStringFromOneByte(resource);
+MaybeLocal<String> v8::String::NewExternalTwoByte(
+    Isolate* isolate, v8::String::ExternalStringResource* resource) {
+  CHECK(resource && resource->data());
+  // TODO(dcarney): throw a context free exception.
+  if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) {
+    return MaybeLocal<String>();
+  }
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  LOG_API(i_isolate, "String::NewExternalTwoByte");
+  i::Handle<i::String> string = i_isolate->factory()
+                                    ->NewExternalStringFromTwoByte(resource)
+                                    .ToHandleChecked();
+  i_isolate->heap()->RegisterExternalString(*string);
+  return Utils::ToLocal(string);
 }
 
 
 Local<String> v8::String::NewExternal(
-    Isolate* isolate,
-    v8::String::ExternalStringResource* resource) {
-  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "String::NewExternal");
-  ENTER_V8(i_isolate);
+    Isolate* isolate, v8::String::ExternalStringResource* resource) {
+  RETURN_TO_LOCAL_UNCHECKED(NewExternalTwoByte(isolate, resource), String);
+}
+
+
+MaybeLocal<String> v8::String::NewExternalOneByte(
+    Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
   CHECK(resource && resource->data());
-  EXCEPTION_PREAMBLE(i_isolate);
-  i::Handle<i::String> string;
-  has_pending_exception =
-      !NewExternalStringHandle(i_isolate, resource).ToHandle(&string);
-  EXCEPTION_BAILOUT_CHECK(i_isolate, Local<String>());
-  i_isolate->heap()->external_string_table()->AddString(*string);
+  // TODO(dcarney): throw a context free exception.
+  if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) {
+    return MaybeLocal<String>();
+  }
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  LOG_API(i_isolate, "String::NewExternalOneByte");
+  i::Handle<i::String> string = i_isolate->factory()
+                                    ->NewExternalStringFromOneByte(resource)
+                                    .ToHandleChecked();
+  i_isolate->heap()->RegisterExternalString(*string);
   return Utils::ToLocal(string);
 }
 
 
+Local<String> v8::String::NewExternal(
+    Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
+  RETURN_TO_LOCAL_UNCHECKED(NewExternalOneByte(isolate, resource), String);
+}
+
+
 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
   i::Handle<i::String> obj = Utils::OpenHandle(this);
   i::Isolate* isolate = obj->GetIsolate();
@@ -5571,9 +5875,6 @@
     return false;  // Already an external string.
   }
   ENTER_V8(isolate);
-  if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
-    return false;
-  }
   if (isolate->heap()->IsInGCPostProcessing()) {
     return false;
   }
@@ -5584,28 +5885,12 @@
   DCHECK(!CanMakeExternal() || result);
   if (result) {
     DCHECK(obj->IsExternalString());
-    isolate->heap()->external_string_table()->AddString(*obj);
+    isolate->heap()->RegisterExternalString(*obj);
   }
   return result;
 }
 
 
-Local<String> v8::String::NewExternal(
-    Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
-  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "String::NewExternal");
-  ENTER_V8(i_isolate);
-  CHECK(resource && resource->data());
-  EXCEPTION_PREAMBLE(i_isolate);
-  i::Handle<i::String> string;
-  has_pending_exception =
-      !NewExternalOneByteStringHandle(i_isolate, resource).ToHandle(&string);
-  EXCEPTION_BAILOUT_CHECK(i_isolate, Local<String>());
-  i_isolate->heap()->external_string_table()->AddString(*string);
-  return Utils::ToLocal(string);
-}
-
-
 bool v8::String::MakeExternal(
     v8::String::ExternalOneByteStringResource* resource) {
   i::Handle<i::String> obj = Utils::OpenHandle(this);
@@ -5614,9 +5899,6 @@
     return false;  // Already an external string.
   }
   ENTER_V8(isolate);
-  if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
-    return false;
-  }
   if (isolate->heap()->IsInGCPostProcessing()) {
     return false;
   }
@@ -5627,7 +5909,7 @@
   DCHECK(!CanMakeExternal() || result);
   if (result) {
     DCHECK(obj->IsExternalString());
-    isolate->heap()->external_string_table()->AddString(*obj);
+    isolate->heap()->RegisterExternalString(*obj);
   }
   return result;
 }
@@ -5637,9 +5919,10 @@
   i::Handle<i::String> obj = Utils::OpenHandle(this);
   i::Isolate* isolate = obj->GetIsolate();
 
-  if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
+  // Old space strings should be externalized.
+  if (!isolate->heap()->new_space()->Contains(*obj)) return true;
   int size = obj->Size();  // Byte size of the original string.
-  if (size < i::ExternalString::kShortSize) return false;
+  if (size <= i::ExternalString::kShortSize) return false;
   i::StringShape shape(*obj);
   return !shape.IsExternal();
 }
@@ -5681,20 +5964,24 @@
 }
 
 
-Local<v8::Value> v8::BooleanObject::New(bool value) {
-  i::Isolate* isolate = i::Isolate::Current();
-  LOG_API(isolate, "BooleanObject::New");
-  ENTER_V8(isolate);
-  i::Handle<i::Object> boolean(value
-                               ? isolate->heap()->true_value()
-                               : isolate->heap()->false_value(),
-                               isolate);
+Local<v8::Value> v8::BooleanObject::New(Isolate* isolate, bool value) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  LOG_API(i_isolate, "BooleanObject::New");
+  ENTER_V8(i_isolate);
+  i::Handle<i::Object> boolean(value ? i_isolate->heap()->true_value()
+                                     : i_isolate->heap()->false_value(),
+                               i_isolate);
   i::Handle<i::Object> obj =
-      i::Object::ToObject(isolate, boolean).ToHandleChecked();
+      i::Object::ToObject(i_isolate, boolean).ToHandleChecked();
   return Utils::ToLocal(obj);
 }
 
 
+Local<v8::Value> v8::BooleanObject::New(bool value) {
+  return New(Isolate::GetCurrent(), value);
+}
+
+
 bool v8::BooleanObject::ValueOf() const {
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
@@ -5704,7 +5991,7 @@
 }
 
 
-Local<v8::Value> v8::StringObject::New(Handle<String> value) {
+Local<v8::Value> v8::StringObject::New(Local<String> value) {
   i::Handle<i::String> string = Utils::OpenHandle(*value);
   i::Isolate* isolate = string->GetIsolate();
   LOG_API(isolate, "StringObject::New");
@@ -5725,7 +6012,7 @@
 }
 
 
-Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Handle<Symbol> value) {
+Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Local<Symbol> value) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   LOG_API(i_isolate, "SymbolObject::New");
   ENTER_V8(i_isolate);
@@ -5745,20 +6032,24 @@
 }
 
 
-Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
-  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Date::New");
+MaybeLocal<v8::Value> v8::Date::New(Local<Context> context, double time) {
   if (std::isnan(time)) {
     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
-    time = base::OS::nan_value();
+    time = std::numeric_limits<double>::quiet_NaN();
   }
-  ENTER_V8(i_isolate);
-  EXCEPTION_PREAMBLE(i_isolate);
-  i::Handle<i::Object> obj;
-  has_pending_exception = !i::Execution::NewDate(
-      i_isolate, time).ToHandle(&obj);
-  EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
-  return Utils::ToLocal(obj);
+  PREPARE_FOR_EXECUTION(context, "Date::New", Value);
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(
+      i::JSDate::New(isolate->date_function(), isolate->date_function(), time),
+      &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
+  auto context = isolate->GetCurrentContext();
+  RETURN_TO_LOCAL_UNCHECKED(New(context, time), Value);
 }
 
 
@@ -5773,13 +6064,9 @@
 
 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
-             return);
   LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
   ENTER_V8(i_isolate);
-
   i_isolate->date_cache()->ResetDateCache();
-
   if (!i_isolate->eternal_handles()->Exists(
           i::EternalHandles::DATE_CACHE_VERSION)) {
     return;
@@ -5795,31 +6082,24 @@
 }
 
 
-static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
-  i::Isolate* isolate = i::Isolate::Current();
-  uint8_t flags_buf[3];
-  int num_flags = 0;
-  if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
-  if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
-  if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
-  DCHECK(num_flags <= static_cast<int>(arraysize(flags_buf)));
-  return isolate->factory()->InternalizeOneByteString(
-      i::Vector<const uint8_t>(flags_buf, num_flags));
+MaybeLocal<v8::RegExp> v8::RegExp::New(Local<Context> context,
+                                       Local<String> pattern, Flags flags) {
+  PREPARE_FOR_EXECUTION(context, "RegExp::New", RegExp);
+  Local<v8::RegExp> result;
+  has_pending_exception =
+      !ToLocal<RegExp>(i::JSRegExp::New(Utils::OpenHandle(*pattern),
+                                        static_cast<i::JSRegExp::Flags>(flags)),
+                       &result);
+  RETURN_ON_FAILED_EXECUTION(RegExp);
+  RETURN_ESCAPED(result);
 }
 
 
-Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
-                                  Flags flags) {
-  i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
-  LOG_API(isolate, "RegExp::New");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::JSRegExp> obj;
-  has_pending_exception = !i::Execution::NewJSRegExp(
-      Utils::OpenHandle(*pattern),
-      RegExpFlagsToString(flags)).ToHandle(&obj);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
-  return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
+Local<v8::RegExp> v8::RegExp::New(Local<String> pattern, Flags flags) {
+  auto isolate =
+      reinterpret_cast<Isolate*>(Utils::OpenHandle(*pattern)->GetIsolate());
+  auto context = isolate->GetCurrentContext();
+  RETURN_TO_LOCAL_UNCHECKED(New(context, pattern, flags), RegExp);
 }
 
 
@@ -5830,18 +6110,20 @@
 
 
 // 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) ==       \
-                static_cast<int>(i::JSRegExp::internal_flag))
-REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
-REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
-REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
-REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
+#define REGEXP_FLAG_ASSERT_EQ(flag)                   \
+  STATIC_ASSERT(static_cast<int>(v8::RegExp::flag) == \
+                static_cast<int>(i::JSRegExp::flag))
+REGEXP_FLAG_ASSERT_EQ(kNone);
+REGEXP_FLAG_ASSERT_EQ(kGlobal);
+REGEXP_FLAG_ASSERT_EQ(kIgnoreCase);
+REGEXP_FLAG_ASSERT_EQ(kMultiline);
+REGEXP_FLAG_ASSERT_EQ(kSticky);
+REGEXP_FLAG_ASSERT_EQ(kUnicode);
 #undef REGEXP_FLAG_ASSERT_EQ
 
 v8::RegExp::Flags v8::RegExp::GetFlags() const {
   i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
-  return static_cast<RegExp::Flags>(obj->GetFlags().value());
+  return RegExp::Flags(static_cast<int>(obj->GetFlags()));
 }
 
 
@@ -5869,174 +6151,395 @@
 }
 
 
-Local<Object> Array::CloneElementAt(uint32_t index) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
-  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  if (!self->HasFastObjectElements()) {
-    return Local<Object>();
-  }
+MaybeLocal<Object> Array::CloneElementAt(Local<Context> context,
+                                         uint32_t index) {
+  PREPARE_FOR_EXECUTION(context, "v8::Array::CloneElementAt()", Object);
+  auto self = Utils::OpenHandle(this);
+  if (!self->HasFastObjectElements()) return Local<Object>();
   i::FixedArray* elms = i::FixedArray::cast(self->elements());
   i::Object* paragon = elms->get(index);
-  if (!paragon->IsJSObject()) {
-    return Local<Object>();
-  }
+  if (!paragon->IsJSObject()) return Local<Object>();
   i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
-  EXCEPTION_PREAMBLE(isolate);
-  ENTER_V8(isolate);
-  i::Handle<i::JSObject> result =
-      isolate->factory()->CopyJSObject(paragon_handle);
-  has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
-  return Utils::ToLocal(result);
+  Local<Object> result;
+  has_pending_exception =
+      !ToLocal<Object>(isolate->factory()->CopyJSObject(paragon_handle),
+                       &result);
+  RETURN_ON_FAILED_EXECUTION(Object);
+  RETURN_ESCAPED(result);
 }
 
 
-bool Value::IsPromise() const {
-  i::Handle<i::Object> val = Utils::OpenHandle(this);
-  if (!val->IsJSObject()) return false;
-  i::Handle<i::JSObject> obj = i::Handle<i::JSObject>::cast(val);
-  i::Isolate* isolate = obj->GetIsolate();
-  LOG_API(isolate, "IsPromise");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> argv[] = { obj };
-  i::Handle<i::Object> b;
-  has_pending_exception = !i::Execution::Call(
-      isolate,
-      isolate->is_promise(),
-      isolate->factory()->undefined_value(),
-      arraysize(argv), argv,
-      false).ToHandle(&b);
-  EXCEPTION_BAILOUT_CHECK(isolate, false);
-  return b->BooleanValue();
+Local<Object> Array::CloneElementAt(uint32_t index) { return Local<Object>(); }
+
+
+Local<v8::Map> v8::Map::New(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  LOG_API(i_isolate, "Map::New");
+  ENTER_V8(i_isolate);
+  i::Handle<i::JSMap> obj = i_isolate->factory()->NewJSMap();
+  return Utils::ToLocal(obj);
 }
 
 
-Local<Promise::Resolver> Promise::Resolver::New(Isolate* v8_isolate) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-  LOG_API(isolate, "Promise::Resolver::New");
+size_t v8::Map::Size() const {
+  i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
+  return i::OrderedHashMap::cast(obj->table())->NumberOfElements();
+}
+
+
+void Map::Clear() {
+  auto self = Utils::OpenHandle(this);
+  i::Isolate* isolate = self->GetIsolate();
+  LOG_API(isolate, "Map::Clear");
   ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
+  i::JSMap::Clear(self);
+}
+
+
+MaybeLocal<Value> Map::Get(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION(context, "Map::Get", Value);
+  auto self = Utils::OpenHandle(this);
+  Local<Value> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
+  has_pending_exception =
+      !ToLocal<Value>(i::Execution::Call(isolate, isolate->map_get(), self,
+                                         arraysize(argv), argv),
+                      &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
+}
+
+
+MaybeLocal<Map> Map::Set(Local<Context> context, Local<Value> key,
+                         Local<Value> value) {
+  PREPARE_FOR_EXECUTION(context, "Map::Set", Map);
+  auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
-  has_pending_exception = !i::Execution::Call(
-      isolate,
-      isolate->promise_create(),
-      isolate->factory()->undefined_value(),
-      0, NULL,
-      false).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise::Resolver>());
-  return Local<Promise::Resolver>::Cast(Utils::ToLocal(result));
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
+                                 Utils::OpenHandle(*value)};
+  has_pending_exception = !i::Execution::Call(isolate, isolate->map_set(), self,
+                                              arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Map);
+  RETURN_ESCAPED(Local<Map>::Cast(Utils::ToLocal(result)));
+}
+
+
+Maybe<bool> Map::Has(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Map::Has", bool);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
+  has_pending_exception = !i::Execution::Call(isolate, isolate->map_has(), self,
+                                              arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(result->IsTrue());
+}
+
+
+Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Map::Delete", bool);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
+  has_pending_exception = !i::Execution::Call(isolate, isolate->map_delete(),
+                                              self, arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(result->IsTrue());
+}
+
+
+Local<Array> Map::AsArray() const {
+  i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
+  i::Isolate* isolate = obj->GetIsolate();
+  i::Factory* factory = isolate->factory();
+  LOG_API(isolate, "Map::AsArray");
+  ENTER_V8(isolate);
+  i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(obj->table()));
+  int size = table->NumberOfElements();
+  int length = size * 2;
+  i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
+  for (int i = 0; i < size; ++i) {
+    if (table->KeyAt(i)->IsTheHole()) continue;
+    result->set(i * 2, table->KeyAt(i));
+    result->set(i * 2 + 1, table->ValueAt(i));
+  }
+  i::Handle<i::JSArray> result_array =
+      factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
+  return Utils::ToLocal(result_array);
+}
+
+
+Local<v8::Set> v8::Set::New(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  LOG_API(i_isolate, "Set::New");
+  ENTER_V8(i_isolate);
+  i::Handle<i::JSSet> obj = i_isolate->factory()->NewJSSet();
+  return Utils::ToLocal(obj);
+}
+
+
+size_t v8::Set::Size() const {
+  i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
+  return i::OrderedHashSet::cast(obj->table())->NumberOfElements();
+}
+
+
+void Set::Clear() {
+  auto self = Utils::OpenHandle(this);
+  i::Isolate* isolate = self->GetIsolate();
+  LOG_API(isolate, "Set::Clear");
+  ENTER_V8(isolate);
+  i::JSSet::Clear(self);
+}
+
+
+MaybeLocal<Set> Set::Add(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION(context, "Set::Add", Set);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
+  has_pending_exception = !i::Execution::Call(isolate, isolate->set_add(), self,
+                                              arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Set);
+  RETURN_ESCAPED(Local<Set>::Cast(Utils::ToLocal(result)));
+}
+
+
+Maybe<bool> Set::Has(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Set::Has", bool);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
+  has_pending_exception = !i::Execution::Call(isolate, isolate->set_has(), self,
+                                              arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(result->IsTrue());
+}
+
+
+Maybe<bool> Set::Delete(Local<Context> context, Local<Value> key) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Set::Delete", bool);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
+  has_pending_exception = !i::Execution::Call(isolate, isolate->set_delete(),
+                                              self, arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(result->IsTrue());
+}
+
+
+Local<Array> Set::AsArray() const {
+  i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
+  i::Isolate* isolate = obj->GetIsolate();
+  i::Factory* factory = isolate->factory();
+  LOG_API(isolate, "Set::AsArray");
+  ENTER_V8(isolate);
+  i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(obj->table()));
+  int length = table->NumberOfElements();
+  i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
+  for (int i = 0; i < length; ++i) {
+    i::Object* key = table->KeyAt(i);
+    if (!key->IsTheHole()) {
+      result->set(i, key);
+    }
+  }
+  i::Handle<i::JSArray> result_array =
+      factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
+  return Utils::ToLocal(result_array);
+}
+
+
+MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) {
+  PREPARE_FOR_EXECUTION(context, "Promise::Resolver::New", Resolver);
+  i::Handle<i::Object> result;
+  has_pending_exception =
+      !i::Execution::Call(isolate, isolate->promise_create(),
+                          isolate->factory()->undefined_value(), 0, NULL)
+           .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Promise::Resolver);
+  RETURN_ESCAPED(Local<Promise::Resolver>::Cast(Utils::ToLocal(result)));
+}
+
+
+Local<Promise::Resolver> Promise::Resolver::New(Isolate* isolate) {
+  RETURN_TO_LOCAL_UNCHECKED(New(isolate->GetCurrentContext()),
+                            Promise::Resolver);
 }
 
 
 Local<Promise> Promise::Resolver::GetPromise() {
-  i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
   return Local<Promise>::Cast(Utils::ToLocal(promise));
 }
 
 
-void Promise::Resolver::Resolve(Handle<Value> value) {
-  i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
-  i::Isolate* isolate = promise->GetIsolate();
-  LOG_API(isolate, "Promise::Resolver::Resolve");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
-  has_pending_exception = i::Execution::Call(
-      isolate,
-      isolate->promise_resolve(),
-      isolate->factory()->undefined_value(),
-      arraysize(argv), argv,
-      false).is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
+Maybe<bool> Promise::Resolver::Resolve(Local<Context> context,
+                                       Local<Value> value) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Promise::Resolver::Resolve", bool);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value)};
+  has_pending_exception =
+      i::Execution::Call(isolate, isolate->promise_resolve(),
+                         isolate->factory()->undefined_value(), arraysize(argv),
+                         argv)
+          .is_null();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(true);
 }
 
 
-void Promise::Resolver::Reject(Handle<Value> value) {
-  i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
-  i::Isolate* isolate = promise->GetIsolate();
-  LOG_API(isolate, "Promise::Resolver::Reject");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
-  has_pending_exception = i::Execution::Call(
-      isolate,
-      isolate->promise_reject(),
-      isolate->factory()->undefined_value(),
-      arraysize(argv), argv,
-      false).is_null();
-  EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
+void Promise::Resolver::Resolve(Local<Value> value) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  USE(Resolve(context, value));
 }
 
 
-Local<Promise> Promise::Chain(Handle<Function> handler) {
-  i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
-  i::Isolate* isolate = promise->GetIsolate();
-  LOG_API(isolate, "Promise::Chain");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
+Maybe<bool> Promise::Resolver::Reject(Local<Context> context,
+                                      Local<Value> value) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Promise::Resolver::Resolve", bool);
+  auto self = Utils::OpenHandle(this);
+  i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value)};
+  has_pending_exception =
+      i::Execution::Call(isolate, isolate->promise_reject(),
+                         isolate->factory()->undefined_value(), arraysize(argv),
+                         argv)
+          .is_null();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return Just(true);
+}
+
+
+void Promise::Resolver::Reject(Local<Value> value) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  USE(Reject(context, value));
+}
+
+
+namespace {
+
+MaybeLocal<Promise> DoChain(Value* value, Local<Context> context,
+                            Local<Function> handler) {
+  PREPARE_FOR_EXECUTION(context, "Promise::Chain", Promise);
+  auto self = Utils::OpenHandle(value);
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*handler)};
+  i::Handle<i::Object> result;
+  has_pending_exception = !i::Execution::Call(isolate, isolate->promise_chain(),
+                                              self, arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Promise);
+  RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
+}
+
+}  // namespace
+
+
+MaybeLocal<Promise> Promise::Chain(Local<Context> context,
+                                   Local<Function> handler) {
+  return DoChain(this, context, handler);
+}
+
+
+Local<Promise> Promise::Chain(Local<Function> handler) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(DoChain(this, context, handler), Promise);
+}
+
+
+MaybeLocal<Promise> Promise::Catch(Local<Context> context,
+                                   Local<Function> handler) {
+  PREPARE_FOR_EXECUTION(context, "Promise::Catch", Promise);
+  auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
   i::Handle<i::Object> result;
-  has_pending_exception = !i::Execution::Call(
-      isolate,
-      isolate->promise_chain(),
-      promise,
-      arraysize(argv), argv,
-      false).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
-  return Local<Promise>::Cast(Utils::ToLocal(result));
+  has_pending_exception = !i::Execution::Call(isolate, isolate->promise_catch(),
+                                              self, arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Promise);
+  RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
 }
 
 
-Local<Promise> Promise::Catch(Handle<Function> handler) {
-  i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
-  i::Isolate* isolate = promise->GetIsolate();
-  LOG_API(isolate, "Promise::Catch");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
-  i::Handle<i::Object> result;
-  has_pending_exception = !i::Execution::Call(
-      isolate,
-      isolate->promise_catch(),
-      promise,
-      arraysize(argv), argv,
-      false).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
-  return Local<Promise>::Cast(Utils::ToLocal(result));
+Local<Promise> Promise::Catch(Local<Function> handler) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(Catch(context, handler), Promise);
 }
 
 
-Local<Promise> Promise::Then(Handle<Function> handler) {
-  i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
-  i::Isolate* isolate = promise->GetIsolate();
-  LOG_API(isolate, "Promise::Then");
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
+MaybeLocal<Promise> Promise::Then(Local<Context> context,
+                                  Local<Function> handler) {
+  PREPARE_FOR_EXECUTION(context, "Promise::Then", Promise);
+  auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
   i::Handle<i::Object> result;
-  has_pending_exception = !i::Execution::Call(
-      isolate,
-      isolate->promise_then(),
-      promise,
-      arraysize(argv), argv,
-      false).ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
-  return Local<Promise>::Cast(Utils::ToLocal(result));
+  has_pending_exception = !i::Execution::Call(isolate, isolate->promise_then(),
+                                              self, arraysize(argv), argv)
+                               .ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Promise);
+  RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
+}
+
+
+Local<Promise> Promise::Then(Local<Function> handler) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(this));
+  RETURN_TO_LOCAL_UNCHECKED(Then(context, handler), Promise);
 }
 
 
 bool Promise::HasHandler() {
-  i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
   i::Isolate* isolate = promise->GetIsolate();
   LOG_API(isolate, "Promise::HasRejectHandler");
   ENTER_V8(isolate);
   i::Handle<i::Symbol> key = isolate->factory()->promise_has_handler_symbol();
-  return i::JSObject::GetDataProperty(promise, key)->IsTrue();
+  return i::JSReceiver::GetDataProperty(promise, key)->IsTrue();
 }
 
 
+Local<Object> Proxy::GetTarget() {
+  i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
+  i::Handle<i::JSReceiver> target(self->target());
+  return Utils::ToLocal(target);
+}
+
+
+Local<Value> Proxy::GetHandler() {
+  i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> handler(self->handler(), self->GetIsolate());
+  return Utils::ToLocal(handler);
+}
+
+
+bool Proxy::IsRevoked() {
+  i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
+  return self->IsRevoked();
+}
+
+
+void Proxy::Revoke() {
+  i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
+  i::JSProxy::Revoke(self);
+}
+
+
+MaybeLocal<Proxy> Proxy::New(Local<Context> context, Local<Object> local_target,
+                             Local<Object> local_handler) {
+  PREPARE_FOR_EXECUTION(context, "Proxy::New", Proxy);
+  i::Handle<i::JSReceiver> target = Utils::OpenHandle(*local_target);
+  i::Handle<i::JSReceiver> handler = Utils::OpenHandle(*local_handler);
+  Local<Proxy> result;
+  has_pending_exception =
+      !ToLocal<Proxy>(i::JSProxy::New(isolate, target, handler), &result);
+  RETURN_ON_FAILED_EXECUTION(Proxy);
+  RETURN_ESCAPED(result);
+}
+
 bool v8::ArrayBuffer::IsExternal() const {
   return Utils::OpenHandle(this)->is_external();
 }
@@ -6048,14 +6551,22 @@
 
 
 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
-  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
-  Utils::ApiCheck(!obj->is_external(),
-                  "v8::ArrayBuffer::Externalize",
+  i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
+  i::Isolate* isolate = self->GetIsolate();
+  Utils::ApiCheck(!self->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());
+  self->set_is_external(true);
+  isolate->heap()->UnregisterArrayBuffer(*self);
+
+  return GetContents();
+}
+
+
+v8::ArrayBuffer::Contents v8::ArrayBuffer::GetContents() {
+  i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
+  size_t byte_length = static_cast<size_t>(self->byte_length()->Number());
   Contents contents;
-  contents.data_ = obj->backing_store();
+  contents.data_ = self->backing_store();
   contents.byte_length_ = byte_length;
   return contents;
 }
@@ -6071,7 +6582,7 @@
                   "Only neuterable ArrayBuffers can be neutered");
   LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
   ENTER_V8(isolate);
-  i::Runtime::NeuterArrayBuffer(obj);
+  obj->Neuter();
 }
 
 
@@ -6086,20 +6597,25 @@
   LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
   ENTER_V8(i_isolate);
   i::Handle<i::JSArrayBuffer> obj =
-      i_isolate->factory()->NewJSArrayBuffer();
-  i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
+      i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared);
+  i::JSArrayBuffer::SetupAllocatingData(obj, i_isolate, byte_length);
   return Utils::ToLocal(obj);
 }
 
 
 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
-                                        size_t byte_length) {
+                                        size_t byte_length,
+                                        ArrayBufferCreationMode mode) {
+  // Embedders must guarantee that the external backing store is valid.
+  CHECK(byte_length == 0 || data != NULL);
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
   ENTER_V8(i_isolate);
   i::Handle<i::JSArrayBuffer> obj =
-      i_isolate->factory()->NewJSArrayBuffer();
-  i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length);
+      i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared);
+  i::JSArrayBuffer::Setup(obj, i_isolate,
+                          mode == ArrayBufferCreationMode::kExternalized, data,
+                          byte_length);
   return Utils::ToLocal(obj);
 }
 
@@ -6119,6 +6635,36 @@
 }
 
 
+size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
+  i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
+  i::Isolate* isolate = self->GetIsolate();
+  size_t byte_offset = i::NumberToSize(isolate, self->byte_offset());
+  size_t bytes_to_copy =
+      i::Min(byte_length, i::NumberToSize(isolate, self->byte_length()));
+  if (bytes_to_copy) {
+    i::DisallowHeapAllocation no_gc;
+    i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()));
+    const char* source = reinterpret_cast<char*>(buffer->backing_store());
+    if (source == nullptr) {
+      DCHECK(self->IsJSTypedArray());
+      i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*self));
+      i::Handle<i::FixedTypedArrayBase> fixed_array(
+          i::FixedTypedArrayBase::cast(typed_array->elements()));
+      source = reinterpret_cast<char*>(fixed_array->DataPtr());
+    }
+    memcpy(dest, source + byte_offset, bytes_to_copy);
+  }
+  return bytes_to_copy;
+}
+
+
+bool v8::ArrayBufferView::HasBuffer() const {
+  i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
+  i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()));
+  return buffer->backing_store() != nullptr;
+}
+
+
 size_t v8::ArrayBufferView::ByteOffset() {
   i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
   return static_cast<size_t>(obj->byte_offset()->Number());
@@ -6133,38 +6679,60 @@
 
 size_t v8::TypedArray::Length() {
   i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
-  return static_cast<size_t>(obj->length()->Number());
+  return static_cast<size_t>(obj->length_value());
 }
 
 
-#define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size)                       \
-  Local<Type##Array> Type##Array::New(Handle<ArrayBuffer> array_buffer,      \
-                                      size_t byte_offset, size_t length) {   \
-    i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate();    \
-    LOG_API(isolate,                                                         \
-            "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \
-    ENTER_V8(isolate);                                                       \
-    if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue),   \
-                         "v8::" #Type                                        \
-                         "Array::New(Handle<ArrayBuffer>, size_t, size_t)",  \
-                         "length exceeds max allowed value")) {              \
-      return Local<Type##Array>();                                           \
-    }                                                                        \
-    i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);   \
-    i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray(    \
-        v8::kExternal##Type##Array, buffer, byte_offset, length);            \
-    return Utils::ToLocal##Type##Array(obj);                                 \
+#define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size)                        \
+  Local<Type##Array> Type##Array::New(Local<ArrayBuffer> array_buffer,        \
+                                      size_t byte_offset, size_t length) {    \
+    i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate();     \
+    LOG_API(isolate,                                                          \
+            "v8::" #Type "Array::New(Local<ArrayBuffer>, size_t, size_t)");   \
+    ENTER_V8(isolate);                                                        \
+    if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue),    \
+                         "v8::" #Type                                         \
+                         "Array::New(Local<ArrayBuffer>, size_t, size_t)",    \
+                         "length exceeds max allowed value")) {               \
+      return Local<Type##Array>();                                            \
+    }                                                                         \
+    i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);    \
+    i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray(     \
+        i::kExternal##Type##Array, buffer, byte_offset, length);              \
+    return Utils::ToLocal##Type##Array(obj);                                  \
+  }                                                                           \
+  Local<Type##Array> Type##Array::New(                                        \
+      Local<SharedArrayBuffer> shared_array_buffer, size_t byte_offset,       \
+      size_t length) {                                                        \
+    CHECK(i::FLAG_harmony_sharedarraybuffer);                                 \
+    i::Isolate* isolate =                                                     \
+        Utils::OpenHandle(*shared_array_buffer)->GetIsolate();                \
+    LOG_API(isolate, "v8::" #Type                                             \
+                     "Array::New(Local<SharedArrayBuffer>, size_t, size_t)"); \
+    ENTER_V8(isolate);                                                        \
+    if (!Utils::ApiCheck(                                                     \
+            length <= static_cast<size_t>(i::Smi::kMaxValue),                 \
+            "v8::" #Type                                                      \
+            "Array::New(Local<SharedArrayBuffer>, size_t, size_t)",           \
+            "length exceeds max allowed value")) {                            \
+      return Local<Type##Array>();                                            \
+    }                                                                         \
+    i::Handle<i::JSArrayBuffer> buffer =                                      \
+        Utils::OpenHandle(*shared_array_buffer);                              \
+    i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray(     \
+        i::kExternal##Type##Array, buffer, byte_offset, length);              \
+    return Utils::ToLocal##Type##Array(obj);                                  \
   }
 
 
 TYPED_ARRAYS(TYPED_ARRAY_NEW)
 #undef TYPED_ARRAY_NEW
 
-Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer,
+Local<DataView> DataView::New(Local<ArrayBuffer> array_buffer,
                               size_t byte_offset, size_t byte_length) {
   i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
   i::Isolate* isolate = buffer->GetIsolate();
-  LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
+  LOG_API(isolate, "v8::DataView::New(Local<ArrayBuffer>, size_t, size_t)");
   ENTER_V8(isolate);
   i::Handle<i::JSDataView> obj =
       isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
@@ -6172,6 +6740,84 @@
 }
 
 
+Local<DataView> DataView::New(Local<SharedArrayBuffer> shared_array_buffer,
+                              size_t byte_offset, size_t byte_length) {
+  CHECK(i::FLAG_harmony_sharedarraybuffer);
+  i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*shared_array_buffer);
+  i::Isolate* isolate = buffer->GetIsolate();
+  LOG_API(isolate,
+          "v8::DataView::New(Local<SharedArrayBuffer>, size_t, size_t)");
+  ENTER_V8(isolate);
+  i::Handle<i::JSDataView> obj =
+      isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
+  return Utils::ToLocal(obj);
+}
+
+
+bool v8::SharedArrayBuffer::IsExternal() const {
+  return Utils::OpenHandle(this)->is_external();
+}
+
+
+v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() {
+  i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
+  i::Isolate* isolate = self->GetIsolate();
+  Utils::ApiCheck(!self->is_external(), "v8::SharedArrayBuffer::Externalize",
+                  "SharedArrayBuffer already externalized");
+  self->set_is_external(true);
+  isolate->heap()->UnregisterArrayBuffer(*self);
+  return GetContents();
+}
+
+
+v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::GetContents() {
+  i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
+  size_t byte_length = static_cast<size_t>(self->byte_length()->Number());
+  Contents contents;
+  contents.data_ = self->backing_store();
+  contents.byte_length_ = byte_length;
+  return contents;
+}
+
+
+size_t v8::SharedArrayBuffer::ByteLength() const {
+  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
+  return static_cast<size_t>(obj->byte_length()->Number());
+}
+
+
+Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate,
+                                                    size_t byte_length) {
+  CHECK(i::FLAG_harmony_sharedarraybuffer);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  LOG_API(i_isolate, "v8::SharedArrayBuffer::New(size_t)");
+  ENTER_V8(i_isolate);
+  i::Handle<i::JSArrayBuffer> obj =
+      i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
+  i::JSArrayBuffer::SetupAllocatingData(obj, i_isolate, byte_length, true,
+                                        i::SharedFlag::kShared);
+  return Utils::ToLocalShared(obj);
+}
+
+
+Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
+    Isolate* isolate, void* data, size_t byte_length,
+    ArrayBufferCreationMode mode) {
+  CHECK(i::FLAG_harmony_sharedarraybuffer);
+  // Embedders must guarantee that the external backing store is valid.
+  CHECK(byte_length == 0 || data != NULL);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  LOG_API(i_isolate, "v8::SharedArrayBuffer::New(void*, size_t)");
+  ENTER_V8(i_isolate);
+  i::Handle<i::JSArrayBuffer> obj =
+      i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
+  i::JSArrayBuffer::Setup(obj, i_isolate,
+                          mode == ArrayBufferCreationMode::kExternalized, data,
+                          byte_length, i::SharedFlag::kShared);
+  return Utils::ToLocalShared(obj);
+}
+
+
 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   LOG_API(i_isolate, "Symbol::New()");
@@ -6184,7 +6830,8 @@
 
 static i::Handle<i::Symbol> SymbolFor(i::Isolate* isolate,
                                       i::Handle<i::String> name,
-                                      i::Handle<i::String> part) {
+                                      i::Handle<i::String> part,
+                                      bool private_symbol) {
   i::Handle<i::JSObject> registry = isolate->GetSymbolRegistry();
   i::Handle<i::JSObject> symbols =
       i::Handle<i::JSObject>::cast(
@@ -6193,7 +6840,10 @@
       i::Object::GetPropertyOrElement(symbols, name).ToHandleChecked();
   if (!symbol->IsSymbol()) {
     DCHECK(symbol->IsUndefined());
-    symbol = isolate->factory()->NewSymbol();
+    if (private_symbol)
+      symbol = isolate->factory()->NewPrivateSymbol();
+    else
+      symbol = isolate->factory()->NewSymbol();
     i::Handle<i::Symbol>::cast(symbol)->set_name(*name);
     i::JSObject::SetProperty(symbols, name, symbol, i::STRICT).Assert();
   }
@@ -6205,7 +6855,7 @@
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
   i::Handle<i::String> part = i_isolate->factory()->for_string();
-  return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
+  return Utils::ToLocal(SymbolFor(i_isolate, i_name, part, false));
 }
 
 
@@ -6213,7 +6863,7 @@
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
   i::Handle<i::String> part = i_isolate->factory()->for_api_string();
-  return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
+  return Utils::ToLocal(SymbolFor(i_isolate, i_name, part, false));
 }
 
 
@@ -6235,6 +6885,12 @@
 }
 
 
+Local<Symbol> v8::Symbol::GetIsConcatSpreadable(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  return Utils::ToLocal(i_isolate->factory()->is_concat_spreadable_symbol());
+}
+
+
 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   LOG_API(i_isolate, "Private::New()");
@@ -6242,28 +6898,17 @@
   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
   if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name));
   Local<Symbol> result = Utils::ToLocal(symbol);
-  return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
+  return v8::Local<Private>(reinterpret_cast<Private*>(*result));
 }
 
 
 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
-  i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
   i::Handle<i::String> part = i_isolate->factory()->private_api_string();
-  i::Handle<i::JSObject> privates =
-      i::Handle<i::JSObject>::cast(
-          i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
-  i::Handle<i::Object> symbol =
-      i::Object::GetPropertyOrElement(privates, i_name).ToHandleChecked();
-  if (!symbol->IsSymbol()) {
-    DCHECK(symbol->IsUndefined());
-    symbol = i_isolate->factory()->NewPrivateSymbol();
-    i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
-    i::JSObject::SetProperty(privates, i_name, symbol, i::STRICT).Assert();
-  }
-  Local<Symbol> result = Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
-  return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
+  Local<Symbol> result =
+      Utils::ToLocal(SymbolFor(i_isolate, i_name, part, true));
+  return v8::Local<Private>(reinterpret_cast<Private*>(*result));
 }
 
 
@@ -6271,7 +6916,7 @@
   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
   if (std::isnan(value)) {
     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
-    value = base::OS::nan_value();
+    value = std::numeric_limits<double>::quiet_NaN();
   }
   ENTER_V8(internal_isolate);
   i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
@@ -6303,9 +6948,11 @@
 }
 
 
-void Isolate::CollectAllGarbage(const char* gc_reason) {
-  reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
-      i::Heap::kNoGCFlags, gc_reason);
+void Isolate::ReportExternalAllocationLimitReached() {
+  i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
+  if (heap->gc_state() != i::Heap::NOT_IN_GC) return;
+  heap->ReportExternalMemoryPressure(
+      "external memory allocation limit reached.");
 }
 
 
@@ -6397,47 +7044,41 @@
 }
 
 
-void Isolate::AddGCPrologueCallback(GCPrologueCallback callback,
-                                    GCType gc_type) {
+void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
   isolate->heap()->AddGCPrologueCallback(callback, gc_type);
 }
 
 
-void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) {
+void Isolate::RemoveGCPrologueCallback(GCCallback callback) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
   isolate->heap()->RemoveGCPrologueCallback(callback);
 }
 
 
-void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback,
-                                    GCType gc_type) {
+void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
   isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
 }
 
 
-void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
+void Isolate::RemoveGCEpilogueCallback(GCCallback callback) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
   isolate->heap()->RemoveGCEpilogueCallback(callback);
 }
 
 
-void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
+void V8::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
   i::Isolate* isolate = i::Isolate::Current();
   isolate->heap()->AddGCPrologueCallback(
-      reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback),
-      gc_type,
-      false);
+      reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false);
 }
 
 
-void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
+void V8::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
   i::Isolate* isolate = i::Isolate::Current();
   isolate->heap()->AddGCEpilogueCallback(
-      reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback),
-      gc_type,
-      false);
+      reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false);
 }
 
 
@@ -6483,10 +7124,6 @@
 }
 
 
-void Isolate::ClearInterrupt() {
-}
-
-
 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
   CHECK(i::FLAG_expose_gc);
   if (type == kMinorGarbageCollection) {
@@ -6509,8 +7146,15 @@
 
 
 Isolate* Isolate::New(const Isolate::CreateParams& params) {
-  i::Isolate* isolate = new i::Isolate(params.enable_serializer);
+  i::Isolate* isolate = new i::Isolate(false);
   Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
+  CHECK(params.array_buffer_allocator != NULL);
+  isolate->set_array_buffer_allocator(params.array_buffer_allocator);
+  if (params.snapshot_blob != NULL) {
+    isolate->set_snapshot_blob(params.snapshot_blob);
+  } else {
+    isolate->set_snapshot_blob(i::Snapshot::DefaultSnapshotBlob());
+  }
   if (params.entry_hook) {
     isolate->set_function_entry_hook(params.entry_hook);
   }
@@ -6519,12 +7163,30 @@
     isolate->logger()->SetCodeEventHandler(kJitCodeEventDefault,
                                            params.code_event_handler);
   }
+  if (params.counter_lookup_callback) {
+    v8_isolate->SetCounterFunction(params.counter_lookup_callback);
+  }
+
+  if (params.create_histogram_callback) {
+    v8_isolate->SetCreateHistogramFunction(params.create_histogram_callback);
+  }
+
+  if (params.add_histogram_sample_callback) {
+    v8_isolate->SetAddHistogramSampleFunction(
+        params.add_histogram_sample_callback);
+  }
   SetResourceConstraints(isolate, params.constraints);
   // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this.
   Isolate::Scope isolate_scope(v8_isolate);
   if (params.entry_hook || !i::Snapshot::Initialize(isolate)) {
     // If the isolate has a function entry hook, it needs to re-build all its
     // code stubs with entry hooks embedded, so don't deserialize a snapshot.
+    if (i::Snapshot::EmbedsScript(isolate)) {
+      // If the snapshot embeds a script, we cannot initialize the isolate
+      // without the snapshot as a fallback. This is unlikely to happen though.
+      V8_Fatal(__FILE__, __LINE__,
+               "Initializing isolate from custom startup snapshot failed");
+    }
     isolate->Init(NULL);
   }
   return v8_isolate;
@@ -6542,6 +7204,12 @@
 }
 
 
+void Isolate::DiscardThreadSpecificMetadata() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  isolate->DiscardPerThreadDataForThisThread();
+}
+
+
 void Isolate::Enter() {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
   isolate->Enter();
@@ -6554,6 +7222,13 @@
 }
 
 
+void Isolate::SetAbortOnUncaughtExceptionCallback(
+    AbortOnUncaughtExceptionCallback callback) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  isolate->SetAbortOnUncaughtExceptionCallback(callback);
+}
+
+
 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
     Isolate* isolate,
     Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
@@ -6614,8 +7289,69 @@
   heap_statistics->total_heap_size_executable_ =
       heap->CommittedMemoryExecutable();
   heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
+  heap_statistics->total_available_size_ = heap->Available();
   heap_statistics->used_heap_size_ = heap->SizeOfObjects();
   heap_statistics->heap_size_limit_ = heap->MaxReserved();
+  heap_statistics->does_zap_garbage_ = heap->ShouldZapGarbage();
+}
+
+
+size_t Isolate::NumberOfHeapSpaces() {
+  return i::LAST_SPACE - i::FIRST_SPACE + 1;
+}
+
+
+bool Isolate::GetHeapSpaceStatistics(HeapSpaceStatistics* space_statistics,
+                                     size_t index) {
+  if (!space_statistics) return false;
+  if (!i::Heap::IsValidAllocationSpace(static_cast<i::AllocationSpace>(index)))
+    return false;
+
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  i::Heap* heap = isolate->heap();
+  i::Space* space = heap->space(static_cast<int>(index));
+
+  space_statistics->space_name_ = heap->GetSpaceName(static_cast<int>(index));
+  space_statistics->space_size_ = space->CommittedMemory();
+  space_statistics->space_used_size_ = space->SizeOfObjects();
+  space_statistics->space_available_size_ = space->Available();
+  space_statistics->physical_space_size_ = space->CommittedPhysicalMemory();
+  return true;
+}
+
+
+size_t Isolate::NumberOfTrackedHeapObjectTypes() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  i::Heap* heap = isolate->heap();
+  return heap->NumberOfTrackedHeapObjectTypes();
+}
+
+
+bool Isolate::GetHeapObjectStatisticsAtLastGC(
+    HeapObjectStatistics* object_statistics, size_t type_index) {
+  if (!object_statistics) return false;
+  if (!i::FLAG_track_gc_object_stats) return false;
+
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  i::Heap* heap = isolate->heap();
+  if (type_index >= heap->NumberOfTrackedHeapObjectTypes()) return false;
+
+  const char* object_type;
+  const char* object_sub_type;
+  size_t object_count = heap->ObjectCountAtLastGC(type_index);
+  size_t object_size = heap->ObjectSizeAtLastGC(type_index);
+  if (!heap->GetObjectTypeName(type_index, &object_type, &object_sub_type)) {
+    // There should be no objects counted when the type is unknown.
+    DCHECK_EQ(object_count, 0U);
+    DCHECK_EQ(object_size, 0U);
+    return false;
+  }
+
+  object_statistics->object_type_ = object_type;
+  object_statistics->object_sub_type_ = object_sub_type;
+  object_statistics->object_count_ = object_count;
+  object_statistics->object_size_ = object_size;
+  return true;
 }
 
 
@@ -6660,7 +7396,7 @@
 }
 
 
-void Isolate::EnqueueMicrotask(Handle<Function> microtask) {
+void Isolate::EnqueueMicrotask(Local<Function> microtask) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
   isolate->EnqueueMicrotask(Utils::OpenHandle(*microtask));
 }
@@ -6751,6 +7487,18 @@
 }
 
 
+void Isolate::IsolateInForegroundNotification() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  return isolate->heap()->SetOptimizeForLatency();
+}
+
+
+void Isolate::IsolateInBackgroundNotification() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  return isolate->heap()->SetOptimizeForMemoryUsage();
+}
+
+
 void Isolate::SetJitCodeEventHandler(JitCodeEventOptions options,
                                      JitCodeEventHandler event_handler) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
@@ -6798,9 +7546,8 @@
 }
 
 
-bool Isolate::AddMessageListener(MessageCallback that, Handle<Value> data) {
+bool Isolate::AddMessageListener(MessageCallback that, Local<Value> data) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
-  ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
   NeanderArray listeners(isolate->factory()->message_listeners());
@@ -6815,7 +7562,6 @@
 
 void Isolate::RemoveMessageListeners(MessageCallback that) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
-  ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
   NeanderArray listeners(isolate->factory()->message_listeners());
@@ -6856,10 +7602,10 @@
  public:
   explicit VisitorAdapter(PersistentHandleVisitor* visitor)
       : visitor_(visitor) {}
-  virtual void VisitPointers(i::Object** start, i::Object** end) {
+  void VisitPointers(i::Object** start, i::Object** end) override {
     UNREACHABLE();
   }
-  virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
+  void VisitEmbedderReference(i::Object** p, uint16_t class_id) override {
     Value* value = ToApi<Value>(i::Handle<i::Object>(p));
     visitor_->VisitPersistentHandle(
         reinterpret_cast<Persistent<Value>*>(&value), class_id);
@@ -6888,15 +7634,26 @@
 }
 
 
-String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
+void Isolate::VisitWeakHandles(PersistentHandleVisitor* visitor) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  i::DisallowHeapAllocation no_allocation;
+  VisitorAdapter visitor_adapter(visitor);
+  isolate->global_handles()->IterateWeakRootsInNewSpaceWithClassIds(
+      &visitor_adapter);
+}
+
+
+String::Utf8Value::Utf8Value(v8::Local<v8::Value> obj)
     : str_(NULL), length_(0) {
-  i::Isolate* isolate = i::Isolate::Current();
   if (obj.IsEmpty()) return;
+  i::Isolate* isolate = i::Isolate::Current();
+  Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  TryCatch try_catch;
-  Handle<String> str = obj->ToString(reinterpret_cast<v8::Isolate*>(isolate));
-  if (str.IsEmpty()) return;
+  Local<Context> context = v8_isolate->GetCurrentContext();
+  TryCatch try_catch(v8_isolate);
+  Local<String> str;
+  if (!obj->ToString(context).ToLocal(&str)) return;
   i::Handle<i::String> i_str = Utils::OpenHandle(*str);
   length_ = v8::Utf8Length(*i_str, isolate);
   str_ = i::NewArray<char>(length_ + 1);
@@ -6909,15 +7666,16 @@
 }
 
 
-String::Value::Value(v8::Handle<v8::Value> obj)
-    : str_(NULL), length_(0) {
-  i::Isolate* isolate = i::Isolate::Current();
+String::Value::Value(v8::Local<v8::Value> obj) : str_(NULL), length_(0) {
   if (obj.IsEmpty()) return;
+  i::Isolate* isolate = i::Isolate::Current();
+  Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  TryCatch try_catch;
-  Handle<String> str = obj->ToString(reinterpret_cast<v8::Isolate*>(isolate));
-  if (str.IsEmpty()) return;
+  Local<Context> context = v8_isolate->GetCurrentContext();
+  TryCatch try_catch(v8_isolate);
+  Local<String> str;
+  if (!obj->ToString(context).ToLocal(&str)) return;
   length_ = str->Length();
   str_ = i::NewArray<uint16_t>(length_ + 1);
   str->Write(str_);
@@ -6929,51 +7687,51 @@
 }
 
 
-#define DEFINE_ERROR(NAME)                                                    \
-  Local<Value> Exception::NAME(v8::Handle<v8::String> raw_message) {          \
-    i::Isolate* isolate = i::Isolate::Current();                              \
-    LOG_API(isolate, #NAME);                                                  \
-    ON_BAILOUT(isolate, "v8::Exception::" #NAME "()", return Local<Value>()); \
-    ENTER_V8(isolate);                                                        \
-    i::Object* error;                                                         \
-    {                                                                         \
-      i::HandleScope scope(isolate);                                          \
-      i::Handle<i::String> message = Utils::OpenHandle(*raw_message);         \
-      i::Handle<i::Object> result;                                            \
-      EXCEPTION_PREAMBLE(isolate);                                            \
-      i::MaybeHandle<i::Object> maybe_result =                                \
-          isolate->factory()->New##NAME(message);                             \
-      has_pending_exception = !maybe_result.ToHandle(&result);                \
-      /* TODO(yangguo): crbug/403509. Return empty handle instead. */         \
-      EXCEPTION_BAILOUT_CHECK(                                                \
-          isolate, v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)));   \
-      error = *result;                                                        \
-    }                                                                         \
-    i::Handle<i::Object> result(error, isolate);                              \
-    return Utils::ToLocal(result);                                            \
+#define DEFINE_ERROR(NAME, name)                                         \
+  Local<Value> Exception::NAME(v8::Local<v8::String> raw_message) {      \
+    i::Isolate* isolate = i::Isolate::Current();                         \
+    LOG_API(isolate, #NAME);                                             \
+    ENTER_V8(isolate);                                                   \
+    i::Object* error;                                                    \
+    {                                                                    \
+      i::HandleScope scope(isolate);                                     \
+      i::Handle<i::String> message = Utils::OpenHandle(*raw_message);    \
+      i::Handle<i::JSFunction> constructor = isolate->name##_function(); \
+      error = *isolate->factory()->NewError(constructor, message);       \
+    }                                                                    \
+    i::Handle<i::Object> result(error, isolate);                         \
+    return Utils::ToLocal(result);                                       \
   }
 
-DEFINE_ERROR(RangeError)
-DEFINE_ERROR(ReferenceError)
-DEFINE_ERROR(SyntaxError)
-DEFINE_ERROR(TypeError)
-DEFINE_ERROR(Error)
+DEFINE_ERROR(RangeError, range_error)
+DEFINE_ERROR(ReferenceError, reference_error)
+DEFINE_ERROR(SyntaxError, syntax_error)
+DEFINE_ERROR(TypeError, type_error)
+DEFINE_ERROR(Error, error)
 
 #undef DEFINE_ERROR
 
 
-Local<Message> Exception::CreateMessage(Handle<Value> exception) {
+Local<Message> Exception::CreateMessage(Isolate* isolate,
+                                        Local<Value> exception) {
   i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
-  if (!obj->IsHeapObject()) return Local<Message>();
-  i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  i::HandleScope scope(i_isolate);
   return Utils::MessageToLocal(
-      scope.CloseAndEscape(isolate->CreateMessage(obj, NULL)));
+      scope.CloseAndEscape(i_isolate->CreateMessage(obj, NULL)));
 }
 
 
-Local<StackTrace> Exception::GetStackTrace(Handle<Value> exception) {
+Local<Message> Exception::CreateMessage(Local<Value> exception) {
+  i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
+  if (!obj->IsHeapObject()) return Local<Message>();
+  i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
+  return CreateMessage(reinterpret_cast<Isolate*>(isolate), exception);
+}
+
+
+Local<StackTrace> Exception::GetStackTrace(Local<Value> exception) {
   i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
   if (!obj->IsJSObject()) return Local<StackTrace>();
   i::Handle<i::JSObject> js_obj = i::Handle<i::JSObject>::cast(obj);
@@ -6985,21 +7743,26 @@
 
 // --- D e b u g   S u p p o r t ---
 
-bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
-  i::Isolate* isolate = i::Isolate::Current();
-  ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::Object> foreign = isolate->factory()->undefined_value();
+bool Debug::SetDebugEventListener(Isolate* isolate, EventCallback that,
+                                  Local<Value> data) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  i::HandleScope scope(i_isolate);
+  i::Handle<i::Object> foreign = i_isolate->factory()->undefined_value();
   if (that != NULL) {
-    foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that));
+    foreign = i_isolate->factory()->NewForeign(FUNCTION_ADDR(that));
   }
-  isolate->debug()->SetEventListener(foreign,
-                                     Utils::OpenHandle(*data, true));
+  i_isolate->debug()->SetEventListener(foreign, Utils::OpenHandle(*data, true));
   return true;
 }
 
 
+bool Debug::SetDebugEventListener(EventCallback that, Local<Value> data) {
+  return SetDebugEventListener(
+      reinterpret_cast<Isolate*>(i::Isolate::Current()), that, data);
+}
+
+
 void Debug::DebugBreak(Isolate* isolate) {
   reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
 }
@@ -7017,16 +7780,16 @@
 }
 
 
-void Debug::DebugBreakForCommand(Isolate* isolate, ClientData* data) {
-  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  internal_isolate->debug()->EnqueueDebugCommand(data);
+void Debug::SetMessageHandler(Isolate* isolate,
+                              v8::Debug::MessageHandler handler) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  i_isolate->debug()->SetMessageHandler(handler);
 }
 
 
 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
-  i::Isolate* isolate = i::Isolate::Current();
-  ENTER_V8(isolate);
-  isolate->debug()->SetMessageHandler(handler);
+  SetMessageHandler(reinterpret_cast<Isolate*>(i::Isolate::Current()), handler);
 }
 
 
@@ -7040,64 +7803,77 @@
 }
 
 
-Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
-                         v8::Handle<v8::Value> data) {
-  i::Isolate* isolate = i::Isolate::Current();
-  ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
-  ENTER_V8(isolate);
-  i::MaybeHandle<i::Object> maybe_result;
-  EXCEPTION_PREAMBLE(isolate);
+MaybeLocal<Value> Debug::Call(Local<Context> context,
+                              v8::Local<v8::Function> fun,
+                              v8::Local<v8::Value> data) {
+  PREPARE_FOR_EXECUTION(context, "v8::Debug::Call()", Value);
+  i::Handle<i::Object> data_obj;
   if (data.IsEmpty()) {
-    maybe_result = isolate->debug()->Call(
-        Utils::OpenHandle(*fun), isolate->factory()->undefined_value());
+    data_obj = isolate->factory()->undefined_value();
   } else {
-    maybe_result = isolate->debug()->Call(
-        Utils::OpenHandle(*fun), Utils::OpenHandle(*data));
+    data_obj = Utils::OpenHandle(*data);
   }
-  i::Handle<i::Object> result;
-  has_pending_exception = !maybe_result.ToHandle(&result);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
-  return Utils::ToLocal(result);
+  Local<Value> result;
+  has_pending_exception =
+      !ToLocal<Value>(isolate->debug()->Call(Utils::OpenHandle(*fun), data_obj),
+                      &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
 }
 
 
-Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
-  i::Isolate* isolate = i::Isolate::Current();
-  ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
-  ENTER_V8(isolate);
-  v8::EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
+Local<Value> Debug::Call(v8::Local<v8::Function> fun,
+                         v8::Local<v8::Value> data) {
+  auto context = ContextFromHeapObject(Utils::OpenHandle(*fun));
+  RETURN_TO_LOCAL_UNCHECKED(Call(context, fun, data), Value);
+}
+
+
+MaybeLocal<Value> Debug::GetMirror(Local<Context> context,
+                                   v8::Local<v8::Value> obj) {
+  PREPARE_FOR_EXECUTION(context, "v8::Debug::GetMirror()", Value);
   i::Debug* isolate_debug = isolate->debug();
-  EXCEPTION_PREAMBLE(isolate);
   has_pending_exception = !isolate_debug->Load();
-  v8::Local<v8::Value> result;
-  if (!has_pending_exception) {
-    i::Handle<i::JSObject> debug(
-        isolate_debug->debug_context()->global_object());
-    i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
-        STATIC_CHAR_VECTOR("MakeMirror"));
-    i::Handle<i::Object> fun_obj =
-        i::Object::GetProperty(debug, name).ToHandleChecked();
-    i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
-    v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
-    const int kArgc = 1;
-    v8::Handle<v8::Value> argv[kArgc] = { obj };
-    result = v8_fun->Call(Utils::ToLocal(debug), kArgc, argv);
-    has_pending_exception = result.IsEmpty();
-  }
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
-  return scope.Escape(result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object());
+  auto name = isolate->factory()->NewStringFromStaticChars("MakeMirror");
+  auto fun_obj = i::Object::GetProperty(debug, name).ToHandleChecked();
+  auto v8_fun = Utils::CallableToLocal(i::Handle<i::JSFunction>::cast(fun_obj));
+  const int kArgc = 1;
+  v8::Local<v8::Value> argv[kArgc] = {obj};
+  Local<Value> result;
+  has_pending_exception =
+      !v8_fun->Call(context, Utils::ToLocal(debug), kArgc, argv)
+           .ToLocal(&result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
+}
+
+
+Local<Value> Debug::GetMirror(v8::Local<v8::Value> obj) {
+  RETURN_TO_LOCAL_UNCHECKED(GetMirror(Local<Context>(), obj), Value);
+}
+
+
+void Debug::ProcessDebugMessages(Isolate* isolate) {
+  reinterpret_cast<i::Isolate*>(isolate)->debug()->ProcessDebugMessages(true);
 }
 
 
 void Debug::ProcessDebugMessages() {
-  i::Isolate::Current()->debug()->ProcessDebugMessages(true);
+  ProcessDebugMessages(reinterpret_cast<Isolate*>(i::Isolate::Current()));
+}
+
+
+Local<Context> Debug::GetDebugContext(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  return Utils::ToLocal(i_isolate->debug()->GetDebugContext());
 }
 
 
 Local<Context> Debug::GetDebugContext() {
-  i::Isolate* isolate = i::Isolate::Current();
-  ENTER_V8(isolate);
-  return Utils::ToLocal(i::Isolate::Current()->debug()->GetDebugContext());
+  return GetDebugContext(reinterpret_cast<Isolate*>(i::Isolate::Current()));
 }
 
 
@@ -7107,9 +7883,21 @@
 }
 
 
-Handle<String> CpuProfileNode::GetFunctionName() const {
-  i::Isolate* isolate = i::Isolate::Current();
+MaybeLocal<Array> Debug::GetInternalProperties(Isolate* v8_isolate,
+                                               Local<Value> value) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  ENTER_V8(isolate);
+  i::Handle<i::Object> val = Utils::OpenHandle(*value);
+  i::Handle<i::JSArray> result;
+  if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result))
+    return MaybeLocal<Array>();
+  return Utils::ToLocal(result);
+}
+
+
+Local<String> CpuProfileNode::GetFunctionName() const {
   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+  i::Isolate* isolate = node->isolate();
   const i::CodeEntry* entry = node->entry();
   i::Handle<i::String> name =
       isolate->factory()->InternalizeUtf8String(entry->name());
@@ -7132,9 +7920,9 @@
 }
 
 
-Handle<String> CpuProfileNode::GetScriptResourceName() const {
-  i::Isolate* isolate = i::Isolate::Current();
+Local<String> CpuProfileNode::GetScriptResourceName() const {
   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+  i::Isolate* isolate = node->isolate();
   return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
       node->entry()->resource_name()));
 }
@@ -7176,7 +7964,7 @@
 
 
 unsigned CpuProfileNode::GetCallUid() const {
-  return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
+  return reinterpret_cast<const i::ProfileNode*>(this)->function_id();
 }
 
 
@@ -7197,17 +7985,24 @@
 }
 
 
-void CpuProfile::Delete() {
-  i::Isolate* isolate = i::Isolate::Current();
-  i::CpuProfiler* profiler = isolate->cpu_profiler();
-  DCHECK(profiler != NULL);
-  profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
+const std::vector<CpuProfileDeoptInfo>& CpuProfileNode::GetDeoptInfos() const {
+  const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+  return node->deopt_infos();
 }
 
 
-Handle<String> CpuProfile::GetTitle() const {
-  i::Isolate* isolate = i::Isolate::Current();
+void CpuProfile::Delete() {
+  i::CpuProfile* profile = reinterpret_cast<i::CpuProfile*>(this);
+  i::Isolate* isolate = profile->top_down()->isolate();
+  i::CpuProfiler* profiler = isolate->cpu_profiler();
+  DCHECK(profiler != NULL);
+  profiler->DeleteProfile(profile);
+}
+
+
+Local<String> CpuProfile::GetTitle() const {
   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
+  i::Isolate* isolate = profile->top_down()->isolate();
   return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
       profile->title()));
 }
@@ -7250,35 +8045,25 @@
 
 
 void CpuProfiler::SetSamplingInterval(int us) {
-  DCHECK(us >= 0);
+  DCHECK_GE(us, 0);
   return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
       base::TimeDelta::FromMicroseconds(us));
 }
 
 
-void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
+void CpuProfiler::StartProfiling(Local<String> title, bool record_samples) {
   reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
       *Utils::OpenHandle(*title), record_samples);
 }
 
 
-void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) {
-  StartProfiling(title, record_samples);
-}
-
-
-CpuProfile* CpuProfiler::StopProfiling(Handle<String> title) {
+CpuProfile* CpuProfiler::StopProfiling(Local<String> title) {
   return reinterpret_cast<CpuProfile*>(
       reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
           *Utils::OpenHandle(*title)));
 }
 
 
-const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) {
-  return StopProfiling(title);
-}
-
-
 void CpuProfiler::SetIdle(bool is_idle) {
   i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
   v8::StateTag state = isolate->current_vm_state();
@@ -7303,9 +8088,9 @@
 }
 
 
-Handle<Value> HeapGraphEdge::GetName() const {
-  i::Isolate* isolate = i::Isolate::Current();
+Local<Value> HeapGraphEdge::GetName() const {
   i::HeapGraphEdge* edge = ToInternal(this);
+  i::Isolate* isolate = edge->isolate();
   switch (edge->type()) {
     case i::HeapGraphEdge::kContextVariable:
     case i::HeapGraphEdge::kInternal:
@@ -7347,8 +8132,8 @@
 }
 
 
-Handle<String> HeapGraphNode::GetName() const {
-  i::Isolate* isolate = i::Isolate::Current();
+Local<String> HeapGraphNode::GetName() const {
+  i::Isolate* isolate = ToInternal(this)->isolate();
   return ToApiHandle<String>(
       isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
 }
@@ -7359,13 +8144,6 @@
 }
 
 
-int HeapGraphNode::GetSelfSize() const {
-  size_t size = ToInternal(this)->self_size();
-  CHECK(size <= static_cast<size_t>(internal::kMaxInt));
-  return static_cast<int>(size);
-}
-
-
 size_t HeapGraphNode::GetShallowSize() const {
   return ToInternal(this)->self_size();
 }
@@ -7389,7 +8167,7 @@
 
 
 void HeapSnapshot::Delete() {
-  i::Isolate* isolate = i::Isolate::Current();
+  i::Isolate* isolate = ToInternal(this)->profiler()->isolate();
   if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
     ToInternal(this)->Delete();
   } else {
@@ -7399,18 +8177,6 @@
 }
 
 
-unsigned HeapSnapshot::GetUid() const {
-  return ToInternal(this)->uid();
-}
-
-
-Handle<String> HeapSnapshot::GetTitle() const {
-  i::Isolate* isolate = i::Isolate::Current();
-  return ToApiHandle<String>(
-      isolate->factory()->InternalizeUtf8String(ToInternal(this)->title()));
-}
-
-
 const HeapGraphNode* HeapSnapshot::GetRoot() const {
   return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
 }
@@ -7451,6 +8217,11 @@
 }
 
 
+// static
+STATIC_CONST_MEMBER_DEFINITION const SnapshotObjectId
+    HeapProfiler::kUnknownObjectId;
+
+
 int HeapProfiler::GetSnapshotCount() {
   return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
 }
@@ -7462,13 +8233,13 @@
 }
 
 
-SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) {
+SnapshotObjectId HeapProfiler::GetObjectId(Local<Value> value) {
   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
   return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
 }
 
 
-Handle<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
+Local<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
   i::Handle<i::Object> obj =
       reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
   if (obj.is_null()) return Local<Value>();
@@ -7482,12 +8253,10 @@
 
 
 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
-    Handle<String> title,
-    ActivityControl* control,
-    ObjectNameResolver* resolver) {
+    ActivityControl* control, ObjectNameResolver* resolver) {
   return reinterpret_cast<const HeapSnapshot*>(
-      reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
-          *Utils::OpenHandle(*title), control, resolver));
+      reinterpret_cast<i::HeapProfiler*>(this)
+          ->TakeSnapshot(control, resolver));
 }
 
 
@@ -7502,8 +8271,10 @@
 }
 
 
-SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
-  return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream);
+SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream,
+                                            int64_t* timestamp_us) {
+  i::HeapProfiler* heap_profiler = reinterpret_cast<i::HeapProfiler*>(this);
+  return heap_profiler->PushHeapObjectsStats(stream, timestamp_us);
 }
 
 
@@ -7592,11 +8363,10 @@
 }
 
 
-// TODO(svenpanne) Deprecate this.
-void Testing::DeoptimizeAll() {
-  i::Isolate* isolate = i::Isolate::Current();
-  i::HandleScope scope(isolate);
-  internal::Deoptimizer::DeoptimizeAll(isolate);
+void Testing::DeoptimizeAll(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::HandleScope scope(i_isolate);
+  internal::Deoptimizer::DeoptimizeAll(i_isolate);
 }
 
 
@@ -7769,4 +8539,5 @@
 }
 
 
-} }  // namespace v8::internal
+}  // namespace internal
+}  // namespace v8