Version 3.21.10

Fixed Eternal::IsEmpty logic (issue 2870).

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@16532 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 4b80555..c95def1 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -53,6 +53,7 @@
 #endif
 #include "parser.h"
 #include "platform.h"
+#include "platform/time.h"
 #include "profile-generator-inl.h"
 #include "property-details.h"
 #include "property.h"
@@ -1438,55 +1439,95 @@
 
 // Ensure that the object template has a constructor.  If no
 // constructor is available we create one.
-static void EnsureConstructor(ObjectTemplate* object_template) {
-  if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
-    Local<FunctionTemplate> templ = FunctionTemplate::New();
-    i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
-    constructor->set_instance_template(*Utils::OpenHandle(object_template));
-    Utils::OpenHandle(object_template)->set_constructor(*constructor);
+static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
+    ObjectTemplate* object_template) {
+  i::Object* obj = Utils::OpenHandle(object_template)->constructor();
+  if (!obj ->IsUndefined()) {
+    i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
+    return i::Handle<i::FunctionTemplateInfo>(info, info->GetIsolate());
   }
+  Local<FunctionTemplate> templ = FunctionTemplate::New();
+  i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
+  constructor->set_instance_template(*Utils::OpenHandle(object_template));
+  Utils::OpenHandle(object_template)->set_constructor(*constructor);
+  return constructor;
 }
 
 
-static inline void AddPropertyToFunctionTemplate(
-    i::Handle<i::FunctionTemplateInfo> cons,
+static inline void AddPropertyToTemplate(
+    i::Handle<i::TemplateInfo> info,
     i::Handle<i::AccessorInfo> obj) {
-  i::Handle<i::Object> list(cons->property_accessors(), cons->GetIsolate());
+  i::Handle<i::Object> list(info->property_accessors(), info->GetIsolate());
   if (list->IsUndefined()) {
     list = NeanderArray().value();
-    cons->set_property_accessors(*list);
+    info->set_property_accessors(*list);
   }
   NeanderArray array(list);
   array.add(obj);
 }
 
 
-template<typename Setter, typename Getter, typename Data>
-static bool ObjectTemplateSetAccessor(
-    ObjectTemplate* object_template,
-    v8::Handle<String> name,
+static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
+    Template* template_obj) {
+  return Utils::OpenHandle(template_obj);
+}
+
+
+// TODO(dcarney): remove this with ObjectTemplate::SetAccessor
+static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
+    ObjectTemplate* object_template) {
+  EnsureConstructor(object_template);
+  return Utils::OpenHandle(object_template);
+}
+
+
+template<typename Setter, typename Getter, typename Data, typename Template>
+static bool TemplateSetAccessor(
+    Template* template_obj,
+    v8::Local<String> name,
     Getter getter,
     Setter setter,
     Data data,
     AccessControl settings,
     PropertyAttribute attribute,
-    v8::Handle<AccessorSignature> signature) {
-  i::Isolate* isolate = Utils::OpenHandle(object_template)->GetIsolate();
+    v8::Local<AccessorSignature> signature) {
+  i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
   if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessor()")) return false;
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  EnsureConstructor(object_template);
-  i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
-      Utils::OpenHandle(object_template)->constructor());
-  i::Handle<i::FunctionTemplateInfo> cons(constructor);
   i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
       name, getter, setter, data, settings, attribute, signature);
   if (obj.is_null()) return false;
-  AddPropertyToFunctionTemplate(cons, obj);
+  i::Handle<i::TemplateInfo> info = GetTemplateInfo(template_obj);
+  AddPropertyToTemplate(info, obj);
   return true;
 }
 
 
+bool Template::SetDeclaredAccessor(
+    Local<String> 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,
+                                     PropertyAttribute attribute,
+                                     v8::Local<AccessorSignature> signature,
+                                     AccessControl settings) {
+  TemplateSetAccessor(
+      this, name, getter, setter, data, settings, attribute, signature);
+}
+
+
 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
                                  AccessorGetterCallback getter,
                                  AccessorSetterCallback setter,
@@ -1494,22 +1535,11 @@
                                  AccessControl settings,
                                  PropertyAttribute attribute,
                                  v8::Handle<AccessorSignature> signature) {
-  ObjectTemplateSetAccessor(
+  TemplateSetAccessor(
       this, name, getter, setter, data, settings, attribute, signature);
 }
 
 
-bool ObjectTemplate::SetAccessor(Handle<String> name,
-                                 Handle<DeclaredAccessorDescriptor> descriptor,
-                                 AccessControl settings,
-                                 PropertyAttribute attribute,
-                                 Handle<AccessorSignature> signature) {
-  void* null = NULL;
-  return ObjectTemplateSetAccessor(
-      this, name, descriptor, null, null, settings, attribute, signature);
-}
-
-
 void ObjectTemplate::SetNamedPropertyHandler(
     NamedPropertyGetterCallback getter,
     NamedPropertySetterCallback setter,
@@ -1683,19 +1713,20 @@
 ScriptData* ScriptData::PreCompile(const char* input, int length) {
   i::Utf8ToUtf16CharacterStream stream(
       reinterpret_cast<const unsigned char*>(input), length);
-  return i::PreParserApi::PreParse(&stream);
+  return i::PreParserApi::PreParse(i::Isolate::Current(), &stream);
 }
 
 
 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
   i::Handle<i::String> str = Utils::OpenHandle(*source);
+  i::Isolate* isolate = str->GetIsolate();
   if (str->IsExternalTwoByteString()) {
     i::ExternalTwoByteStringUtf16CharacterStream stream(
       i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
-    return i::PreParserApi::PreParse(&stream);
+    return i::PreParserApi::PreParse(isolate, &stream);
   } else {
     i::GenericStringUtf16CharacterStream stream(str, 0, str->length());
-    return i::PreParserApi::PreParse(&stream);
+    return i::PreParserApi::PreParse(isolate, &stream);
   }
 }
 
@@ -2289,7 +2320,7 @@
   ENTER_V8(isolate);
   HandleScope scope(reinterpret_cast<Isolate*>(isolate));
   i::Handle<i::JSArray> self = Utils::OpenHandle(this);
-  i::Object* raw_object = self->GetElementNoExceptionThrown(index);
+  i::Object* raw_object = self->GetElementNoExceptionThrown(isolate, index);
   i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
   return scope.Close(Utils::StackFrameToLocal(obj));
 }
@@ -3362,7 +3393,7 @@
   ENTER_V8(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   EXCEPTION_PREAMBLE(isolate);
-  i::Handle<i::Object> result = i::Object::GetElement(self, index);
+  i::Handle<i::Object> result = i::Object::GetElement(isolate, self, index);
   has_pending_exception = result.is_null();
   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
   return Utils::ToLocal(result);
@@ -3637,10 +3668,10 @@
 }
 
 
-bool Object::SetAccessor(Handle<String> name,
-                         Handle<DeclaredAccessorDescriptor> descriptor,
-                         AccessControl settings,
-                         PropertyAttribute attributes) {
+bool Object::SetDeclaredAccessor(Local<String> name,
+                                 Local<DeclaredAccessorDescriptor> descriptor,
+                                 PropertyAttribute attributes,
+                                 AccessControl settings) {
   void* null = NULL;
   return ObjectSetAccessor(
       this, name, descriptor, null, null, settings, attributes);
@@ -5285,7 +5316,8 @@
   // continue to call IdleNotification.
   i::Isolate* isolate = i::Isolate::Current();
   if (isolate == NULL || !isolate->IsInitialized()) return true;
-  return i::V8::IdleNotification(hint);
+  if (!i::FLAG_use_idle_notification) return true;
+  return isolate->heap()->IdleNotification(hint);
 }
 
 
@@ -5313,18 +5345,6 @@
 }
 
 
-static i::Handle<i::FunctionTemplateInfo>
-    EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
-  if (templ->constructor()->IsUndefined()) {
-    Local<FunctionTemplate> constructor = FunctionTemplate::New();
-    Utils::OpenHandle(*constructor)->set_instance_template(*templ);
-    templ->set_constructor(*Utils::OpenHandle(*constructor));
-  }
-  return i::Handle<i::FunctionTemplateInfo>(
-    i::FunctionTemplateInfo::cast(templ->constructor()));
-}
-
-
 static i::Handle<i::Context> CreateEnvironment(
     i::Isolate* isolate,
     v8::ExtensionConfiguration* extensions,
@@ -5341,13 +5361,11 @@
 
     if (!global_template.IsEmpty()) {
       // Make sure that the global_template has a constructor.
-      global_constructor =
-          EnsureConstructor(Utils::OpenHandle(*global_template));
+      global_constructor = EnsureConstructor(*global_template);
 
       // Create a fresh template for the global proxy object.
       proxy_template = ObjectTemplate::New();
-      proxy_constructor =
-          EnsureConstructor(Utils::OpenHandle(*proxy_template));
+      proxy_constructor = EnsureConstructor(*proxy_template);
 
       // Set the global template to be the prototype template of
       // global proxy template.
@@ -7332,6 +7350,13 @@
 }
 
 
+void CpuProfiler::SetSamplingInterval(int us) {
+  ASSERT(us >= 0);
+  return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
+      i::TimeDelta::FromMicroseconds(us));
+}
+
+
 const CpuProfile* CpuProfiler::GetCpuProfile(int index) {
   return reinterpret_cast<const CpuProfile*>(
       reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(index));
diff --git a/src/assembler.cc b/src/assembler.cc
index a9587f3..44d5f22 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -798,7 +798,7 @@
     target_object()->ShortPrint(out);
     PrintF(out, ")");
   } else if (rmode_ == EXTERNAL_REFERENCE) {
-    ExternalReferenceEncoder ref_encoder;
+    ExternalReferenceEncoder ref_encoder(isolate);
     PrintF(out, " (%s)  (%p)",
            ref_encoder.NameOfAddress(*target_reference_address()),
            *target_reference_address());
diff --git a/src/ast.h b/src/ast.h
index f22c96c..0f01a3e 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -2038,7 +2038,8 @@
         op_(op),
         left_(left),
         right_(right),
-        pos_(pos) {
+        pos_(pos),
+        combined_type_(Type::Null(), isolate) {
     ASSERT(Token::IsCompareOp(op));
   }
 
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index ace134b..b7991d3 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -2604,7 +2604,7 @@
   // We can only de-serialize a context if the isolate was initialized from
   // a snapshot. Otherwise we have to build the context from scratch.
   if (isolate->initialized_from_snapshot()) {
-    native_context_ = Snapshot::NewContextFromSnapshot();
+    native_context_ = Snapshot::NewContextFromSnapshot(isolate);
   } else {
     native_context_ = Handle<Context>();
   }
diff --git a/src/builtins.cc b/src/builtins.cc
index fea503b..b481483 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -594,7 +594,7 @@
   if (accessor->HasElement(array, array, new_length, elms_obj)) {
     maybe_result = accessor->Get(array, array, new_length, elms_obj);
   } else {
-    maybe_result = array->GetPrototype()->GetElement(len - 1);
+    maybe_result = array->GetPrototype()->GetElement(isolate, len - 1);
   }
   if (maybe_result->IsFailure()) return maybe_result;
   MaybeObject* maybe_failure =
@@ -1461,6 +1461,16 @@
 }
 
 
+static void Generate_StoreIC_PreMonomorphic(MacroAssembler* masm) {
+  StoreIC::GeneratePreMonomorphic(masm);
+}
+
+
+static void Generate_StoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
+  StoreIC::GeneratePreMonomorphic(masm);
+}
+
+
 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
   StoreIC::GenerateMiss(masm);
 }
@@ -1546,6 +1556,16 @@
 }
 
 
+static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
+  KeyedStoreIC::GeneratePreMonomorphic(masm);
+}
+
+
+static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
+  KeyedStoreIC::GeneratePreMonomorphic(masm);
+}
+
+
 static void Generate_KeyedStoreIC_NonStrictArguments(MacroAssembler* masm) {
   KeyedStoreIC::GenerateNonStrictArguments(masm);
 }
diff --git a/src/builtins.h b/src/builtins.h
index b7be785..cbfa1d7 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -162,6 +162,8 @@
                                                                         \
   V(StoreIC_Initialize,             STORE_IC, UNINITIALIZED,            \
                                     Code::kNoExtraICState)              \
+  V(StoreIC_PreMonomorphic,         STORE_IC, PREMONOMORPHIC,           \
+                                    Code::kNoExtraICState)              \
   V(StoreIC_Normal,                 STORE_IC, MONOMORPHIC,              \
                                     Code::kNoExtraICState)              \
   V(StoreIC_Megamorphic,            STORE_IC, MEGAMORPHIC,              \
@@ -174,6 +176,8 @@
                                     Code::kNoExtraICState)              \
   V(StoreIC_Initialize_Strict,      STORE_IC, UNINITIALIZED,            \
                                     kStrictMode)                        \
+  V(StoreIC_PreMonomorphic_Strict,  STORE_IC, PREMONOMORPHIC,           \
+                                    kStrictMode)                        \
   V(StoreIC_Normal_Strict,          STORE_IC, MONOMORPHIC,              \
                                     kStrictMode)                        \
   V(StoreIC_Megamorphic_Strict,     STORE_IC, MEGAMORPHIC,              \
@@ -185,11 +189,15 @@
                                                                         \
   V(KeyedStoreIC_Initialize,        KEYED_STORE_IC, UNINITIALIZED,      \
                                     Code::kNoExtraICState)              \
+  V(KeyedStoreIC_PreMonomorphic,    KEYED_STORE_IC, PREMONOMORPHIC,     \
+                                    Code::kNoExtraICState)              \
   V(KeyedStoreIC_Generic,           KEYED_STORE_IC, GENERIC,            \
                                     Code::kNoExtraICState)              \
                                                                         \
   V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED,      \
                                     kStrictMode)                        \
+  V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC, PREMONOMORPHIC, \
+                                    kStrictMode)                        \
   V(KeyedStoreIC_Generic_Strict,    KEYED_STORE_IC, GENERIC,            \
                                     kStrictMode)                        \
   V(KeyedStoreIC_NonStrictArguments, KEYED_STORE_IC, MONOMORPHIC,       \
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 131fe31..23d4269 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -888,8 +888,7 @@
 
   if (FLAG_trace_elements_transitions) {
     // Tracing elements transitions is the job of the runtime.
-    Add<HDeoptimize>("Deopt due to --trace-elements-transitions",
-                     Deoptimizer::EAGER);
+    Add<HDeoptimize>("Tracing elements transitions", Deoptimizer::EAGER);
   } else {
     info()->MarkAsSavesCallerDoubles();
 
diff --git a/src/compiler.cc b/src/compiler.cc
index bc65b1f..2bf012e 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -58,7 +58,8 @@
                                  Zone* zone)
     : flags_(LanguageModeField::encode(CLASSIC_MODE)),
       script_(script),
-      osr_ast_id_(BailoutId::None()) {
+      osr_ast_id_(BailoutId::None()),
+      osr_pc_offset_(0) {
   Initialize(script->GetIsolate(), BASE, zone);
 }
 
@@ -68,7 +69,8 @@
     : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
       shared_info_(shared_info),
       script_(Handle<Script>(Script::cast(shared_info->script()))),
-      osr_ast_id_(BailoutId::None()) {
+      osr_ast_id_(BailoutId::None()),
+      osr_pc_offset_(0) {
   Initialize(script_->GetIsolate(), BASE, zone);
 }
 
@@ -80,7 +82,8 @@
       shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
       script_(Handle<Script>(Script::cast(shared_info_->script()))),
       context_(closure->context()),
-      osr_ast_id_(BailoutId::None()) {
+      osr_ast_id_(BailoutId::None()),
+      osr_pc_offset_(0) {
   Initialize(script_->GetIsolate(), BASE, zone);
 }
 
@@ -90,7 +93,8 @@
                                  Zone* zone)
     : flags_(LanguageModeField::encode(CLASSIC_MODE) |
              IsLazy::encode(true)),
-      osr_ast_id_(BailoutId::None()) {
+      osr_ast_id_(BailoutId::None()),
+      osr_pc_offset_(0) {
   Initialize(isolate, STUB, zone);
   code_stub_ = stub;
 }
@@ -494,6 +498,8 @@
     info()->SetCode(optimized_code);
   }
   RecordOptimizationStats();
+  // Add to the weak list of optimized code objects.
+  info()->context()->native_context()->AddOptimizedCode(*info()->code());
   return SetLastStatus(SUCCEEDED);
 }
 
@@ -875,9 +881,10 @@
 
 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
   Handle<Code> code = info->code();
-  if (FLAG_cache_optimized_code &&
-      info->osr_ast_id().IsNone() &&
-      code->kind() == Code::OPTIMIZED_FUNCTION) {
+  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;  // Nothing to do.
+
+  // Cache non-OSR optimized code.
+  if (FLAG_cache_optimized_code && info->osr_ast_id().IsNone()) {
     Handle<JSFunction> function = info->closure();
     Handle<SharedFunctionInfo> shared(function->shared());
     Handle<FixedArray> literals(function->literals());
@@ -889,9 +896,10 @@
 
 
 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) {
-  if (FLAG_cache_optimized_code &&
-      info->osr_ast_id().IsNone() &&
-      info->IsOptimizing()) {
+  if (!info->IsOptimizing()) return false;  // Nothing to look up.
+
+  // Lookup non-OSR optimized code.
+  if (FLAG_cache_optimized_code && info->osr_ast_id().IsNone()) {
     Handle<SharedFunctionInfo> shared = info->shared_info();
     Handle<JSFunction> function = info->closure();
     ASSERT(!function.is_null());
@@ -963,8 +971,9 @@
 }
 
 
-void Compiler::RecompileConcurrent(Handle<JSFunction> closure) {
-  ASSERT(closure->IsMarkedForConcurrentRecompilation());
+bool Compiler::RecompileConcurrent(Handle<JSFunction> closure,
+                                   uint32_t osr_pc_offset) {
+  bool compiling_for_osr = (osr_pc_offset != 0);
 
   Isolate* isolate = closure->GetIsolate();
   // Here we prepare compile data for the concurrent recompilation thread, but
@@ -978,23 +987,39 @@
       closure->PrintName();
       PrintF(" on next run.\n");
     }
-    return;
+    return false;
   }
 
   SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure));
+  Handle<SharedFunctionInfo> shared = info->shared_info();
+
+  if (compiling_for_osr) {
+    BailoutId osr_ast_id =
+        shared->code()->TranslatePcOffsetToAstId(osr_pc_offset);
+    ASSERT(!osr_ast_id.IsNone());
+    info->SetOptimizing(osr_ast_id);
+    info->set_osr_pc_offset(osr_pc_offset);
+
+    if (FLAG_trace_osr) {
+      PrintF("[COSR - attempt to queue ");
+      closure->PrintName();
+      PrintF(" at AST id %d]\n", osr_ast_id.ToInt());
+    }
+  } else {
+    info->SetOptimizing(BailoutId::None());
+  }
+
   VMState<COMPILER> state(isolate);
   PostponeInterruptsScope postpone(isolate);
 
-  Handle<SharedFunctionInfo> shared = info->shared_info();
   int compiled_size = shared->end_position() - shared->start_position();
   isolate->counters()->total_compile_size()->Increment(compiled_size);
-  info->SetOptimizing(BailoutId::None());
 
   {
     CompilationHandleScope handle_scope(*info);
 
-    if (InstallCodeFromOptimizedCodeMap(*info)) {
-      return;
+    if (!compiling_for_osr && InstallCodeFromOptimizedCodeMap(*info)) {
+      return true;
     }
 
     if (Parser::Parse(*info)) {
@@ -1011,6 +1036,8 @@
           info.Detach();
           shared->code()->set_profiler_ticks(0);
           isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
+          ASSERT(!isolate->has_pending_exception());
+          return true;
         } else if (status == OptimizingCompiler::BAILED_OUT) {
           isolate->clear_pending_exception();
           InstallFullCode(*info);
@@ -1019,19 +1046,12 @@
     }
   }
 
-  if (shared->code()->back_edges_patched_for_osr()) {
-    // At this point we either put the function on recompilation queue or
-    // aborted optimization.  In either case we want to continue executing
-    // the unoptimized code without running into OSR.  If the unoptimized
-    // code has been patched for OSR, unpatch it.
-    Deoptimizer::RevertInterruptCode(isolate, shared->code());
-  }
-
   if (isolate->has_pending_exception()) isolate->clear_pending_exception();
+  return false;
 }
 
 
-void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
+bool Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
   SmartPointer<CompilationInfo> info(optimizing_compiler->info());
   // The function may have already been optimized by OSR.  Simply continue.
   // Except when OSR already disabled optimization for some reason.
@@ -1044,7 +1064,7 @@
       PrintF(" as it has been disabled.\n");
     }
     ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
-    return;
+    return false;
   }
 
   Isolate* isolate = info->isolate();
@@ -1091,6 +1111,168 @@
   // profiler ticks to prevent too soon re-opt after a deopt.
   info->shared_info()->code()->set_profiler_ticks(0);
   ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
+  return status == OptimizingCompiler::SUCCEEDED;
+}
+
+
+static uint32_t CurrentPcOffset(Isolate* isolate,
+                                Handle<JSFunction> function,
+                                Handle<Code> unoptimized) {
+  JavaScriptFrameIterator it(isolate);
+  JavaScriptFrame* frame = it.frame();
+  ASSERT(frame->function() == *function);
+  ASSERT(frame->LookupCode() == *unoptimized);
+  ASSERT(unoptimized->contains(frame->pc()));
+
+  // Use linear search of the unoptimized code's back edge table to find
+  // the AST id matching the PC.
+  return static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
+}
+
+
+static bool IsSuitableForOnStackReplacement(Isolate* isolate,
+                                            Handle<JSFunction> function,
+                                            Handle<Code> unoptimized) {
+  // Keep track of whether we've succeeded in optimizing.
+  if (!unoptimized->optimizable()) return false;
+  // If we are trying to do OSR when there are already optimized
+  // activations of the function, it means (a) the function is directly or
+  // indirectly recursive and (b) an optimized invocation has been
+  // deoptimized so that we are currently in an unoptimized activation.
+  // Check for optimized activations of this function.
+  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
+    JavaScriptFrame* frame = it.frame();
+    if (frame->is_optimized() && frame->function() == *function) return false;
+  }
+
+  return true;
+}
+
+
+BailoutId Compiler::CompileForOnStackReplacement(Handle<JSFunction> function) {
+  Isolate* isolate = function->GetIsolate();
+  // We have hit a back edge in an unoptimized frame for a function that was
+  // selected for on-stack replacement.  Find the unoptimized code object.
+  Handle<Code> unoptimized(function->shared()->code(), isolate);
+
+  Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
+  if (FLAG_trace_osr) {
+    PrintF("[OSR - restored original interrupt calls in ");
+    function->PrintName();
+    PrintF("]\n");
+  }
+
+  if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
+    return BailoutId::None();
+  }
+
+  uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized);
+
+  BailoutId ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset);
+  ASSERT(!ast_id.IsNone());
+  if (FLAG_trace_osr) {
+    PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt());
+    function->PrintName();
+    PrintF("]\n");
+  }
+
+  // Try to compile the optimized code.  A true return value from
+  // CompileOptimized means that compilation succeeded, not necessarily
+  // that optimization succeeded.
+  if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
+      function->IsOptimized()) {
+    DeoptimizationInputData* data = DeoptimizationInputData::cast(
+        function->code()->deoptimization_data());
+    if (data->OsrPcOffset()->value() >= 0) {
+      if (FLAG_trace_osr) {
+        PrintF("[OSR - entry, offset %d in optimized code]\n",
+            data->OsrPcOffset()->value());
+      }
+      ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
+      return ast_id;
+    }
+  } else {
+    if (FLAG_trace_osr) {
+      PrintF("[OSR - optimization failed for ");
+      function->PrintName();
+      PrintF("]\n");
+    }
+  }
+  return BailoutId::None();
+}
+
+
+BailoutId Compiler::CompileForConcurrentOSR(Handle<JSFunction> function) {
+  Isolate* isolate = function->GetIsolate();
+  Handle<Code> unoptimized(function->shared()->code(), isolate);
+
+  uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized);
+
+  if (isolate->optimizing_compiler_thread()->
+          IsQueuedForOSR(function, pc_offset)) {
+    // Still waiting for the optimizing compiler thread to finish.  Carry on.
+    if (FLAG_trace_osr) {
+      PrintF("[COSR - polling recompile tasks for ");
+      function->PrintName();
+      PrintF("]\n");
+    }
+    return BailoutId::None();
+  }
+
+  OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()->
+                                     FindReadyOSRCandidate(function, pc_offset);
+
+  if (compiler != NULL) {
+    if (FLAG_trace_osr) {
+      PrintF("[COSR - optimization complete for ");
+      function->PrintName();
+      PrintF(", restoring interrupt calls]\n");
+    }
+    Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
+
+    BailoutId ast_id = compiler->info()->osr_ast_id();
+
+    bool succeeded = InstallOptimizedCode(compiler);
+
+    isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates();
+
+    if (!succeeded) {
+      if (FLAG_trace_osr) {
+        PrintF("[COSR - optimization failed for ");
+        function->PrintName();
+        PrintF("]\n");
+      }
+      return BailoutId::None();
+    }
+
+    DeoptimizationInputData* data = DeoptimizationInputData::cast(
+        function->code()->deoptimization_data());
+
+    if (data->OsrPcOffset()->value() >= 0) {
+      ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
+      if (FLAG_trace_osr) {
+        PrintF("[COSR - entry at AST id %d, offset %d in optimized code]\n",
+               ast_id.ToInt(), data->OsrPcOffset()->value());
+      }
+      return ast_id;
+    }
+    return BailoutId::None();
+  }
+
+  if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
+    if (FLAG_trace_osr) {
+      PrintF("[COSR - ");
+      function->PrintName();
+      PrintF(" is unsuitable, restoring interrupt calls]\n");
+    }
+    Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
+    return BailoutId::None();
+  }
+
+  if (!RecompileConcurrent(function, pc_offset)) {
+    Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
+  }
+  return BailoutId::None();
 }
 
 
diff --git a/src/compiler.h b/src/compiler.h
index 4f6a472..98b93d3 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -308,6 +308,14 @@
     return abort_due_to_dependency_;
   }
 
+  void set_osr_pc_offset(uint32_t pc_offset) {
+    osr_pc_offset_ = pc_offset;
+  }
+
+  bool HasSameOsrEntry(Handle<JSFunction> function, uint32_t pc_offset) {
+    return osr_pc_offset_ == pc_offset && function.is_identical_to(closure_);
+  }
+
  protected:
   CompilationInfo(Handle<Script> script,
                   Zone* zone);
@@ -402,6 +410,9 @@
   // Compilation mode flag and whether deoptimization is allowed.
   Mode mode_;
   BailoutId osr_ast_id_;
+  // The pc_offset corresponding to osr_ast_id_ in unoptimized code.
+  // We can look this up in the back edge table, but cache it for quick access.
+  uint32_t osr_pc_offset_;
 
   // Flag whether compilation needs to be aborted due to dependency change.
   bool abort_due_to_dependency_;
@@ -600,7 +611,8 @@
   // success and false if the compilation resulted in a stack overflow.
   static bool CompileLazy(CompilationInfo* info);
 
-  static void RecompileConcurrent(Handle<JSFunction> function);
+  static bool RecompileConcurrent(Handle<JSFunction> function,
+                                  uint32_t osr_pc_offset = 0);
 
   // Compile a shared function info object (the function is possibly lazily
   // compiled).
@@ -613,7 +625,11 @@
                               bool is_toplevel,
                               Handle<Script> script);
 
-  static void InstallOptimizedCode(OptimizingCompiler* info);
+  static bool InstallOptimizedCode(OptimizingCompiler* info);
+
+  static BailoutId CompileForOnStackReplacement(Handle<JSFunction> function);
+
+  static BailoutId CompileForConcurrentOSR(Handle<JSFunction> function);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   static bool MakeCodeForLiveEdit(CompilationInfo* info);
diff --git a/src/contexts.cc b/src/contexts.cc
index 5981fd6..441ef9d 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -319,14 +319,48 @@
 }
 
 
+void Context::SetOptimizedFunctionsListHead(Object* head) {
+  ASSERT(IsNativeContext());
+  set(OPTIMIZED_FUNCTIONS_LIST, head);
+}
+
+
 Object* Context::OptimizedFunctionsListHead() {
   ASSERT(IsNativeContext());
   return get(OPTIMIZED_FUNCTIONS_LIST);
 }
 
 
-void Context::ClearOptimizedFunctions() {
-  set(OPTIMIZED_FUNCTIONS_LIST, GetHeap()->undefined_value());
+void Context::AddOptimizedCode(Code* code) {
+  ASSERT(IsNativeContext());
+  ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+  ASSERT(code->next_code_link()->IsUndefined());
+  code->set_next_code_link(get(OPTIMIZED_CODE_LIST));
+  set(OPTIMIZED_CODE_LIST, code);
+}
+
+
+void Context::SetOptimizedCodeListHead(Object* head) {
+  ASSERT(IsNativeContext());
+  set(OPTIMIZED_CODE_LIST, head);
+}
+
+
+Object* Context::OptimizedCodeListHead() {
+  ASSERT(IsNativeContext());
+  return get(OPTIMIZED_CODE_LIST);
+}
+
+
+void Context::SetDeoptimizedCodeListHead(Object* head) {
+  ASSERT(IsNativeContext());
+  set(DEOPTIMIZED_CODE_LIST, head);
+}
+
+
+Object* Context::DeoptimizedCodeListHead() {
+  ASSERT(IsNativeContext());
+  return get(DEOPTIMIZED_CODE_LIST);
 }
 
 
diff --git a/src/contexts.h b/src/contexts.h
index 88c3cd9..189c215 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -337,8 +337,10 @@
     // Properties from here are treated as weak references by the full GC.
     // Scavenge treats them as strong references.
     OPTIMIZED_FUNCTIONS_LIST,  // Weak.
-    MAP_CACHE_INDEX,  // Weak.
-    NEXT_CONTEXT_LINK,  // Weak.
+    OPTIMIZED_CODE_LIST,       // Weak.
+    DEOPTIMIZED_CODE_LIST,     // Weak.
+    MAP_CACHE_INDEX,           // Weak.
+    NEXT_CONTEXT_LINK,         // Weak.
 
     // Total number of slots.
     NATIVE_CONTEXT_SLOTS,
@@ -428,11 +430,19 @@
   // Mark the native context with out of memory.
   inline void mark_out_of_memory();
 
-  // A native context hold a list of all functions which have been optimized.
+  // A native context holds a list of all functions with optimized code.
   void AddOptimizedFunction(JSFunction* function);
   void RemoveOptimizedFunction(JSFunction* function);
+  void SetOptimizedFunctionsListHead(Object* head);
   Object* OptimizedFunctionsListHead();
-  void ClearOptimizedFunctions();
+
+  // The native context also stores a list of all optimized code and a
+  // list of all deoptimized code, which are needed by the deoptimizer.
+  void AddOptimizedCode(Code* code);
+  void SetOptimizedCodeListHead(Object* head);
+  Object* OptimizedCodeListHead();
+  void SetDeoptimizedCodeListHead(Object* head);
+  Object* DeoptimizedCodeListHead();
 
   Handle<Object> ErrorMessageForCodeGenerationFromStrings();
 
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index 34bebb8..35fe788 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -363,6 +363,8 @@
 
 CpuProfiler::CpuProfiler(Isolate* isolate)
     : isolate_(isolate),
+      sampling_interval_(TimeDelta::FromMicroseconds(
+          FLAG_cpu_profiler_sampling_interval)),
       profiles_(new CpuProfilesCollection()),
       next_profile_uid_(1),
       generator_(NULL),
@@ -376,6 +378,8 @@
                          ProfileGenerator* test_generator,
                          ProfilerEventsProcessor* test_processor)
     : isolate_(isolate),
+      sampling_interval_(TimeDelta::FromMicroseconds(
+          FLAG_cpu_profiler_sampling_interval)),
       profiles_(test_profiles),
       next_profile_uid_(1),
       generator_(test_generator),
@@ -390,6 +394,12 @@
 }
 
 
+void CpuProfiler::set_sampling_interval(TimeDelta value) {
+  ASSERT(!is_profiling_);
+  sampling_interval_ = value;
+}
+
+
 void CpuProfiler::ResetProfiles() {
   delete profiles_;
   profiles_ = new CpuProfilesCollection();
@@ -418,8 +428,7 @@
     generator_ = new ProfileGenerator(profiles_);
     Sampler* sampler = logger->sampler();
     processor_ = new ProfilerEventsProcessor(
-        generator_, sampler,
-        TimeDelta::FromMicroseconds(FLAG_cpu_profiler_sampling_interval));
+        generator_, sampler, sampling_interval_);
     is_profiling_ = true;
     // Enumerate stuff we already have in the heap.
     ASSERT(isolate_->heap()->HasBeenSetUp());
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index a6eccff..e36c301 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -31,6 +31,7 @@
 #include "allocation.h"
 #include "atomicops.h"
 #include "circular-queue.h"
+#include "platform/time.h"
 #include "sampler.h"
 #include "unbound-queue.h"
 
@@ -203,6 +204,7 @@
 
   virtual ~CpuProfiler();
 
+  void set_sampling_interval(TimeDelta value);
   void StartProfiling(const char* title, bool record_samples = false);
   void StartProfiling(String* title, bool record_samples);
   CpuProfile* StopProfiling(const char* title);
@@ -260,6 +262,7 @@
   void LogBuiltins();
 
   Isolate* isolate_;
+  TimeDelta sampling_interval_;
   CpuProfilesCollection* profiles_;
   unsigned next_profile_uid_;
   ProfileGenerator* generator_;
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index 2905500..602ae16 100644
--- a/src/d8-debug.cc
+++ b/src/d8-debug.cc
@@ -29,8 +29,9 @@
 
 #include "d8.h"
 #include "d8-debug.h"
-#include "platform.h"
 #include "debug-agent.h"
+#include "platform.h"
+#include "platform/socket.h"
 
 
 namespace v8 {
@@ -171,21 +172,14 @@
 void RemoteDebugger::Run() {
   bool ok;
 
-  // Make sure that socket support is initialized.
-  ok = i::Socket::SetUp();
-  if (!ok) {
-    printf("Unable to initialize socket support %d\n", i::Socket::LastError());
-    return;
-  }
-
   // Connect to the debugger agent.
-  conn_ = i::OS::CreateSocket();
+  conn_ = new i::Socket;
   static const int kPortStrSize = 6;
   char port_str[kPortStrSize];
   i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
   ok = conn_->Connect("localhost", port_str);
   if (!ok) {
-    printf("Unable to connect to debug agent %d\n", i::Socket::LastError());
+    printf("Unable to connect to debug agent %d\n", i::Socket::GetLastError());
     return;
   }
 
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
index 51bd4b1..aad3608 100644
--- a/src/debug-agent.cc
+++ b/src/debug-agent.cc
@@ -25,12 +25,12 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 
 #include "v8.h"
 #include "debug.h"
 #include "debug-agent.h"
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
+#include "platform/socket.h"
 
 namespace v8 {
 namespace internal {
@@ -44,6 +44,27 @@
 }
 
 
+DebuggerAgent::DebuggerAgent(Isolate* isolate, const char* name, int port)
+  : Thread(name),
+    isolate_(isolate),
+    name_(StrDup(name)),
+    port_(port),
+    server_(new Socket),
+    terminate_(false),
+    session_(NULL),
+    terminate_now_(0),
+    listening_(0) {
+  ASSERT(isolate_->debugger_agent_instance() == NULL);
+  isolate_->set_debugger_agent_instance(this);
+}
+
+
+DebuggerAgent::~DebuggerAgent() {
+  isolate_->set_debugger_agent_instance(NULL);
+  delete server_;
+}
+
+
 // Debugger agent main thread.
 void DebuggerAgent::Run() {
   // Allow this socket to reuse port even if still in TIME_WAIT.
@@ -112,8 +133,10 @@
 
   // If another session is already established terminate this one.
   if (session_ != NULL) {
-    client->Send(kCreateSessionMessage, StrLength(kCreateSessionMessage));
+    int len = StrLength(kCreateSessionMessage);
+    int res = client->Send(kCreateSessionMessage, len);
     delete client;
+    USE(res);
     return;
   }
 
@@ -228,7 +251,7 @@
 const char* const DebuggerAgentUtil::kContentLength = "Content-Length";
 
 
-SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) {
+SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(Socket* conn) {
   int received;
 
   // Read header.
@@ -245,7 +268,7 @@
       prev_c = c;
       received = conn->Receive(&c, 1);
       if (received == 0) {
-        PrintF("Error %d\n", Socket::LastError());
+        PrintF("Error %d\n", Socket::GetLastError());
         return SmartArrayPointer<char>();
       }
 
@@ -307,7 +330,7 @@
   char* buffer = NewArray<char>(content_length + 1);
   received = ReceiveAll(conn, buffer, content_length);
   if (received < content_length) {
-    PrintF("Error %d\n", Socket::LastError());
+    PrintF("Error %d\n", Socket::GetLastError());
     return SmartArrayPointer<char>();
   }
   buffer[content_length] = '\0';
@@ -316,7 +339,7 @@
 }
 
 
-bool DebuggerAgentUtil::SendConnectMessage(const Socket* conn,
+bool DebuggerAgentUtil::SendConnectMessage(Socket* conn,
                                            const char* embedding_host) {
   static const int kBufferSize = 80;
   char buffer[kBufferSize];  // Sending buffer.
@@ -362,7 +385,7 @@
 }
 
 
-bool DebuggerAgentUtil::SendMessage(const Socket* conn,
+bool DebuggerAgentUtil::SendMessage(Socket* conn,
                                     const Vector<uint16_t> message) {
   static const int kBufferSize = 80;
   char buffer[kBufferSize];  // Sending buffer both for header and body.
@@ -377,14 +400,17 @@
   }
 
   // Send the header.
-  int len;
-  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
-                     "%s: %d\r\n", kContentLength, utf8_len);
-  conn->Send(buffer, len);
+  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                         "%s: %d\r\n", kContentLength, utf8_len);
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Terminate header with empty line.
   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
-  conn->Send(buffer, len);
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Send message body as UTF-8.
   int buffer_position = 0;  // Current buffer position.
@@ -404,13 +430,19 @@
         const int kEncodedSurrogateLength =
             unibrow::Utf16::kUtf8BytesToCodeASurrogate;
         ASSERT(buffer_position >= kEncodedSurrogateLength);
-        conn->Send(buffer, buffer_position - kEncodedSurrogateLength);
+        len = buffer_position - kEncodedSurrogateLength;
+        if (conn->Send(buffer, len) < len) {
+          return false;
+        }
         for (int i = 0; i < kEncodedSurrogateLength; i++) {
           buffer[i] = buffer[buffer_position + i];
         }
         buffer_position = kEncodedSurrogateLength;
       } else {
-        conn->Send(buffer, buffer_position);
+        len = buffer_position;
+        if (conn->Send(buffer, len) < len) {
+          return false;
+        }
         buffer_position = 0;
       }
     }
@@ -421,7 +453,7 @@
 }
 
 
-bool DebuggerAgentUtil::SendMessage(const Socket* conn,
+bool DebuggerAgentUtil::SendMessage(Socket* conn,
                                     const v8::Handle<v8::String> request) {
   static const int kBufferSize = 80;
   char buffer[kBufferSize];  // Sending buffer both for header and body.
@@ -430,24 +462,30 @@
   v8::String::Utf8Value utf8_request(request);
 
   // Send the header.
-  int len;
-  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
-                     "Content-Length: %d\r\n", utf8_request.length());
-  conn->Send(buffer, len);
+  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                         "Content-Length: %d\r\n", utf8_request.length());
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Terminate header with empty line.
   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
-  conn->Send(buffer, len);
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Send message body as UTF-8.
-  conn->Send(*utf8_request, utf8_request.length());
+  len = utf8_request.length();
+  if (conn->Send(*utf8_request, len) < len) {
+    return false;
+  }
 
   return true;
 }
 
 
 // Receive the full buffer before returning unless an error occours.
-int DebuggerAgentUtil::ReceiveAll(const Socket* conn, char* data, int len) {
+int DebuggerAgentUtil::ReceiveAll(Socket* conn, char* data, int len) {
   int total_received = 0;
   while (total_received < len) {
     int received = conn->Receive(data + total_received, len - total_received);
diff --git a/src/debug-agent.h b/src/debug-agent.h
index 9d7c62b..138e51a 100644
--- a/src/debug-agent.h
+++ b/src/debug-agent.h
@@ -37,27 +37,15 @@
 
 // Forward decelrations.
 class DebuggerAgentSession;
+class Socket;
 
 
 // Debugger agent which starts a socket listener on the debugger port and
 // handles connection from a remote debugger.
 class DebuggerAgent: public Thread {
  public:
-  DebuggerAgent(Isolate* isolate, const char* name, int port)
-      : Thread(name),
-        isolate_(isolate),
-        name_(StrDup(name)), port_(port),
-        server_(OS::CreateSocket()), terminate_(false),
-        session_(NULL),
-        terminate_now_(0),
-        listening_(0) {
-    ASSERT(isolate_->debugger_agent_instance() == NULL);
-    isolate_->set_debugger_agent_instance(this);
-  }
-  ~DebuggerAgent() {
-     isolate_->set_debugger_agent_instance(NULL);
-     delete server_;
-  }
+  DebuggerAgent(Isolate* isolate, const char* name, int port);
+  ~DebuggerAgent();
 
   void Shutdown();
   void WaitUntilListening();
@@ -116,13 +104,11 @@
  public:
   static const char* const kContentLength;
 
-  static SmartArrayPointer<char> ReceiveMessage(const Socket* conn);
-  static bool SendConnectMessage(const Socket* conn,
-                                 const char* embedding_host);
-  static bool SendMessage(const Socket* conn, const Vector<uint16_t> message);
-  static bool SendMessage(const Socket* conn,
-                          const v8::Handle<v8::String> message);
-  static int ReceiveAll(const Socket* conn, char* data, int len);
+  static SmartArrayPointer<char> ReceiveMessage(Socket* conn);
+  static bool SendConnectMessage(Socket* conn, const char* embedding_host);
+  static bool SendMessage(Socket* conn, const Vector<uint16_t> message);
+  static bool SendMessage(Socket* conn, const v8::Handle<v8::String> message);
+  static int ReceiveAll(Socket* conn, char* data, int len);
 };
 
 } }  // namespace v8::internal
diff --git a/src/debug.cc b/src/debug.cc
index 9f38601..c3d737e 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -3433,15 +3433,11 @@
     v8::Debug::DebugBreak();
   }
 
-  if (Socket::SetUp()) {
-    if (agent_ == NULL) {
-      agent_ = new DebuggerAgent(isolate_, name, port);
-      agent_->Start();
-    }
-    return true;
+  if (agent_ == NULL) {
+    agent_ = new DebuggerAgent(isolate_, name, port);
+    agent_->Start();
   }
-
-  return false;
+  return true;
 }
 
 
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 49d046b..61ce780 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -56,11 +56,10 @@
 
 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator)
     : allocator_(allocator),
-      current_(NULL),
 #ifdef ENABLE_DEBUGGER_SUPPORT
       deoptimized_frame_info_(NULL),
 #endif
-      deoptimizing_code_list_(NULL) {
+      current_(NULL) {
   for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) {
     deopt_entry_code_entries_[i] = -1;
     deopt_entry_code_[i] = AllocateCodeChunk(allocator);
@@ -73,14 +72,6 @@
     allocator_->Free(deopt_entry_code_[i]);
     deopt_entry_code_[i] = NULL;
   }
-
-  DeoptimizingCodeListNode* current = deoptimizing_code_list_;
-  while (current != NULL) {
-    DeoptimizingCodeListNode* prev = current;
-    current = current->next();
-    delete prev;
-  }
-  deoptimizing_code_list_ = NULL;
 }
 
 
@@ -93,33 +84,19 @@
 #endif
 
 
-Code* DeoptimizerData::FindDeoptimizingCode(Address addr) {
-  for (DeoptimizingCodeListNode* node = deoptimizing_code_list_;
-       node != NULL;
-       node = node->next()) {
-    if (node->code()->contains(addr)) return *node->code();
-  }
-  return NULL;
-}
-
-
-void DeoptimizerData::RemoveDeoptimizingCode(Code* code) {
-  for (DeoptimizingCodeListNode *prev = NULL, *cur = deoptimizing_code_list_;
-       cur != NULL;
-       prev = cur, cur = cur->next()) {
-    if (*cur->code() == code) {
-      if (prev == NULL) {
-        deoptimizing_code_list_ = cur->next();
-      } else {
-        prev->set_next(cur->next());
-      }
-      delete cur;
-      return;
+Code* Deoptimizer::FindDeoptimizingCode(Address addr) {
+  if (function_->IsHeapObject()) {
+    // Search all deoptimizing code in the native context of the function.
+    Context* native_context = function_->context()->native_context();
+    Object* element = native_context->DeoptimizedCodeListHead();
+    while (!element->IsUndefined()) {
+      Code* code = Code::cast(element);
+      ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+      if (code->contains(addr)) return code;
+      element = code->next_code_link();
     }
   }
-  // Deoptimizing code is removed through weak callback. Each object is expected
-  // to be removed once and only once.
-  UNREACHABLE();
+  return NULL;
 }
 
 
@@ -289,27 +266,42 @@
 
 void Deoptimizer::VisitAllOptimizedFunctionsForContext(
     Context* context, OptimizedFunctionVisitor* visitor) {
-  Isolate* isolate = context->GetIsolate();
-  Zone zone(isolate);
   DisallowHeapAllocation no_allocation;
 
   ASSERT(context->IsNativeContext());
 
   visitor->EnterContext(context);
 
-  // Create a snapshot of the optimized functions list. This is needed because
-  // visitors might remove more than one link from the list at once.
-  ZoneList<JSFunction*> snapshot(1, &zone);
+  // Visit the list of optimized functions, removing elements that
+  // no longer refer to optimized code.
+  JSFunction* prev = NULL;
   Object* element = context->OptimizedFunctionsListHead();
   while (!element->IsUndefined()) {
-    JSFunction* element_function = JSFunction::cast(element);
-    snapshot.Add(element_function, &zone);
-    element = element_function->next_function_link();
-  }
-
-  // Run through the snapshot of optimized functions and visit them.
-  for (int i = 0; i < snapshot.length(); ++i) {
-    visitor->VisitFunction(snapshot.at(i));
+    JSFunction* function = JSFunction::cast(element);
+    Object* next = function->next_function_link();
+    if (function->code()->kind() != Code::OPTIMIZED_FUNCTION ||
+        (visitor->VisitFunction(function),
+         function->code()->kind() != Code::OPTIMIZED_FUNCTION)) {
+      // The function no longer refers to optimized code, or the visitor
+      // changed the code to which it refers to no longer be optimized code.
+      // Remove the function from this list.
+      if (prev != NULL) {
+        prev->set_next_function_link(next);
+      } else {
+        context->SetOptimizedFunctionsListHead(next);
+      }
+      // The visitor should not alter the link directly.
+      ASSERT(function->next_function_link() == next);
+      // Set the next function link to undefined to indicate it is no longer
+      // in the optimized functions list.
+      function->set_next_function_link(context->GetHeap()->undefined_value());
+    } else {
+      // The visitor should not alter the link directly.
+      ASSERT(function->next_function_link() == next);
+      // preserve this element.
+      prev = function;
+    }
+    element = next;
   }
 
   visitor->LeaveContext(context);
@@ -321,7 +313,7 @@
     OptimizedFunctionVisitor* visitor) {
   DisallowHeapAllocation no_allocation;
 
-  // Run through the list of all native contexts and deoptimize.
+  // Run through the list of all native contexts.
   Object* context = isolate->heap()->native_contexts_list();
   while (!context->IsUndefined()) {
     VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor);
@@ -330,220 +322,164 @@
 }
 
 
-// Removes the functions selected by the given filter from the optimized
-// function list of the given context and adds their code to the list of
-// code objects to be deoptimized.
-static void SelectCodeToDeoptimize(Context* context,
-                                   OptimizedFunctionFilter* filter,
-                                   ZoneList<Code*>* codes,
-                                   Zone* zone,
-                                   Object* undefined) {
+// Unlink functions referring to code marked for deoptimization, then move
+// marked code from the optimized code list to the deoptimized code list,
+// and patch code for lazy deopt.
+void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) {
   DisallowHeapAllocation no_allocation;
-  Object* current = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
-  Object* remainder_head = undefined;
-  Object* remainder_tail = undefined;
 
-  // TODO(titzer): rewrite to not modify unselected functions.
-  while (current != undefined) {
-    JSFunction* function = JSFunction::cast(current);
-    current = function->next_function_link();
-    if (filter->TakeFunction(function)) {
-      // Extract this function from the context's list and remember the code.
+  // A "closure" that unlinks optimized code that is going to be
+  // deoptimized from the functions that refer to it.
+  class SelectedCodeUnlinker: public OptimizedFunctionVisitor {
+   public:
+    virtual void EnterContext(Context* context) { }  // Don't care.
+    virtual void LeaveContext(Context* context)  { }  // Don't care.
+    virtual void VisitFunction(JSFunction* function) {
       Code* code = function->code();
-      ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
-      if (code->marked_for_deoptimization()) {
-        ASSERT(codes->Contains(code));
-      } else {
-        code->set_marked_for_deoptimization(true);
-        codes->Add(code, zone);
-      }
+      if (!code->marked_for_deoptimization()) return;
+
+      // Unlink this function and evict from optimized code map.
       SharedFunctionInfo* shared = function->shared();
-      // Replace the function's code with the shared code.
       function->set_code(shared->code());
-      // Evict the code from the optimized code map.
       shared->EvictFromOptimizedCodeMap(code, "deoptimized function");
-      // Remove the function from the optimized functions list.
-      function->set_next_function_link(undefined);
 
       if (FLAG_trace_deopt) {
-        PrintF("[forced deoptimization: ");
+        PrintF("[deoptimizer unlinked: ");
         function->PrintName();
         PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
       }
-    } else {
-      // Don't select this function; link it back into the list.
-      if (remainder_head == undefined) {
-        remainder_head = function;
-      } else {
-        JSFunction::cast(remainder_tail)->set_next_function_link(function);
-      }
-      remainder_tail = function;
     }
+  };
+
+  // Unlink all functions that refer to marked code.
+  SelectedCodeUnlinker unlinker;
+  VisitAllOptimizedFunctionsForContext(context, &unlinker);
+
+  // Move marked code from the optimized code list to the deoptimized
+  // code list, collecting them into a ZoneList.
+  Isolate* isolate = context->GetHeap()->isolate();
+  Zone zone(isolate);
+  ZoneList<Code*> codes(10, &zone);
+
+  // Walk over all optimized code objects in this native context.
+  Code* prev = NULL;
+  Object* element = context->OptimizedCodeListHead();
+  while (!element->IsUndefined()) {
+    Code* code = Code::cast(element);
+    ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+    Object* next = code->next_code_link();
+    if (code->marked_for_deoptimization()) {
+      // Put the code into the list for later patching.
+      codes.Add(code, &zone);
+
+      if (prev != NULL) {
+        // Skip this code in the optimized code list.
+        prev->set_next_code_link(next);
+      } else {
+        // There was no previous node, the next node is the new head.
+        context->SetOptimizedCodeListHead(next);
+      }
+
+      // Move the code to the _deoptimized_ code list.
+      code->set_next_code_link(context->DeoptimizedCodeListHead());
+      context->SetDeoptimizedCodeListHead(code);
+    } else {
+      // Not marked; preserve this element.
+      prev = code;
+    }
+    element = next;
   }
-  if (remainder_tail != undefined) {
-    JSFunction::cast(remainder_tail)->set_next_function_link(undefined);
+
+  // TODO(titzer): we need a handle scope only because of the macro assembler,
+  // which is only used in EnsureCodeForDeoptimizationEntry.
+  HandleScope scope(isolate);
+  // Now patch all the codes for deoptimization.
+  for (int i = 0; i < codes.length(); i++) {
+    // It is finally time to die, code object.
+    // Do platform-specific patching to force any activations to lazy deopt.
+    PatchCodeForDeoptimization(isolate, codes[i]);
+
+    // We might be in the middle of incremental marking with compaction.
+    // Tell collector to treat this code object in a special way and
+    // ignore all slots that might have been recorded on it.
+    isolate->heap()->mark_compact_collector()->InvalidateCode(codes[i]);
   }
-  context->set(Context::OPTIMIZED_FUNCTIONS_LIST, remainder_head);
 }
 
 
-class DeoptimizeAllFilter : public OptimizedFunctionFilter {
- public:
-  virtual bool TakeFunction(JSFunction* function) {
-    return true;
-  }
-};
-
-
-class DeoptimizeWithMatchingCodeFilter : public OptimizedFunctionFilter {
- public:
-  explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {}
-  virtual bool TakeFunction(JSFunction* function) {
-    return function->code() == code_;
-  }
- private:
-  Code* code_;
-};
-
-
-class DeoptimizeMarkedCodeFilter : public OptimizedFunctionFilter {
- public:
-  virtual bool TakeFunction(JSFunction* function) {
-    return function->code()->marked_for_deoptimization();
-  }
-};
-
-
 void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
-  DisallowHeapAllocation no_allocation;
-
   if (FLAG_trace_deopt) {
-    PrintF("[deoptimize all contexts]\n");
+    PrintF("[deoptimize all code in all contexts]\n");
   }
+  DisallowHeapAllocation no_allocation;
+  // For all contexts, mark all code, then deoptimize.
+  Object* context = isolate->heap()->native_contexts_list();
+  while (!context->IsUndefined()) {
+    Context* native_context = Context::cast(context);
+    MarkAllCodeForContext(native_context);
+    DeoptimizeMarkedCodeForContext(native_context);
+    context = native_context->get(Context::NEXT_CONTEXT_LINK);
+  }
+}
 
-  DeoptimizeAllFilter filter;
-  DeoptimizeAllFunctionsWith(isolate, &filter);
+
+void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
+  if (FLAG_trace_deopt) {
+    PrintF("[deoptimize marked code in all contexts]\n");
+  }
+  DisallowHeapAllocation no_allocation;
+  // For all contexts, deoptimize code already marked.
+  Object* context = isolate->heap()->native_contexts_list();
+  while (!context->IsUndefined()) {
+    Context* native_context = Context::cast(context);
+    DeoptimizeMarkedCodeForContext(native_context);
+    context = native_context->get(Context::NEXT_CONTEXT_LINK);
+  }
 }
 
 
 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) {
-  DisallowHeapAllocation no_allocation;
-  DeoptimizeAllFilter filter;
+  if (FLAG_trace_deopt) {
+    PrintF("[deoptimize global object @ 0x%08" V8PRIxPTR "]\n",
+        reinterpret_cast<intptr_t>(object));
+  }
   if (object->IsJSGlobalProxy()) {
     Object* proto = object->GetPrototype();
     ASSERT(proto->IsJSGlobalObject());
-    DeoptimizeAllFunctionsForContext(
-        GlobalObject::cast(proto)->native_context(), &filter);
+    Context* native_context = GlobalObject::cast(proto)->native_context();
+    MarkAllCodeForContext(native_context);
+    DeoptimizeMarkedCodeForContext(native_context);
   } else if (object->IsGlobalObject()) {
-    DeoptimizeAllFunctionsForContext(
-        GlobalObject::cast(object)->native_context(), &filter);
+    Context* native_context = GlobalObject::cast(object)->native_context();
+    MarkAllCodeForContext(native_context);
+    DeoptimizeMarkedCodeForContext(native_context);
+  }
+}
+
+
+void Deoptimizer::MarkAllCodeForContext(Context* context) {
+  Object* element = context->OptimizedCodeListHead();
+  while (!element->IsUndefined()) {
+    Code* code = Code::cast(element);
+    ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+    code->set_marked_for_deoptimization(true);
+    element = code->next_code_link();
   }
 }
 
 
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
   Code* code = function->code();
-  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;
-  DeoptimizeWithMatchingCodeFilter filter(code);
-  DeoptimizeAllFunctionsForContext(
-      function->context()->native_context(), &filter);
-}
-
-
-void Deoptimizer::DeoptimizeAllFunctionsForContext(
-    Context* context, OptimizedFunctionFilter* filter) {
-  ASSERT(context->IsNativeContext());
-  Isolate* isolate = context->GetIsolate();
-  Object* undefined = isolate->heap()->undefined_value();
-  Zone zone(isolate);
-  ZoneList<Code*> codes(4, &zone);
-  SelectCodeToDeoptimize(context, filter, &codes, &zone, undefined);
-  for (int i = 0; i < codes.length(); i++) {
-    DeoptimizeCode(isolate, codes.at(i));
+  if (code->kind() == Code::OPTIMIZED_FUNCTION) {
+    // Mark the code for deoptimization and unlink any functions that also
+    // refer to that code. The code cannot be shared across native contexts,
+    // so we only need to search one.
+    code->set_marked_for_deoptimization(true);
+    DeoptimizeMarkedCodeForContext(function->context()->native_context());
   }
 }
 
 
-void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate,
-                                             OptimizedFunctionFilter* filter) {
-  DisallowHeapAllocation no_allocation;
-
-  // Run through the list of all native contexts and deoptimize.
-  Object* context = isolate->heap()->native_contexts_list();
-  while (!context->IsUndefined()) {
-    DeoptimizeAllFunctionsForContext(Context::cast(context), filter);
-    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
-  }
-}
-
-
-void Deoptimizer::DeoptimizeCodeList(Isolate* isolate, ZoneList<Code*>* codes) {
-  if (codes->length() == 0) return;  // Nothing to do.
-
-  // Mark the code; any functions refering to this code will be selected.
-  for (int i = 0; i < codes->length(); i++) {
-    ASSERT(!codes->at(i)->marked_for_deoptimization());
-    codes->at(i)->set_marked_for_deoptimization(true);
-  }
-
-  // For all contexts, remove optimized functions that refer to the selected
-  // code from the optimized function lists.
-  Object* undefined = isolate->heap()->undefined_value();
-  Zone zone(isolate);
-  Object* list = isolate->heap()->native_contexts_list();
-  DeoptimizeMarkedCodeFilter filter;
-  while (!list->IsUndefined()) {
-    Context* context = Context::cast(list);
-    // Note that selecting code unlinks the functions that refer to it.
-    SelectCodeToDeoptimize(context, &filter, codes, &zone, undefined);
-    list = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
-  }
-
-  // Now deoptimize all the code.
-  for (int i = 0; i < codes->length(); i++) {
-    DeoptimizeCode(isolate, codes->at(i));
-  }
-}
-
-
-void Deoptimizer::DeoptimizeCode(Isolate* isolate, Code* code) {
-  HandleScope scope(isolate);
-  DisallowHeapAllocation nha;
-
-  // Do platform-specific patching of the optimized code.
-  PatchCodeForDeoptimization(isolate, code);
-
-  // Add the deoptimizing code to the list.
-  DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
-  DeoptimizerData* data = isolate->deoptimizer_data();
-  node->set_next(data->deoptimizing_code_list_);
-  data->deoptimizing_code_list_ = node;
-
-  // We might be in the middle of incremental marking with compaction.
-  // Tell collector to treat this code object in a special way and
-  // ignore all slots that might have been recorded on it.
-  isolate->heap()->mark_compact_collector()->InvalidateCode(code);
-}
-
-
-void Deoptimizer::HandleWeakDeoptimizedCode(v8::Isolate* isolate,
-                                            v8::Persistent<v8::Value>* obj,
-                                            void* parameter) {
-  DeoptimizingCodeListNode* node =
-      reinterpret_cast<DeoptimizingCodeListNode*>(parameter);
-  DeoptimizerData* data =
-      reinterpret_cast<Isolate*>(isolate)->deoptimizer_data();
-  data->RemoveDeoptimizingCode(*node->code());
-#ifdef DEBUG
-  for (DeoptimizingCodeListNode* current = data->deoptimizing_code_list_;
-       current != NULL;
-       current = current->next()) {
-    ASSERT(current != node);
-  }
-#endif
-}
-
-
 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
   deoptimizer->DoComputeOutputFrames();
 }
@@ -647,8 +583,7 @@
     case Deoptimizer::SOFT:
     case Deoptimizer::EAGER:
     case Deoptimizer::LAZY: {
-      Code* compiled_code =
-          isolate_->deoptimizer_data()->FindDeoptimizingCode(from_);
+      Code* compiled_code = FindDeoptimizingCode(from_);
       return (compiled_code == NULL)
           ? static_cast<Code*>(isolate_->FindCodeObject(from_))
           : compiled_code;
@@ -765,11 +700,18 @@
 
 int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
   int length = 0;
-  DeoptimizingCodeListNode* node =
-      isolate->deoptimizer_data()->deoptimizing_code_list_;
-  while (node != NULL) {
-    length++;
-    node = node->next();
+  // Count all entries in the deoptimizing code list of every context.
+  Object* context = isolate->heap()->native_contexts_list();
+  while (!context->IsUndefined()) {
+    Context* native_context = Context::cast(context);
+    Object* element = native_context->DeoptimizedCodeListHead();
+    while (!element->IsUndefined()) {
+      Code* code = Code::cast(element);
+      ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+      length++;
+      element = code->next_code_link();
+    }
+    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
   }
   return length;
 }
@@ -2591,71 +2533,68 @@
 
 
 void Deoptimizer::PatchInterruptCode(Isolate* isolate,
-                                     Code* unoptimized_code) {
+                                     Code* unoptimized) {
   DisallowHeapAllocation no_gc;
   Code* replacement_code =
       isolate->builtins()->builtin(Builtins::kOnStackReplacement);
 
   // Iterate over the back edge table and patch every interrupt
   // call to an unconditional call to the replacement code.
-  int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level();
+  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
 
-  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
+  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized, &no_gc);
        !back_edges.Done();
        back_edges.Next()) {
     if (static_cast<int>(back_edges.loop_depth()) == loop_nesting_level) {
       ASSERT_EQ(NOT_PATCHED, GetInterruptPatchState(isolate,
-                                                    unoptimized_code,
+                                                    unoptimized,
                                                     back_edges.pc()));
-      PatchInterruptCodeAt(unoptimized_code,
+      PatchInterruptCodeAt(unoptimized,
                            back_edges.pc(),
                            replacement_code);
     }
   }
 
-  unoptimized_code->set_back_edges_patched_for_osr(true);
-#ifdef DEBUG
-  Deoptimizer::VerifyInterruptCode(
-      isolate, unoptimized_code, loop_nesting_level);
-#endif  // DEBUG
+  unoptimized->set_back_edges_patched_for_osr(true);
+  ASSERT(Deoptimizer::VerifyInterruptCode(
+             isolate, unoptimized, loop_nesting_level));
 }
 
 
 void Deoptimizer::RevertInterruptCode(Isolate* isolate,
-                                      Code* unoptimized_code) {
+                                      Code* unoptimized) {
   DisallowHeapAllocation no_gc;
   Code* interrupt_code =
       isolate->builtins()->builtin(Builtins::kInterruptCheck);
 
   // Iterate over the back edge table and revert the patched interrupt calls.
-  ASSERT(unoptimized_code->back_edges_patched_for_osr());
-  int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level();
+  ASSERT(unoptimized->back_edges_patched_for_osr());
+  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
 
-  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
+  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized, &no_gc);
        !back_edges.Done();
        back_edges.Next()) {
     if (static_cast<int>(back_edges.loop_depth()) <= loop_nesting_level) {
       ASSERT_EQ(PATCHED_FOR_OSR, GetInterruptPatchState(isolate,
-                                                        unoptimized_code,
+                                                        unoptimized,
                                                         back_edges.pc()));
-      RevertInterruptCodeAt(unoptimized_code, back_edges.pc(), interrupt_code);
+      RevertInterruptCodeAt(unoptimized, back_edges.pc(), interrupt_code);
     }
   }
 
-  unoptimized_code->set_back_edges_patched_for_osr(false);
-  unoptimized_code->set_allow_osr_at_loop_nesting_level(0);
-#ifdef DEBUG
+  unoptimized->set_back_edges_patched_for_osr(false);
+  unoptimized->set_allow_osr_at_loop_nesting_level(0);
   // Assert that none of the back edges are patched anymore.
-  Deoptimizer::VerifyInterruptCode(isolate, unoptimized_code, -1);
-#endif  // DEBUG
+  ASSERT(Deoptimizer::VerifyInterruptCode(isolate, unoptimized, -1));
 }
 
 
 #ifdef DEBUG
-void Deoptimizer::VerifyInterruptCode(Isolate* isolate,
-                                      Code* unoptimized_code,
+bool Deoptimizer::VerifyInterruptCode(Isolate* isolate,
+                                      Code* unoptimized,
                                       int loop_nesting_level) {
-  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
+  DisallowHeapAllocation no_gc;
+  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized, &no_gc);
        !back_edges.Done();
        back_edges.Next()) {
     uint32_t loop_depth = back_edges.loop_depth();
@@ -2664,9 +2603,10 @@
     // have already been patched.
     CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
              GetInterruptPatchState(isolate,
-                                    unoptimized_code,
+                                    unoptimized,
                                     back_edges.pc()) != NOT_PATCHED);
   }
+  return true;
 }
 #endif  // DEBUG
 
@@ -3121,22 +3061,6 @@
 #endif
 
 
-DeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) {
-  GlobalHandles* global_handles = code->GetIsolate()->global_handles();
-  // Globalize the code object and make it weak.
-  code_ = Handle<Code>::cast(global_handles->Create(code));
-  global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()),
-                           this,
-                           Deoptimizer::HandleWeakDeoptimizedCode);
-}
-
-
-DeoptimizingCodeListNode::~DeoptimizingCodeListNode() {
-  GlobalHandles* global_handles = code_->GetIsolate()->global_handles();
-  global_handles->Destroy(reinterpret_cast<Object**>(code_.location()));
-}
-
-
 // We can't intermix stack decoding and allocations because
 // deoptimization infrastracture is not GC safe.
 // Thus we build a temporary structure in malloced space.
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 0d62bd0..c28b7b9 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -58,7 +58,6 @@
 
 class FrameDescription;
 class TranslationIterator;
-class DeoptimizingCodeListNode;
 class DeoptimizedFrameInfo;
 
 class HeapNumberMaterializationDescriptor BASE_EMBEDDED {
@@ -121,17 +120,6 @@
 };
 
 
-class OptimizedFunctionFilter BASE_EMBEDDED {
- public:
-  virtual ~OptimizedFunctionFilter() {}
-
-  virtual bool TakeFunction(JSFunction* function) = 0;
-};
-
-
-class Deoptimizer;
-
-
 class Deoptimizer : public Malloced {
  public:
   enum BailoutType {
@@ -208,28 +196,20 @@
   // execution returns.
   static void DeoptimizeFunction(JSFunction* function);
 
-  // Iterate over all the functions which share the same code object
-  // and make them use unoptimized version.
-  static void ReplaceCodeForRelatedFunctions(JSFunction* function, Code* code);
-
-  // Deoptimize all functions in the heap.
+  // Deoptimize all code in the given isolate.
   static void DeoptimizeAll(Isolate* isolate);
 
+  // Deoptimize code associated with the given global object.
   static void DeoptimizeGlobalObject(JSObject* object);
 
-  static void DeoptimizeAllFunctionsWith(Isolate* isolate,
-                                         OptimizedFunctionFilter* filter);
+  // Deoptimizes all optimized code that has been previously marked
+  // (via code->set_marked_for_deoptimization) and unlinks all functions that
+  // refer to that code.
+  static void DeoptimizeMarkedCode(Isolate* isolate);
 
-  static void DeoptimizeCodeList(Isolate* isolate, ZoneList<Code*>* codes);
-
-  static void DeoptimizeAllFunctionsForContext(
-      Context* context, OptimizedFunctionFilter* filter);
-
-  static void VisitAllOptimizedFunctionsForContext(
-      Context* context, OptimizedFunctionVisitor* visitor);
-
-  static void VisitAllOptimizedFunctions(Isolate* isolate,
-                                         OptimizedFunctionVisitor* visitor);
+  // Visit all the known optimized functions in a given isolate.
+  static void VisitAllOptimizedFunctions(
+      Isolate* isolate, OptimizedFunctionVisitor* visitor);
 
   // The size in bytes of the code required at a lazy deopt patch site.
   static int patch_size();
@@ -262,7 +242,7 @@
                                                     Address pc_after);
 
   // Verify that all back edges of a certain loop depth are patched.
-  static void VerifyInterruptCode(Isolate* isolate,
+  static bool VerifyInterruptCode(Isolate* isolate,
                                   Code* unoptimized_code,
                                   int loop_nesting_level);
 #endif  // DEBUG
@@ -442,17 +422,24 @@
   static void GenerateDeoptimizationEntries(
       MacroAssembler* masm, int count, BailoutType type);
 
-  // Weak handle callback for deoptimizing code objects.
-  static void HandleWeakDeoptimizedCode(v8::Isolate* isolate,
-                                        v8::Persistent<v8::Value>* obj,
-                                        void* data);
+  // Marks all the code in the given context for deoptimization.
+  static void MarkAllCodeForContext(Context* native_context);
 
-  // Deoptimize the given code and add to appropriate deoptimization lists.
-  static void DeoptimizeCode(Isolate* isolate, Code* code);
+  // Visit all the known optimized functions in a given context.
+  static void VisitAllOptimizedFunctionsForContext(
+      Context* context, OptimizedFunctionVisitor* visitor);
+
+  // Deoptimizes all code marked in the given context.
+  static void DeoptimizeMarkedCodeForContext(Context* native_context);
 
   // Patch the given code so that it will deoptimize itself.
   static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
 
+  // Searches the list of known deoptimizing code for a Code object
+  // containing the given address (which is supposedly faster than
+  // searching all code objects).
+  Code* FindDeoptimizingCode(Address addr);
+
   // Fill the input from from a JavaScript frame. This is used when
   // the debugger needs to inspect an optimized frame. For normal
   // deoptimizations the input frame is filled in generated code.
@@ -514,7 +501,6 @@
   static const int table_entry_size_;
 
   friend class FrameDescription;
-  friend class DeoptimizingCodeListNode;
   friend class DeoptimizedFrameInfo;
 };
 
@@ -688,24 +674,16 @@
   void Iterate(ObjectVisitor* v);
 #endif
 
-  Code* FindDeoptimizingCode(Address addr);
-  void RemoveDeoptimizingCode(Code* code);
-
  private:
   MemoryAllocator* allocator_;
   int deopt_entry_code_entries_[Deoptimizer::kBailoutTypesWithCodeEntry];
   MemoryChunk* deopt_entry_code_[Deoptimizer::kBailoutTypesWithCodeEntry];
-  Deoptimizer* current_;
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   DeoptimizedFrameInfo* deoptimized_frame_info_;
 #endif
 
-  // List of deoptimized code which still have references from active stack
-  // frames. These code objects are needed by the deoptimizer when deoptimizing
-  // a frame for which the code object for the function function has been
-  // changed from the code present when deoptimizing was done.
-  DeoptimizingCodeListNode* deoptimizing_code_list_;
+  Deoptimizer* current_;
 
   friend class Deoptimizer;
 
@@ -823,26 +801,6 @@
 };
 
 
-// Linked list holding deoptimizing code objects. The deoptimizing code objects
-// are kept as weak handles until they are no longer activated on the stack.
-class DeoptimizingCodeListNode : public Malloced {
- public:
-  explicit DeoptimizingCodeListNode(Code* code);
-  ~DeoptimizingCodeListNode();
-
-  DeoptimizingCodeListNode* next() const { return next_; }
-  void set_next(DeoptimizingCodeListNode* next) { next_ = next; }
-  Handle<Code> code() const { return code_; }
-
- private:
-  // Global (weak) handle to the deoptimizing code object.
-  Handle<Code> code_;
-
-  // Next pointer for linked list.
-  DeoptimizingCodeListNode* next_;
-};
-
-
 class SlotRef BASE_EMBEDDED {
  public:
   enum SlotRepresentation {
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 55b4127..30df186 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -117,7 +117,7 @@
                     byte* end) {
   SealHandleScope shs(isolate);
   DisallowHeapAllocation no_alloc;
-  ExternalReferenceEncoder ref_encoder;
+  ExternalReferenceEncoder ref_encoder(isolate);
   Heap* heap = HEAP;
 
   v8::internal::EmbeddedVector<char, 128> decode_buffer;
diff --git a/src/execution.cc b/src/execution.cc
index 6075624..048e6e0 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -708,7 +708,7 @@
   int serial_number = Smi::cast(data->serial_number())->value();
   Object* elm =
       isolate->native_context()->function_cache()->
-          GetElementNoExceptionThrown(serial_number);
+          GetElementNoExceptionThrown(isolate, serial_number);
   if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
   // The function has not yet been instantiated in this context; do it.
   Handle<Object> args[] = { data };
diff --git a/src/extensions/statistics-extension.cc b/src/extensions/statistics-extension.cc
index 32bc07d..651d99d 100644
--- a/src/extensions/statistics-extension.cc
+++ b/src/extensions/statistics-extension.cc
@@ -60,7 +60,7 @@
 
 void StatisticsExtension::GetCounters(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate());
   Heap* heap = isolate->heap();
 
   if (args.Length() > 0) {  // GC if first argument evaluates to true.
diff --git a/src/factory.cc b/src/factory.cc
index 819e9f0..c7f7806 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -130,7 +130,8 @@
                                                     int slack) {
   ASSERT(0 <= number_of_descriptors);
   CALL_HEAP_FUNCTION(isolate(),
-                     DescriptorArray::Allocate(number_of_descriptors, slack),
+                     DescriptorArray::Allocate(
+                         isolate(), number_of_descriptors, slack),
                      DescriptorArray);
 }
 
@@ -806,7 +807,7 @@
       *p++ = ' ';
       space--;
       if (space > 0) {
-        MaybeObject* maybe_arg = args->GetElement(i);
+        MaybeObject* maybe_arg = args->GetElement(isolate(), i);
         Handle<String> arg_str(reinterpret_cast<String*>(maybe_arg));
         const char* arg = *arg_str->ToCString();
         Vector<char> v2(p, static_cast<int>(space));
@@ -1321,7 +1322,7 @@
 
 
 Handle<Object> Factory::ToObject(Handle<Object> object) {
-  CALL_HEAP_FUNCTION(isolate(), object->ToObject(), Object);
+  CALL_HEAP_FUNCTION(isolate(), object->ToObject(isolate()), Object);
 }
 
 
@@ -1460,15 +1461,29 @@
   result->shared()->set_construct_stub(*construct_stub);
   result->shared()->DontAdaptArguments();
 
-  // Recursively copy parent templates' accessors, 'data' may be modified.
+  // Recursively copy parent instance templates' accessors,
+  // 'data' may be modified.
   int max_number_of_additional_properties = 0;
+  int max_number_of_static_properties = 0;
   FunctionTemplateInfo* info = *obj;
   while (true) {
-    Object* props = info->property_accessors();
-    if (!props->IsUndefined()) {
-      Handle<Object> props_handle(props, isolate());
-      NeanderArray props_array(props_handle);
-      max_number_of_additional_properties += props_array.length();
+    if (!info->instance_template()->IsUndefined()) {
+      Object* props =
+          ObjectTemplateInfo::cast(
+              info->instance_template())->property_accessors();
+      if (!props->IsUndefined()) {
+        Handle<Object> props_handle(props, isolate());
+        NeanderArray props_array(props_handle);
+        max_number_of_additional_properties += props_array.length();
+      }
+    }
+    if (!info->property_accessors()->IsUndefined()) {
+      Object* props = info->property_accessors();
+      if (!props->IsUndefined()) {
+        Handle<Object> props_handle(props, isolate());
+        NeanderArray props_array(props_handle);
+        max_number_of_static_properties += props_array.length();
+      }
     }
     Object* parent = info->parent_template();
     if (parent->IsUndefined()) break;
@@ -1477,17 +1492,44 @@
 
   Map::EnsureDescriptorSlack(map, max_number_of_additional_properties);
 
+  // Use a temporary FixedArray to acculumate static accessors
+  int valid_descriptors = 0;
+  Handle<FixedArray> array;
+  if (max_number_of_static_properties > 0) {
+    array = NewFixedArray(max_number_of_static_properties);
+  }
+
   while (true) {
-    Handle<Object> props = Handle<Object>(obj->property_accessors(),
-                                          isolate());
-    if (!props->IsUndefined()) {
-      Map::AppendCallbackDescriptors(map, props);
+    // Install instance descriptors
+    if (!obj->instance_template()->IsUndefined()) {
+      Handle<ObjectTemplateInfo> instance =
+          Handle<ObjectTemplateInfo>(
+              ObjectTemplateInfo::cast(obj->instance_template()), isolate());
+      Handle<Object> props = Handle<Object>(instance->property_accessors(),
+                                            isolate());
+      if (!props->IsUndefined()) {
+        Map::AppendCallbackDescriptors(map, props);
+      }
     }
+    // Accumulate static accessors
+    if (!obj->property_accessors()->IsUndefined()) {
+      Handle<Object> props = Handle<Object>(obj->property_accessors(),
+                                            isolate());
+      valid_descriptors =
+          AccessorInfo::AppendUnique(props, array, valid_descriptors);
+    }
+    // Climb parent chain
     Handle<Object> parent = Handle<Object>(obj->parent_template(), isolate());
     if (parent->IsUndefined()) break;
     obj = Handle<FunctionTemplateInfo>::cast(parent);
   }
 
+  // Install accumulated static accessors
+  for (int i = 0; i < valid_descriptors; i++) {
+    Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
+    JSObject::SetAccessor(result, accessor);
+  }
+
   ASSERT(result->shared()->IsApiFunction());
   return result;
 }
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index f19c4a6..d47e9b1 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -240,7 +240,7 @@
 DEFINE_bool(use_gvn, true, "use hydrogen global value numbering")
 DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing")
 DEFINE_bool(use_inlining, true, "use function inlining")
-DEFINE_bool(use_escape_analysis, true, "use hydrogen escape analysis")
+DEFINE_bool(use_escape_analysis, false, "use hydrogen escape analysis")
 DEFINE_bool(use_allocation_folding, true, "use allocation folding")
 DEFINE_int(max_inlining_levels, 5, "maximum number of inlining levels")
 DEFINE_int(max_inlined_source_size, 600,
@@ -331,6 +331,8 @@
            "the length of the concurrent compilation queue")
 DEFINE_int(concurrent_recompilation_delay, 0,
            "artificial compilation delay in ms")
+DEFINE_bool(concurrent_osr, false,
+            "concurrent on-stack replacement")
 
 DEFINE_bool(omit_map_checks_for_leaf_maps, true,
             "do not emit check maps for constant values that have a leaf map, "
@@ -455,16 +457,8 @@
 DEFINE_bool(cache_prototype_transitions, true, "cache prototype transitions")
 
 // cpu-profiler.cc
-#if defined(ANDROID)
-// Phones and tablets have processors that are much slower than desktop
-// and laptop computers for which current heuristics are tuned.
-#define DEFAULT_INTERVAL 5000
-#else
-#define DEFAULT_INTERVAL 1000
-#endif
-DEFINE_int(cpu_profiler_sampling_interval, DEFAULT_INTERVAL,
+DEFINE_int(cpu_profiler_sampling_interval, 1000,
            "CPU profiler sampling interval in microseconds")
-#undef DEFAULT_INTERVAL
 
 // debug.cc
 DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
diff --git a/src/frames.cc b/src/frames.cc
index c17a9d5..5d90f06 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -814,8 +814,7 @@
       PrintF("+%d", code_offset);
       SharedFunctionInfo* shared = fun->shared();
       if (print_line_number) {
-        Code* code = Code::cast(
-            v8::internal::Isolate::Current()->FindCodeObject(pc));
+        Code* code = Code::cast(isolate->FindCodeObject(pc));
         int source_pos = code->SourcePosition(pc);
         Object* maybe_script = shared->script();
         if (maybe_script->IsScript()) {
diff --git a/src/full-codegen.h b/src/full-codegen.h
index ed2cc17..5580cb3 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -141,7 +141,8 @@
 
   class BackEdgeTableIterator {
    public:
-    explicit BackEdgeTableIterator(Code* unoptimized) {
+    explicit BackEdgeTableIterator(Code* unoptimized,
+                                   DisallowHeapAllocation* required) {
       ASSERT(unoptimized->kind() == Code::FUNCTION);
       instruction_start_ = unoptimized->instruction_start();
       cursor_ = instruction_start_ + unoptimized->back_edge_table_offset();
@@ -192,7 +193,6 @@
     Address end_;
     Address instruction_start_;
     uint32_t table_length_;
-    DisallowHeapAllocation no_gc_while_iterating_over_raw_addresses_;
 
     DISALLOW_COPY_AND_ASSIGN(BackEdgeTableIterator);
   };
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 9d04797..8808855 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -766,7 +766,7 @@
 MaybeObject* TranscendentalCache::Get(Type type, double input) {
   SubCache* cache = caches_[type];
   if (cache == NULL) {
-    caches_[type] = cache = new SubCache(type);
+    caches_[type] = cache = new SubCache(isolate_, type);
   }
   return cache->Get(input);
 }
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 1c8a7b3..6a5bb63 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -732,7 +732,7 @@
     HeapSnapshot* snapshot,
     SnapshottingProgressReportingInterface* progress,
     v8::HeapProfiler::ObjectNameResolver* resolver)
-    : heap_(Isolate::Current()->heap()),
+    : heap_(snapshot->collection()->heap()),
       snapshot_(snapshot),
       collection_(snapshot_->collection()),
       progress_(progress),
@@ -1852,7 +1852,7 @@
 
 // Modifies heap. Must not be run during heap traversal.
 void V8HeapExplorer::TagGlobalObjects() {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = heap_->isolate();
   HandleScope scope(isolate);
   GlobalObjectsEnumerator enumerator;
   isolate->global_handles()->IterateAllRoots(&enumerator);
@@ -1927,8 +1927,10 @@
 
 
 NativeObjectsExplorer::NativeObjectsExplorer(
-    HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
-    : snapshot_(snapshot),
+    HeapSnapshot* snapshot,
+    SnapshottingProgressReportingInterface* progress)
+    : isolate_(snapshot->collection()->heap()->isolate()),
+      snapshot_(snapshot),
       collection_(snapshot_->collection()),
       progress_(progress),
       embedder_queried_(false),
@@ -1973,7 +1975,7 @@
 
 void NativeObjectsExplorer::FillRetainedObjects() {
   if (embedder_queried_) return;
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = isolate_;
   const GCType major_gc_type = kGCTypeMarkSweepCompact;
   // Record objects that are joined into ObjectGroups.
   isolate->heap()->CallGCPrologueCallbacks(
@@ -2000,7 +2002,7 @@
 
 
 void NativeObjectsExplorer::FillImplicitReferences() {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = isolate_;
   List<ImplicitRefGroup*>* groups =
       isolate->global_handles()->implicit_ref_groups();
   for (int i = 0; i < groups->length(); ++i) {
@@ -2157,7 +2159,7 @@
 
 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
   if (in_groups_.Contains(*p)) return;
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = isolate_;
   v8::RetainedObjectInfo* info =
       isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p);
   if (info == NULL) return;
@@ -2243,15 +2245,15 @@
   // full GC is reachable from the root when computing dominators.
   // This is not true for weakly reachable objects.
   // As a temporary solution we call GC twice.
-  Isolate::Current()->heap()->CollectAllGarbage(
+  heap_->CollectAllGarbage(
       Heap::kMakeHeapIterableMask,
       "HeapSnapshotGenerator::GenerateSnapshot");
-  Isolate::Current()->heap()->CollectAllGarbage(
+  heap_->CollectAllGarbage(
       Heap::kMakeHeapIterableMask,
       "HeapSnapshotGenerator::GenerateSnapshot");
 
 #ifdef VERIFY_HEAP
-  Heap* debug_heap = Isolate::Current()->heap();
+  Heap* debug_heap = heap_;
   CHECK(!debug_heap->old_data_space()->was_swept_conservatively());
   CHECK(!debug_heap->old_pointer_space()->was_swept_conservatively());
   CHECK(!debug_heap->code_space()->was_swept_conservatively());
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index cea9958..ccdcab4 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -538,7 +538,7 @@
 class NativeObjectsExplorer {
  public:
   NativeObjectsExplorer(HeapSnapshot* snapshot,
-                      SnapshottingProgressReportingInterface* progress);
+                        SnapshottingProgressReportingInterface* progress);
   virtual ~NativeObjectsExplorer();
   void AddRootEntries(SnapshotFillerInterface* filler);
   int EstimateObjectsCount();
@@ -570,6 +570,7 @@
 
   NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label);
 
+  Isolate* isolate_;
   HeapSnapshot* snapshot_;
   HeapSnapshotsCollection* collection_;
   SnapshottingProgressReportingInterface* progress_;
diff --git a/src/heap.cc b/src/heap.cc
index 8487857..037a7a1 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1027,7 +1027,7 @@
   isolate_->eternal_handles()->PostGarbageCollectionProcessing(this);
 
   // Update relocatables.
-  Relocatable::PostGarbageCollectionProcessing();
+  Relocatable::PostGarbageCollectionProcessing(isolate_);
 
   if (collector == MARK_COMPACTOR) {
     // Register the amount of external allocated memory.
@@ -1616,6 +1616,29 @@
 
 
 template<>
+struct WeakListVisitor<Code> {
+  static void SetWeakNext(Code* code, Object* next) {
+    code->set_next_code_link(next);
+  }
+
+  static Object* WeakNext(Code* code) {
+    return code->next_code_link();
+  }
+
+  static int WeakNextOffset() {
+    return Code::kNextCodeLinkOffset;
+  }
+
+  static void VisitLiveObject(Heap*, Code*,
+                              WeakObjectRetainer*, bool) {
+  }
+
+  static void VisitPhantomObject(Heap*, Code*) {
+  }
+};
+
+
+template<>
 struct WeakListVisitor<Context> {
   static void SetWeakNext(Context* context, Object* next) {
     context->set(Context::NEXT_CONTEXT_LINK,
@@ -1631,22 +1654,34 @@
                               Context* context,
                               WeakObjectRetainer* retainer,
                               bool record_slots) {
-    // Process the weak list of optimized functions for the context.
-    Object* function_list_head =
-        VisitWeakList<JSFunction>(
-            heap,
-            context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
-            retainer,
-            record_slots);
-    context->set(Context::OPTIMIZED_FUNCTIONS_LIST,
-                 function_list_head,
-                 UPDATE_WRITE_BARRIER);
+    // Process the three weak lists linked off the context.
+    DoWeakList<JSFunction>(heap, context, retainer, record_slots,
+        Context::OPTIMIZED_FUNCTIONS_LIST);
+    DoWeakList<Code>(heap, context, retainer, record_slots,
+        Context::OPTIMIZED_CODE_LIST);
+    DoWeakList<Code>(heap, context, retainer, record_slots,
+        Context::DEOPTIMIZED_CODE_LIST);
+  }
+
+  template<class T>
+  static void DoWeakList(Heap* heap,
+                         Context* context,
+                         WeakObjectRetainer* retainer,
+                         bool record_slots,
+                         int index) {
+    // Visit the weak list, removing dead intermediate elements.
+    Object* list_head = VisitWeakList<T>(heap, context->get(index), retainer,
+        record_slots);
+
+    // Update the list head.
+    context->set(index, list_head, UPDATE_WRITE_BARRIER);
+
     if (record_slots) {
-      Object** optimized_functions =
-          HeapObject::RawField(
-              context, FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST));
+      // Record the updated slot if necessary.
+      Object** head_slot = HeapObject::RawField(
+          context, FixedArray::SizeFor(index));
       heap->mark_compact_collector()->RecordSlot(
-          optimized_functions, optimized_functions, function_list_head);
+          head_slot, head_slot, list_head);
     }
   }
 
@@ -2938,7 +2973,7 @@
   { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_POINTER_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  return Oddball::cast(result)->Initialize(to_string, to_number, kind);
+  return Oddball::cast(result)->Initialize(this, to_string, to_number, kind);
 }
 
 
@@ -3042,15 +3077,16 @@
 
   // Finish initializing oddballs after creating the string table.
   { MaybeObject* maybe_obj =
-        undefined_value()->Initialize("undefined",
+        undefined_value()->Initialize(this,
+                                      "undefined",
                                       nan_value(),
                                       Oddball::kUndefined);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
 
   // Initialize the null_value.
-  { MaybeObject* maybe_obj =
-        null_value()->Initialize("null", Smi::FromInt(0), Oddball::kNull);
+  { MaybeObject* maybe_obj = null_value()->Initialize(
+      this, "null", Smi::FromInt(0), Oddball::kNull);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
 
@@ -6115,12 +6151,12 @@
 
 void Heap::ReportCodeStatistics(const char* title) {
   PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
-  PagedSpace::ResetCodeStatistics();
+  PagedSpace::ResetCodeStatistics(isolate());
   // We do not look for code in new space, map space, or old space.  If code
   // somehow ends up in those spaces, we would miss it here.
   code_space_->CollectCodeStatistics();
   lo_space_->CollectCodeStatistics();
-  PagedSpace::ReportCodeStatistics();
+  PagedSpace::ReportCodeStatistics(isolate());
 }
 
 
@@ -6574,7 +6610,7 @@
   v->Synchronize(VisitorSynchronization::kBootstrapper);
   isolate_->Iterate(v);
   v->Synchronize(VisitorSynchronization::kTop);
-  Relocatable::Iterate(v);
+  Relocatable::Iterate(isolate_, v);
   v->Synchronize(VisitorSynchronization::kRelocatable);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
@@ -6635,7 +6671,7 @@
   // serialization this does nothing, since the partial snapshot cache is
   // empty.  However the next thing we do is create the partial snapshot,
   // filling up the partial snapshot cache with objects it needs as we go.
-  SerializerDeserializer::Iterate(v);
+  SerializerDeserializer::Iterate(isolate_, v);
   // We don't do a v->Synchronize call here, because in debug mode that will
   // output a flag to the snapshot.  However at this point the serializer and
   // deserializer are deliberately a little unsynchronized (see above) so the
@@ -7239,12 +7275,12 @@
 
 class UnreachableObjectsFilter : public HeapObjectsFilter {
  public:
-  UnreachableObjectsFilter() {
+  explicit UnreachableObjectsFilter(Heap* heap) : heap_(heap) {
     MarkReachableObjects();
   }
 
   ~UnreachableObjectsFilter() {
-    Isolate::Current()->heap()->mark_compact_collector()->ClearMarkbits();
+    heap_->mark_compact_collector()->ClearMarkbits();
   }
 
   bool SkipObject(HeapObject* object) {
@@ -7281,12 +7317,12 @@
   };
 
   void MarkReachableObjects() {
-    Heap* heap = Isolate::Current()->heap();
     MarkingVisitor visitor;
-    heap->IterateRoots(&visitor, VISIT_ALL);
+    heap_->IterateRoots(&visitor, VISIT_ALL);
     visitor.TransitiveClosure();
   }
 
+  Heap* heap_;
   DisallowHeapAllocation no_allocation_;
 };
 
@@ -7318,7 +7354,7 @@
   space_iterator_ = new SpaceIterator(heap_);
   switch (filtering_) {
     case kFilterUnreachable:
-      filter_ = new UnreachableObjectsFilter;
+      filter_ = new UnreachableObjectsFilter(heap_);
       break;
     default:
       break;
@@ -7863,9 +7899,9 @@
 #endif
 
 
-TranscendentalCache::SubCache::SubCache(Type t)
+TranscendentalCache::SubCache::SubCache(Isolate* isolate, Type t)
   : type_(t),
-    isolate_(Isolate::Current()) {
+    isolate_(isolate) {
   uint32_t in0 = 0xffffffffu;  // Bit-pattern for a NaN that isn't
   uint32_t in1 = 0xffffffffu;  // generated by the FPU.
   for (int i = 0; i < kCacheSize; i++) {
diff --git a/src/heap.h b/src/heap.h
index 4071ef6..94fbf46 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -2881,7 +2881,7 @@
   class SubCache {
     static const int kCacheSize = 512;
 
-    explicit SubCache(Type t);
+    explicit SubCache(Isolate* isolate, Type t);
 
     MUST_USE_RESULT inline MaybeObject* Get(double input);
 
@@ -2918,7 +2918,7 @@
     DISALLOW_COPY_AND_ASSIGN(SubCache);
   };
 
-  TranscendentalCache() {
+  explicit TranscendentalCache(Isolate* isolate) : isolate_(isolate) {
     for (int i = 0; i < kNumberOfCaches; ++i) caches_[i] = NULL;
   }
 
@@ -2936,6 +2936,7 @@
   // Allow access to the caches_ array as an ExternalReference.
   friend class ExternalReference;
 
+  Isolate* isolate_;
   SubCache* caches_[kNumberOfCaches];
   DISALLOW_COPY_AND_ASSIGN(TranscendentalCache);
 };
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index f6ee8dc..e371277 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -3668,7 +3668,7 @@
     Zone* zone, HValue* context, HValue* char_code) {
   if (FLAG_fold_constants && char_code->IsConstant()) {
     HConstant* c_code = HConstant::cast(char_code);
-    Isolate* isolate = Isolate::Current();
+    Isolate* isolate = zone->isolate();
     if (c_code->HasNumberValue()) {
       if (std::isfinite(c_code->DoubleValue())) {
         uint32_t code = c_code->NumberValueAsInteger32() & 0xffff;
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 0357805..a6d8915 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -2159,7 +2159,7 @@
 
   bool IsApplyFunction() const {
     return function_->code() ==
-        Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
+        function_->GetIsolate()->builtins()->builtin(Builtins::kFunctionApply);
   }
 
   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@@ -2629,7 +2629,7 @@
  public:
   static HCheckValue* New(Zone* zone, HValue* context,
                           HValue* value, Handle<JSFunction> target) {
-    bool in_new_space = Isolate::Current()->heap()->InNewSpace(*target);
+    bool in_new_space = zone->isolate()->heap()->InNewSpace(*target);
     HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
     return check;
   }
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index c42d035..25522e8 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -4554,7 +4554,6 @@
 
 
 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
-    Property* expr,
     HValue* object,
     SmallMapList* types,
     Handle<String> name) {
@@ -4655,15 +4654,15 @@
 
 
 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
-    Property* expr,
+    int position,
+    BailoutId ast_id,
     HValue* object,
     SmallMapList* types,
     Handle<String> name) {
-  HInstruction* instr = TryLoadPolymorphicAsMonomorphic(
-      expr, object, types, name);
+  HInstruction* instr = TryLoadPolymorphicAsMonomorphic(object, types, name);
   if (instr != NULL) {
-    instr->set_position(expr->position());
-    return ast_context()->ReturnInstruction(instr, expr->id());
+    instr->set_position(position);
+    return ast_context()->ReturnInstruction(instr, ast_id);
   }
 
   // Something did not match; must use a polymorphic load.
@@ -4695,7 +4694,7 @@
       if (lookup.IsField()) {
         HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
         HLoadNamedField* load = BuildLoadNamedField(compare, access);
-        load->set_position(expr->position());
+        load->set_position(position);
         AddInstruction(load);
         if (!ast_context()->IsEffect()) Push(load);
       } else if (lookup.IsConstant()) {
@@ -4726,22 +4725,23 @@
   if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
     FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
   } else {
-    HInstruction* load = BuildLoadNamedGeneric(object, name, expr);
-    load->set_position(expr->position());
+    HValue* context = environment()->context();
+    HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name);
+    load->set_position(position);
     AddInstruction(load);
     if (!ast_context()->IsEffect()) Push(load);
 
     if (join != NULL) {
       current_block()->Goto(join);
     } else {
-      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
       return;
     }
   }
 
   ASSERT(join != NULL);
-  join->SetJoinId(expr->id());
+  join->SetJoinId(ast_id);
   set_current_block(join);
   if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
 }
@@ -4751,8 +4751,7 @@
     int position,
     BailoutId assignment_id,
     HValue* object,
-    HValue* store_value,
-    HValue* result_value,
+    HValue* value,
     SmallMapList* types,
     Handle<String> name) {
   // Use monomorphic store if property lookup results in the same field index
@@ -4798,14 +4797,14 @@
   HInstruction* store;
   CHECK_ALIVE_OR_RETURN(
       store = BuildStoreNamedField(
-          checked_object, name, store_value, types->at(count - 1), &lookup),
+          checked_object, name, value, types->at(count - 1), &lookup),
       true);
-  if (!ast_context()->IsEffect()) Push(result_value);
+  if (!ast_context()->IsEffect()) Push(value);
   store->set_position(position);
   AddInstruction(store);
   Add<HSimulate>(assignment_id);
   if (!ast_context()->IsEffect()) Drop(1);
-  ast_context()->ReturnValue(result_value);
+  ast_context()->ReturnValue(value);
   return true;
 }
 
@@ -4814,13 +4813,11 @@
     int position,
     BailoutId assignment_id,
     HValue* object,
-    HValue* store_value,
-    HValue* result_value,
+    HValue* value,
     SmallMapList* types,
     Handle<String> name) {
   if (TryStorePolymorphicAsMonomorphic(
-          position, assignment_id, object,
-          store_value, result_value, types, name)) {
+          position, assignment_id, object, value, types, name)) {
     return;
   }
 
@@ -4847,11 +4844,11 @@
       set_current_block(if_true);
       HInstruction* instr;
       CHECK_ALIVE(instr = BuildStoreNamedField(
-          compare, name, store_value, map, &lookup));
+          compare, name, value, map, &lookup));
       instr->set_position(position);
       // Goto will add the HSimulate for the store.
       AddInstruction(instr);
-      if (!ast_context()->IsEffect()) Push(result_value);
+      if (!ast_context()->IsEffect()) Push(value);
       current_block()->Goto(join);
 
       set_current_block(if_false);
@@ -4864,13 +4861,13 @@
   if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
     FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
   } else {
-    HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value);
+    HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
     instr->set_position(position);
     AddInstruction(instr);
 
     if (join != NULL) {
       if (!ast_context()->IsEffect()) {
-        Push(result_value);
+        Push(value);
       }
       current_block()->Goto(join);
     } else {
@@ -4881,12 +4878,12 @@
         if (ast_context()->IsEffect()) {
           Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
         } else {
-          Push(result_value);
+          Push(value);
           Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
           Drop(1);
         }
       }
-      return ast_context()->ReturnValue(result_value);
+      return ast_context()->ReturnValue(value);
     }
   }
 
@@ -4915,7 +4912,7 @@
                        Deoptimizer::SOFT);
     }
     return BuildStoreNamed(expr, expr->id(), expr->position(),
-                           expr->AssignmentId(), prop, object, value, value);
+                           expr->AssignmentId(), prop, object, value);
   } else {
     // Keyed store.
     CHECK_ALIVE(VisitForValue(prop->key()));
@@ -4987,8 +4984,7 @@
                                              BailoutId assignment_id,
                                              Property* prop,
                                              HValue* object,
-                                             HValue* store_value,
-                                             HValue* result_value) {
+                                             HValue* value) {
   Literal* key = prop->key()->AsLiteral();
   Handle<String> name = Handle<String>::cast(key->value());
   ASSERT(!name.is_null());
@@ -5006,42 +5002,38 @@
     Handle<JSObject> holder;
     if (LookupSetter(map, name, &setter, &holder)) {
       AddCheckConstantFunction(holder, object, map);
-      // Don't try to inline if the result_value is different from the
-      // store_value. That case isn't handled yet by the inlining.
-      if (result_value == store_value &&
-          FLAG_inline_accessors &&
-          TryInlineSetter(setter, id, assignment_id, store_value)) {
+      if (FLAG_inline_accessors &&
+          TryInlineSetter(setter, id, assignment_id, value)) {
         return;
       }
       Drop(2);
       Add<HPushArgument>(object);
-      Add<HPushArgument>(store_value);
+      Add<HPushArgument>(value);
       instr = new(zone()) HCallConstantFunction(setter, 2);
     } else {
       Drop(2);
       CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
                                                      name,
-                                                     store_value,
+                                                     value,
                                                      map));
     }
   } else if (types != NULL && types->length() > 1) {
     Drop(2);
     return HandlePolymorphicStoreNamedField(
-        position, id, object,
-        store_value, result_value, types, name);
+        position, id, object, value, types, name);
   } else {
     Drop(2);
-    instr = BuildStoreNamedGeneric(object, name, store_value);
+    instr = BuildStoreNamedGeneric(object, name, value);
   }
 
-  if (!ast_context()->IsEffect()) Push(result_value);
+  if (!ast_context()->IsEffect()) Push(value);
   instr->set_position(position);
   AddInstruction(instr);
   if (instr->HasObservableSideEffects()) {
     Add<HSimulate>(id, REMOVABLE_SIMULATE);
   }
   if (!ast_context()->IsEffect()) Drop(1);
-  return ast_context()->ReturnValue(result_value);
+  return ast_context()->ReturnValue(value);
 }
 
 
@@ -5130,34 +5122,7 @@
       // Named property.
       CHECK_ALIVE(VisitForValue(prop->obj()));
       HValue* object = Top();
-
-      Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
-      Handle<Map> map;
-      HInstruction* load = NULL;
-      SmallMapList* types = prop->GetReceiverTypes();
-      bool monomorphic = prop->IsMonomorphic();
-      if (monomorphic) {
-        map = types->first();
-        // We can't generate code for a monomorphic dict mode load so
-        // just pretend it is not monomorphic.
-        monomorphic = CanInlinePropertyAccess(*map);
-      }
-      if (monomorphic) {
-        Handle<JSFunction> getter;
-        Handle<JSObject> holder;
-        if (LookupGetter(map, name, &getter, &holder)) {
-          load = BuildCallGetter(object, map, getter, holder);
-        } else {
-          load = BuildLoadNamedMonomorphic(object, name, prop, map);
-        }
-      } else if (types != NULL && types->length() > 1) {
-        load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name);
-      }
-      if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
-      PushAndAdd(load);
-      if (load->HasObservableSideEffects()) {
-        Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
-      }
+      PushLoad(prop, object, expr->position());
 
       CHECK_ALIVE(VisitForValue(expr->value()));
       HValue* right = Pop();
@@ -5170,7 +5135,7 @@
       }
 
       return BuildStoreNamed(expr, expr->id(), expr->position(),
-                             expr->AssignmentId(), prop, object, instr, instr);
+                             expr->AssignmentId(), prop, object, instr);
     } else {
       // Keyed property.
       CHECK_ALIVE(VisitForValue(prop->obj()));
@@ -5396,7 +5361,7 @@
     Handle<String> name,
     Property* expr) {
   if (expr->IsUninitialized()) {
-    Add<HDeoptimize>("Insufficient feedback for generic named load",
+    Add<HDeoptimize>("Insufficient type feedback for generic named load",
                      Deoptimizer::SOFT);
   }
   HValue* context = environment()->context();
@@ -5418,7 +5383,6 @@
 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
     HValue* object,
     Handle<String> name,
-    Property* expr,
     Handle<Map> map) {
   // Handle a load from a known field.
   ASSERT(!map->is_dictionary_map());
@@ -5471,7 +5435,8 @@
   }
 
   // No luck, do a generic load.
-  return BuildLoadNamedGeneric(object, name, expr);
+  HValue* context = environment()->context();
+  return new(zone()) HLoadNamedGeneric(context, object, name);
 }
 
 
@@ -5710,7 +5675,7 @@
 
   // Deopt if none of the cases matched.
   NoObservableSideEffectsScope scope(this);
-  FinishExitWithHardDeoptimization("Unknown type in polymorphic element access",
+  FinishExitWithHardDeoptimization("Unknown map in polymorphic element access",
                                    join);
   set_current_block(join);
   return is_store ? NULL : Pop();
@@ -5747,13 +5712,13 @@
   } else {
     if (is_store) {
       if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
-        Add<HDeoptimize>("Insufficient feedback for keyed store",
+        Add<HDeoptimize>("Insufficient type feedback for keyed store",
                          Deoptimizer::SOFT);
       }
       instr = BuildStoreKeyedGeneric(obj, key, val);
     } else {
       if (expr->AsProperty()->IsUninitialized()) {
-        Add<HDeoptimize>("Insufficient feedback for keyed load",
+        Add<HDeoptimize>("Insufficient type feedback for keyed load",
                          Deoptimizer::SOFT);
       }
       instr = BuildLoadKeyedGeneric(obj, key);
@@ -5858,15 +5823,18 @@
 }
 
 
-void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
-  ASSERT(!HasStackOverflow());
-  ASSERT(current_block() != NULL);
-  ASSERT(current_block()->HasPredecessor());
+void HOptimizedGraphBuilder::PushLoad(Property* expr,
+                                      HValue* object,
+                                      int position) {
+  ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
+  Push(object);
+  BuildLoad(expr, position, expr->LoadId());
+}
 
-  if (TryArgumentsAccess(expr)) return;
 
-  CHECK_ALIVE(VisitForValue(expr->obj()));
-
+void HOptimizedGraphBuilder::BuildLoad(Property* expr,
+                                       int position,
+                                       BailoutId ast_id) {
   HInstruction* instr = NULL;
   if (expr->IsStringLength()) {
     HValue* string = Pop();
@@ -5908,14 +5876,18 @@
       Handle<JSObject> holder;
       if (LookupGetter(map, name, &getter, &holder)) {
         AddCheckConstantFunction(holder, Top(), map);
-        if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return;
+        if (FLAG_inline_accessors &&
+            TryInlineGetter(getter, ast_id, expr->LoadId())) {
+          return;
+        }
         Add<HPushArgument>(Pop());
         instr = new(zone()) HCallConstantFunction(getter, 1);
       } else {
-        instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map);
+        instr = BuildLoadNamedMonomorphic(Pop(), name, map);
       }
     } else if (types != NULL && types->length() > 1) {
-      return HandlePolymorphicLoadNamedField(expr, Pop(), types, name);
+      return HandlePolymorphicLoadNamedField(
+          position, ast_id, Pop(), types, name);
     } else {
       instr = BuildLoadNamedGeneric(Pop(), name, expr);
     }
@@ -5928,22 +5900,34 @@
 
     bool has_side_effects = false;
     HValue* load = HandleKeyedElementAccess(
-        obj, key, NULL, expr, expr->id(), expr->position(),
+        obj, key, NULL, expr, ast_id, position,
         false,  // is_store
         &has_side_effects);
     if (has_side_effects) {
       if (ast_context()->IsEffect()) {
-        Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
       } else {
         Push(load);
-        Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
         Drop(1);
       }
     }
     return ast_context()->ReturnValue(load);
   }
-  instr->set_position(expr->position());
-  return ast_context()->ReturnInstruction(instr, expr->id());
+  instr->set_position(position);
+  return ast_context()->ReturnInstruction(instr, ast_id);
+}
+
+
+void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
+  ASSERT(!HasStackOverflow());
+  ASSERT(current_block() != NULL);
+  ASSERT(current_block()->HasPredecessor());
+
+  if (TryArgumentsAccess(expr)) return;
+
+  CHECK_ALIVE(VisitForValue(expr->obj()));
+  BuildLoad(expr, expr->position(), expr->id());
 }
 
 
@@ -6620,13 +6604,14 @@
 
 
 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
-                                             Property* prop) {
+                                             BailoutId ast_id,
+                                             BailoutId return_id) {
   return TryInline(CALL_AS_METHOD,
                    getter,
                    0,
                    NULL,
-                   prop->id(),
-                   prop->LoadId(),
+                   ast_id,
+                   return_id,
                    GETTER_CALL_RETURN);
 }
 
@@ -7576,38 +7561,25 @@
 
       CHECK_ALIVE(VisitForValue(prop->obj()));
       HValue* object = Top();
-
-      Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
-      Handle<Map> map;
-      HInstruction* load = NULL;
-      bool monomorphic = prop->IsMonomorphic();
-      SmallMapList* types = prop->GetReceiverTypes();
-      if (monomorphic) {
-        map = types->first();
-        monomorphic = CanInlinePropertyAccess(*map);
-      }
-      if (monomorphic) {
-        Handle<JSFunction> getter;
-        Handle<JSObject> holder;
-        if (LookupGetter(map, name, &getter, &holder)) {
-          load = BuildCallGetter(object, map, getter, holder);
-        } else {
-          load = BuildLoadNamedMonomorphic(object, name, prop, map);
-        }
-      } else if (types != NULL && types->length() > 1) {
-        load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name);
-      }
-      if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
-      PushAndAdd(load);
-      if (load->HasObservableSideEffects()) {
-        Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
-      }
+      PushLoad(prop, object, expr->position());
 
       after = BuildIncrement(returns_original_input, expr);
-      HValue* result = returns_original_input ? Pop() : after;
+
+      if (returns_original_input) {
+        HValue* result = Pop();
+        HValue* object = Pop();
+        environment()->SetExpressionStackAt(0, result);
+        {
+          EffectContext for_effect(this);
+          Push(object);
+          Push(after);
+          return BuildStoreNamed(expr, expr->id(), expr->position(),
+                                 expr->AssignmentId(), prop, object, after);
+        }
+      }
 
       return BuildStoreNamed(expr, expr->id(), expr->position(),
-                             expr->AssignmentId(), prop, object, after, result);
+                             expr->AssignmentId(), prop, object, after);
     } else {
       // Keyed property.
       if (returns_original_input) Push(graph()->GetConstantUndefined());
@@ -7768,13 +7740,13 @@
   }
 
   if (left_type->Is(Type::None())) {
-    Add<HDeoptimize>("Insufficient type feedback for left side",
+    Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
                      Deoptimizer::SOFT);
     // TODO(rossberg): we should be able to get rid of non-continuous defaults.
     left_type = handle(Type::Any(), isolate());
   }
   if (right_type->Is(Type::None())) {
-    Add<HDeoptimize>("Insufficient type feedback for right side",
+    Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
                      Deoptimizer::SOFT);
     right_type = handle(Type::Any(), isolate());
   }
@@ -8125,7 +8097,8 @@
   // Cases handled below depend on collected type feedback. They should
   // soft deoptimize when there is no type feedback.
   if (combined_type->Is(Type::None())) {
-    Add<HDeoptimize>("insufficient type feedback for combined type",
+    Add<HDeoptimize>("Insufficient type feedback for combined type "
+                     "of binary operation",
                      Deoptimizer::SOFT);
     combined_type = left_type = right_type = handle(Type::Any(), isolate());
   }
diff --git a/src/hydrogen.h b/src/hydrogen.h
index cdca1bd..0e1ed13 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1911,7 +1911,9 @@
 
   bool TryInlineCall(Call* expr, bool drop_extra = false);
   bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
-  bool TryInlineGetter(Handle<JSFunction> getter, Property* prop);
+  bool TryInlineGetter(Handle<JSFunction> getter,
+                       BailoutId ast_id,
+                       BailoutId return_id);
   bool TryInlineSetter(Handle<JSFunction> setter,
                        BailoutId id,
                        BailoutId assignment_id,
@@ -1939,26 +1941,24 @@
 
   void HandlePropertyAssignment(Assignment* expr);
   void HandleCompoundAssignment(Assignment* expr);
-  void HandlePolymorphicLoadNamedField(Property* expr,
+  void HandlePolymorphicLoadNamedField(int position,
+                                       BailoutId return_id,
                                        HValue* object,
                                        SmallMapList* types,
                                        Handle<String> name);
-  HInstruction* TryLoadPolymorphicAsMonomorphic(Property* expr,
-                                                HValue* object,
+  HInstruction* TryLoadPolymorphicAsMonomorphic(HValue* object,
                                                 SmallMapList* types,
                                                 Handle<String> name);
   void HandlePolymorphicStoreNamedField(int position,
                                         BailoutId assignment_id,
                                         HValue* object,
                                         HValue* value,
-                                        HValue* result,
                                         SmallMapList* types,
                                         Handle<String> name);
   bool TryStorePolymorphicAsMonomorphic(int position,
                                         BailoutId assignment_id,
                                         HValue* object,
                                         HValue* value,
-                                        HValue* result,
                                         SmallMapList* types,
                                         Handle<String> name);
   void HandlePolymorphicCallNamed(Call* expr,
@@ -2029,19 +2029,24 @@
                                 Handle<JSObject> holder);
   HInstruction* BuildLoadNamedMonomorphic(HValue* object,
                                           Handle<String> name,
-                                          Property* expr,
                                           Handle<Map> map);
 
   HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
 
+  void BuildLoad(Property* property,
+                 int position,
+                 BailoutId ast_id);
+  void PushLoad(Property* property,
+                HValue* object,
+                int position);
+
   void BuildStoreNamed(Expression* expression,
                        BailoutId id,
                        int position,
                        BailoutId assignment_id,
                        Property* prop,
                        HValue* object,
-                       HValue* store_value,
-                       HValue* result_value);
+                       HValue* value);
 
   HInstruction* BuildStoreNamedField(HValue* object,
                                      Handle<String> name,
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index bd058f8..065f02c 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -48,6 +48,7 @@
       allow_stub_calls_(true),
       has_frame_(false) {
   if (isolate() != NULL) {
+    // TODO(titzer): should we just use a null handle here instead?
     code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
                                   isolate());
   }
diff --git a/src/ic.cc b/src/ic.cc
index 7f27d3f..190fdb1 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -375,20 +375,22 @@
 }
 
 
-void IC::Clear(Address address) {
+void IC::Clear(Isolate* isolate, Address address) {
   Code* target = GetTargetAtAddress(address);
 
   // Don't clear debug break inline cache as it will remove the break point.
   if (target->is_debug_stub()) return;
 
   switch (target->kind()) {
-    case Code::LOAD_IC: return LoadIC::Clear(address, target);
-    case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
-    case Code::STORE_IC: return StoreIC::Clear(address, target);
-    case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
+    case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target);
+    case Code::KEYED_LOAD_IC:
+      return KeyedLoadIC::Clear(isolate, address, target);
+    case Code::STORE_IC: return StoreIC::Clear(isolate, address, target);
+    case Code::KEYED_STORE_IC:
+      return KeyedStoreIC::Clear(isolate, address, target);
     case Code::CALL_IC: return CallIC::Clear(address, target);
     case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
-    case Code::COMPARE_IC: return CompareIC::Clear(address, target);
+    case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target);
     case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target);
     case Code::BINARY_OP_IC:
     case Code::TO_BOOLEAN_IC:
@@ -404,7 +406,7 @@
   if (target->ic_state() == UNINITIALIZED) return;
   bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
   Code* code =
-      Isolate::Current()->stub_cache()->FindCallInitialize(
+      target->GetIsolate()->stub_cache()->FindCallInitialize(
           target->arguments_count(),
           contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET,
           target->kind());
@@ -412,40 +414,40 @@
 }
 
 
-void KeyedLoadIC::Clear(Address address, Code* target) {
+void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) {
   if (target->ic_state() == UNINITIALIZED) return;
   // Make sure to also clear the map used in inline fast cases.  If we
   // do not clear these maps, cached code can keep objects alive
   // through the embedded maps.
-  SetTargetAtAddress(address, *initialize_stub());
+  SetTargetAtAddress(address, *initialize_stub(isolate));
 }
 
 
-void LoadIC::Clear(Address address, Code* target) {
+void LoadIC::Clear(Isolate* isolate, Address address, Code* target) {
   if (target->ic_state() == UNINITIALIZED) return;
-  SetTargetAtAddress(address, *initialize_stub());
+  SetTargetAtAddress(address, *initialize_stub(isolate));
 }
 
 
-void StoreIC::Clear(Address address, Code* target) {
+void StoreIC::Clear(Isolate* isolate, Address address, Code* target) {
   if (target->ic_state() == UNINITIALIZED) return;
   SetTargetAtAddress(address,
       (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
-        ? *initialize_stub_strict()
-        : *initialize_stub());
+        ? *initialize_stub_strict(isolate)
+        : *initialize_stub(isolate));
 }
 
 
-void KeyedStoreIC::Clear(Address address, Code* target) {
+void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) {
   if (target->ic_state() == UNINITIALIZED) return;
   SetTargetAtAddress(address,
       (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
-        ? *initialize_stub_strict()
-        : *initialize_stub());
+        ? *initialize_stub_strict(isolate)
+        : *initialize_stub(isolate));
 }
 
 
-void CompareIC::Clear(Address address, Code* target) {
+void CompareIC::Clear(Isolate* isolate, Address address, Code* target) {
   ASSERT(target->major_key() == CodeStub::CompareIC);
   CompareIC::State handler_state;
   Token::Value op;
@@ -453,7 +455,7 @@
                                 &handler_state, &op);
   // Only clear CompareICs that can retain objects.
   if (handler_state != KNOWN_OBJECT) return;
-  SetTargetAtAddress(address, GetRawUninitialized(op));
+  SetTargetAtAddress(address, GetRawUninitialized(isolate, op));
   PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
 }
 
@@ -564,7 +566,7 @@
   // the element if so.
   uint32_t index;
   if (name->AsArrayIndex(&index)) {
-    Handle<Object> result = Object::GetElement(object, index);
+    Handle<Object> result = Object::GetElement(isolate(), object, index);
     RETURN_IF_EMPTY_HANDLE(isolate(), result);
     if (result->IsJSFunction()) return *result;
 
@@ -1709,22 +1711,30 @@
   }
 
   LookupResult lookup(isolate());
-  if (LookupForWrite(receiver, name, value, &lookup, &state)) {
-    if (FLAG_use_ic) {
-      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
-    }
-  } else if (strict_mode == kStrictMode &&
-             !(lookup.IsProperty() && lookup.IsReadOnly()) &&
-             IsUndeclaredGlobal(object)) {
+  bool can_store = LookupForWrite(receiver, name, value, &lookup, &state);
+  if (!can_store &&
+      strict_mode == kStrictMode &&
+      !(lookup.IsProperty() && lookup.IsReadOnly()) &&
+      IsUndeclaredGlobal(object)) {
     // Strict mode doesn't allow setting non-existent global property.
     return ReferenceError("not_defined", name);
-  } else if (FLAG_use_ic &&
-             (!name->IsCacheable(isolate()) ||
-              lookup.IsNormal() ||
-              (lookup.IsField() && lookup.CanHoldValue(value)))) {
-    Handle<Code> stub = strict_mode == kStrictMode
-        ? generic_stub_strict() : generic_stub();
-    set_target(*stub);
+  }
+  if (FLAG_use_ic) {
+    if (state == UNINITIALIZED) {
+      Handle<Code> stub = (strict_mode == kStrictMode)
+          ? pre_monomorphic_stub_strict()
+          : pre_monomorphic_stub();
+      set_target(*stub);
+      TRACE_IC("StoreIC", name, state, *stub);
+    } else if (can_store) {
+      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
+    } else if (!name->IsCacheable(isolate()) ||
+               lookup.IsNormal() ||
+               (lookup.IsField() && lookup.CanHoldValue(value))) {
+      Handle<Code> stub = (strict_mode == kStrictMode) ? generic_stub_strict()
+                                                       : generic_stub();
+      set_target(*stub);
+    }
   }
 
   // Set the property.
@@ -2771,10 +2781,10 @@
 }
 
 
-Code* CompareIC::GetRawUninitialized(Token::Value op) {
+Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
   ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
   Code* code = NULL;
-  CHECK(stub.FindCodeInCache(&code, Isolate::Current()));
+  CHECK(stub.FindCodeInCache(&code, isolate));
   return code;
 }
 
diff --git a/src/ic.h b/src/ic.h
index fcf0de5..5c883cd 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -102,7 +102,7 @@
   static State StateFrom(Code* target, Object* receiver, Object* name);
 
   // Clear the inline cache to initial state.
-  static void Clear(Address address);
+  static void Clear(Isolate* isolate, Address address);
 
   // Computes the reloc info for this IC. This is a fairly expensive
   // operation as it has to search through the heap to find the code
@@ -420,14 +420,14 @@
 
  private:
   // Stub accessors.
-  static Handle<Code> initialize_stub() {
-    return Isolate::Current()->builtins()->LoadIC_Initialize();
+  static Handle<Code> initialize_stub(Isolate* isolate) {
+    return isolate->builtins()->LoadIC_Initialize();
   }
   virtual Handle<Code> pre_monomorphic_stub() {
     return isolate()->builtins()->LoadIC_PreMonomorphic();
   }
 
-  static void Clear(Address address, Code* target);
+  static void Clear(Isolate* isolate, Address address, Code* target);
 
   friend class IC;
 };
@@ -496,8 +496,8 @@
 
  private:
   // Stub accessors.
-  static Handle<Code> initialize_stub() {
-    return Isolate::Current()->builtins()->KeyedLoadIC_Initialize();
+  static Handle<Code> initialize_stub(Isolate* isolate) {
+    return isolate->builtins()->KeyedLoadIC_Initialize();
   }
   virtual Handle<Code> pre_monomorphic_stub() {
     return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
@@ -512,7 +512,7 @@
     return isolate()->builtins()->KeyedLoadIC_String();
   }
 
-  static void Clear(Address address, Code* target);
+  static void Clear(Isolate* isolate, Address address, Code* target);
 
   friend class IC;
 };
@@ -527,6 +527,9 @@
   // Code generators for stub routines. Only called once at startup.
   static void GenerateSlow(MacroAssembler* masm);
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
+  static void GeneratePreMonomorphic(MacroAssembler* masm) {
+    GenerateMiss(masm);
+  }
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateMegamorphic(MacroAssembler* masm,
                                   StrictModeFlag strict_mode);
@@ -558,6 +561,12 @@
   virtual Handle<Code> generic_stub_strict() const {
     return isolate()->builtins()->StoreIC_Generic_Strict();
   }
+  virtual Handle<Code> pre_monomorphic_stub() const {
+    return isolate()->builtins()->StoreIC_PreMonomorphic();
+  }
+  virtual Handle<Code> pre_monomorphic_stub_strict() const {
+    return isolate()->builtins()->StoreIC_PreMonomorphic_Strict();
+  }
   virtual Handle<Code> global_proxy_stub() {
     return isolate()->builtins()->StoreIC_GlobalProxy();
   }
@@ -601,13 +610,13 @@
     IC::set_target(code);
   }
 
-  static Handle<Code> initialize_stub() {
-    return Isolate::Current()->builtins()->StoreIC_Initialize();
+  static Handle<Code> initialize_stub(Isolate* isolate) {
+    return isolate->builtins()->StoreIC_Initialize();
   }
-  static Handle<Code> initialize_stub_strict() {
-    return Isolate::Current()->builtins()->StoreIC_Initialize_Strict();
+  static Handle<Code> initialize_stub_strict(Isolate* isolate) {
+    return isolate->builtins()->StoreIC_Initialize_Strict();
   }
-  static void Clear(Address address, Code* target);
+  static void Clear(Isolate* isolate, Address address, Code* target);
 
   friend class IC;
 };
@@ -643,6 +652,9 @@
   static void GenerateInitialize(MacroAssembler* masm) {
     GenerateMiss(masm, MISS);
   }
+  static void GeneratePreMonomorphic(MacroAssembler* masm) {
+    GenerateMiss(masm, MISS);
+  }
   static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
   static void GenerateSlow(MacroAssembler* masm);
   static void GenerateRuntimeSetProperty(MacroAssembler* masm,
@@ -660,6 +672,12 @@
                                                Handle<Object> value);
   virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
 
+  virtual Handle<Code> pre_monomorphic_stub() const {
+    return isolate()->builtins()->KeyedStoreIC_PreMonomorphic();
+  }
+  virtual Handle<Code> pre_monomorphic_stub_strict() const {
+    return isolate()->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
+  }
   virtual Handle<Code> megamorphic_stub() {
     return isolate()->builtins()->KeyedStoreIC_Generic();
   }
@@ -685,11 +703,11 @@
   }
 
   // Stub accessors.
-  static Handle<Code> initialize_stub() {
-    return Isolate::Current()->builtins()->KeyedStoreIC_Initialize();
+  static Handle<Code> initialize_stub(Isolate* isolate) {
+    return isolate->builtins()->KeyedStoreIC_Initialize();
   }
-  static Handle<Code> initialize_stub_strict() {
-    return Isolate::Current()->builtins()->KeyedStoreIC_Initialize_Strict();
+  static Handle<Code> initialize_stub_strict(Isolate* isolate) {
+    return isolate->builtins()->KeyedStoreIC_Initialize_Strict();
   }
   Handle<Code> generic_stub() const {
     return isolate()->builtins()->KeyedStoreIC_Generic();
@@ -701,7 +719,7 @@
     return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
   }
 
-  static void Clear(Address address, Code* target);
+  static void Clear(Isolate* isolate, Address address, Code* target);
 
   KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
                                     Handle<Object> key,
@@ -807,9 +825,9 @@
   bool strict() const { return op_ == Token::EQ_STRICT; }
   Condition GetCondition() const { return ComputeCondition(op_); }
 
-  static Code* GetRawUninitialized(Token::Value op);
+  static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
 
-  static void Clear(Address address, Code* target);
+  static void Clear(Isolate* isolate, Address address, Code* target);
 
   Token::Value op_;
 
diff --git a/src/isolate-inl.h b/src/isolate-inl.h
index ddb1580..5e2c8c2 100644
--- a/src/isolate-inl.h
+++ b/src/isolate-inl.h
@@ -36,7 +36,9 @@
 namespace internal {
 
 
-SaveContext::SaveContext(Isolate* isolate) : prev_(isolate->save_context()) {
+SaveContext::SaveContext(Isolate* isolate)
+  : isolate_(isolate),
+    prev_(isolate->save_context()) {
   if (isolate->context() != NULL) {
     context_ = Handle<Context>(isolate->context());
   }
diff --git a/src/isolate.cc b/src/isolate.cc
index 39d75e2..2c15717 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -567,11 +567,11 @@
   if (stack_trace_nesting_level_ == 0) {
     stack_trace_nesting_level_++;
     HeapStringAllocator allocator;
-    StringStream::ClearMentionedObjectCache();
+    StringStream::ClearMentionedObjectCache(this);
     StringStream accumulator(&allocator);
     incomplete_message_ = &accumulator;
     PrintStack(&accumulator);
-    Handle<String> stack_trace = accumulator.ToString();
+    Handle<String> stack_trace = accumulator.ToString(this);
     incomplete_message_ = NULL;
     stack_trace_nesting_level_ = 0;
     return stack_trace;
@@ -871,7 +871,7 @@
       allocator = preallocated_message_space_;
     }
 
-    StringStream::ClearMentionedObjectCache();
+    StringStream::ClearMentionedObjectCache(this);
     StringStream accumulator(allocator);
     incomplete_message_ = &accumulator;
     PrintStack(&accumulator);
@@ -915,7 +915,7 @@
   }
   // The MentionedObjectCache is not GC-proof at the moment.
   DisallowHeapAllocation no_gc;
-  ASSERT(StringStream::IsMentionedObjectCacheClear());
+  ASSERT(StringStream::IsMentionedObjectCacheClear(this));
 
   // Avoid printing anything if there are no frames.
   if (c_entry_fp(thread_local_top()) == 0) return;
@@ -928,7 +928,7 @@
       "\n==== Details ================================================\n\n");
   PrintFrames(this, accumulator, StackFrame::DETAILS);
 
-  accumulator->PrintMentionedObjectCache();
+  accumulator->PrintMentionedObjectCache(this);
   accumulator->Add("=====================\n\n");
 }
 
@@ -2187,7 +2187,7 @@
   string_tracker_ = new StringTracker();
   string_tracker_->isolate_ = this;
   compilation_cache_ = new CompilationCache(this);
-  transcendental_cache_ = new TranscendentalCache();
+  transcendental_cache_ = new TranscendentalCache(this);
   keyed_lookup_cache_ = new KeyedLookupCache();
   context_slot_cache_ = new ContextSlotCache();
   descriptor_lookup_cache_ = new DescriptorLookupCache();
@@ -2272,7 +2272,7 @@
 
   // If we are deserializing, read the state into the now-empty heap.
   if (!create_heap_objects) {
-    des->Deserialize();
+    des->Deserialize(this);
   }
   stub_cache_->Initialize();
 
diff --git a/src/isolate.h b/src/isolate.h
index 8be8af7..741c4c0 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1396,15 +1396,8 @@
   inline explicit SaveContext(Isolate* isolate);
 
   ~SaveContext() {
-    if (context_.is_null()) {
-      Isolate* isolate = Isolate::Current();
-      isolate->set_context(NULL);
-      isolate->set_save_context(prev_);
-    } else {
-      Isolate* isolate = context_->GetIsolate();
-      isolate->set_context(*context_);
-      isolate->set_save_context(prev_);
-    }
+    isolate_->set_context(context_.is_null() ? NULL : *context_);
+    isolate_->set_save_context(prev_);
   }
 
   Handle<Context> context() { return context_; }
@@ -1416,6 +1409,7 @@
   }
 
  private:
+  Isolate* isolate_;
   Handle<Context> context_;
   SaveContext* prev_;
   Address c_entry_fp_;
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index 2de1401..c6ea288 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -602,12 +602,12 @@
     Handle<JSArray> object, int length) {
   for (int i = 0; i < length; i++) {
     if (i > 0) Append(',');
-    Handle<Object> element = Object::GetElement(object, i);
+    Handle<Object> element = Object::GetElement(isolate_, object, i);
     RETURN_IF_EMPTY_HANDLE_VALUE(isolate_, element, EXCEPTION);
     if (element->IsUndefined()) {
       AppendAscii("null");
     } else {
-      Result result = SerializeElement(object->GetIsolate(), element, i);
+      Result result = SerializeElement(isolate_, element, i);
       if (result == SUCCESS) continue;
       if (result == UNCHANGED) {
         AppendAscii("null");
@@ -678,9 +678,10 @@
         key_handle = factory_->NumberToString(Handle<Object>(key, isolate_));
         uint32_t index;
         if (key->IsSmi()) {
-          property = Object::GetElement(object, Smi::cast(key)->value());
+          property = Object::GetElement(
+              isolate_, object, Smi::cast(key)->value());
         } else if (key_handle->AsArrayIndex(&index)) {
-          property = Object::GetElement(object, index);
+          property = Object::GetElement(isolate_, object, index);
         } else {
           property = GetProperty(isolate_, object, key_handle);
         }
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 0ce10b8..5c79477 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -1869,7 +1869,7 @@
   for (int i = j; i < kSize; i++) {
     templ[i] = bit;
   }
-  Factory* factory = Isolate::Current()->factory();
+  Factory* factory = masm->zone()->isolate()->factory();
   // TODO(erikcorry): Cache these.
   Handle<ByteArray> ba = factory->NewByteArray(kSize, TENURED);
   for (int i = 0; i < kSize; i++) {
@@ -2548,7 +2548,7 @@
                                     RegExpCompiler* compiler,
                                     int characters_filled_in,
                                     bool not_at_start) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = compiler->macro_assembler()->zone()->isolate();
   ASSERT(characters_filled_in < details->characters());
   int characters = details->characters();
   int char_mask;
@@ -3246,8 +3246,8 @@
                             Trace* trace,
                             bool first_element_checked,
                             int* checked_up_to) {
-  Isolate* isolate = Isolate::Current();
   RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  Isolate* isolate = assembler->zone()->isolate();
   bool ascii = compiler->ascii();
   Label* backtrack = trace->backtrack();
   QuickCheckDetails* quick_check = trace->quick_check_performed();
@@ -3820,7 +3820,7 @@
     return true;
   }
 
-  Factory* factory = Isolate::Current()->factory();
+  Factory* factory = masm->zone()->isolate()->factory();
   Handle<ByteArray> boolean_skip_table = factory->NewByteArray(kSize, TENURED);
   int skip_distance = GetSkipTable(
       min_lookahead, max_lookahead, boolean_skip_table);
@@ -5292,7 +5292,7 @@
 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges,
                                         bool is_ascii,
                                         Zone* zone) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = zone->isolate();
   uc16 bottom = from();
   uc16 top = to();
   if (is_ascii && !RangeContainsLatin1Equivalents(*this)) {
@@ -5680,7 +5680,7 @@
 
 
 void Analysis::EnsureAnalyzed(RegExpNode* that) {
-  StackLimitCheck check(Isolate::Current());
+  StackLimitCheck check(that->zone()->isolate());
   if (check.HasOverflowed()) {
     fail("Stack overflow");
     return;
diff --git a/src/liveedit.cc b/src/liveedit.cc
index b260c81..7df17ed 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -631,8 +631,8 @@
 
 // Wraps any object into a OpaqueReference, that will hide the object
 // from JavaScript.
-static Handle<JSValue> WrapInJSValue(Handle<Object> object) {
-  Isolate* isolate = Isolate::Current();
+static Handle<JSValue> WrapInJSValue(Handle<HeapObject> object) {
+  Isolate* isolate = object->GetIsolate();
   Handle<JSFunction> constructor = isolate->opaque_reference_function();
   Handle<JSValue> result =
       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
@@ -662,8 +662,8 @@
 template<typename S>
 class JSArrayBasedStruct {
  public:
-  static S Create() {
-    Factory* factory = Isolate::Current()->factory();
+  static S Create(Isolate* isolate) {
+    Factory* factory = isolate->factory();
     Handle<JSArray> array = factory->NewJSArray(S::kSize_);
     return S(array);
   }
@@ -691,7 +691,7 @@
                         Handle<Smi>(Smi::FromInt(value), isolate()));
   }
   Object* GetField(int field_position) {
-    return array_->GetElementNoExceptionThrown(field_position);
+    return array_->GetElementNoExceptionThrown(isolate(), field_position);
   }
   int GetSmiValueField(int field_position) {
     Object* res = GetField(field_position);
@@ -724,7 +724,7 @@
     this->SetSmiValueField(kParentIndexOffset_, parent_index);
   }
   void SetFunctionCode(Handle<Code> function_code,
-      Handle<Object> code_scope_info) {
+      Handle<HeapObject> code_scope_info) {
     Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
     this->SetField(kCodeOffset_, code_wrapper);
 
@@ -788,7 +788,8 @@
  public:
   static bool IsInstance(Handle<JSArray> array) {
     return array->length() == Smi::FromInt(kSize_) &&
-        array->GetElementNoExceptionThrown(kSharedInfoOffset_)->IsJSValue();
+        array->GetElementNoExceptionThrown(
+            array->GetIsolate(), kSharedInfoOffset_)->IsJSValue();
   }
 
   explicit SharedInfoWrapper(Handle<JSArray> array)
@@ -832,7 +833,7 @@
 
   void FunctionStarted(FunctionLiteral* fun) {
     HandleScope scope(isolate());
-    FunctionInfoWrapper info = FunctionInfoWrapper::Create();
+    FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate());
     info.SetInitialProperties(fun->name(), fun->start_position(),
                               fun->end_position(), fun->parameter_count(),
                               fun->materialized_literal_count(),
@@ -846,7 +847,8 @@
     HandleScope scope(isolate());
     FunctionInfoWrapper info =
         FunctionInfoWrapper::cast(
-            result_->GetElementNoExceptionThrown(current_parent_index_));
+            result_->GetElementNoExceptionThrown(
+                isolate(), current_parent_index_));
     current_parent_index_ = info.GetParentIndex();
   }
 
@@ -855,10 +857,10 @@
   void FunctionCode(Handle<Code> function_code) {
     FunctionInfoWrapper info =
         FunctionInfoWrapper::cast(
-            result_->GetElementNoExceptionThrown(current_parent_index_));
+            result_->GetElementNoExceptionThrown(
+                isolate(), current_parent_index_));
     info.SetFunctionCode(function_code,
-                         Handle<Object>(isolate()->heap()->null_value(),
-                                        isolate()));
+                         Handle<HeapObject>(isolate()->heap()->null_value()));
   }
 
   // Saves full information about a function: its code, its scope info
@@ -870,9 +872,10 @@
     }
     FunctionInfoWrapper info =
         FunctionInfoWrapper::cast(
-            result_->GetElementNoExceptionThrown(current_parent_index_));
+            result_->GetElementNoExceptionThrown(
+                isolate(), current_parent_index_));
     info.SetFunctionCode(Handle<Code>(shared->code()),
-                         Handle<Object>(shared->scope_info(), isolate()));
+                         Handle<HeapObject>(shared->scope_info()));
     info.SetSharedFunctionInfo(shared);
 
     Handle<Object> scope_info_list(SerializeFunctionScope(scope, zone),
@@ -935,7 +938,7 @@
 
 JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
                                      Handle<String> source) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = script->GetIsolate();
 
   FunctionInfoListener listener(isolate);
   Handle<Object> original_source =
@@ -1001,12 +1004,14 @@
 
 
 void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
-  HandleScope scope(array->GetIsolate());
+  Isolate* isolate = array->GetIsolate();
+  HandleScope scope(isolate);
   int len = GetArrayLength(array);
   for (int i = 0; i < len; i++) {
     Handle<SharedFunctionInfo> info(
-        SharedFunctionInfo::cast(array->GetElementNoExceptionThrown(i)));
-    SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
+        SharedFunctionInfo::cast(
+            array->GetElementNoExceptionThrown(isolate, i)));
+    SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
     Handle<String> name_handle(String::cast(info->name()));
     info_wrapper.SetProperties(name_handle, info->start_position(),
                                info->end_position(), info);
@@ -1242,34 +1247,48 @@
 }
 
 
-class DependentFunctionFilter : public OptimizedFunctionFilter {
- public:
-  explicit DependentFunctionFilter(
-      SharedFunctionInfo* function_info)
-      : function_info_(function_info) {}
-
-  virtual bool TakeFunction(JSFunction* function) {
-    return (function->shared() == function_info_ ||
-            IsInlined(function, function_info_));
-  }
-
- private:
-  SharedFunctionInfo* function_info_;
-};
-
-
 static void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) {
-  DisallowHeapAllocation no_allocation;
+  // Marks code that shares the same shared function info or has inlined
+  // code that shares the same function info.
+  class DependentFunctionMarker: public OptimizedFunctionVisitor {
+   public:
+    SharedFunctionInfo* shared_info_;
+    bool found_;
 
-  DependentFunctionFilter filter(function_info);
-  Deoptimizer::DeoptimizeAllFunctionsWith(function_info->GetIsolate(), &filter);
+    explicit DependentFunctionMarker(SharedFunctionInfo* shared_info)
+      : shared_info_(shared_info), found_(false) { }
+
+    virtual void EnterContext(Context* context) { }  // Don't care.
+    virtual void LeaveContext(Context* context)  { }  // Don't care.
+    virtual void VisitFunction(JSFunction* function) {
+      // It should be guaranteed by the iterator that everything is optimized.
+      ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
+      if (shared_info_ == function->shared() ||
+          IsInlined(function, shared_info_)) {
+        // mark the code for deoptimization
+        function->code()->set_marked_for_deoptimization(true);
+        found_ = true;
+      }
+    }
+  };
+
+
+  DisallowHeapAllocation no_allocation;
+  DependentFunctionMarker marker(function_info);
+  // TODO(titzer): need to traverse all optimized code to find OSR code here.
+  Deoptimizer::VisitAllOptimizedFunctions(function_info->GetIsolate(), &marker);
+
+  if (marker.found_) {
+    // Only go through with the deoptimization if something was found.
+    Deoptimizer::DeoptimizeMarkedCode(function_info->GetIsolate());
+  }
 }
 
 
 MaybeObject* LiveEdit::ReplaceFunctionCode(
     Handle<JSArray> new_compile_info_array,
     Handle<JSArray> shared_info_array) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = new_compile_info_array->GetIsolate();
   HandleScope scope(isolate);
 
   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
@@ -1343,7 +1362,7 @@
   CHECK(script_handle->IsScript() || script_handle->IsUndefined());
   shared_info->set_script(*script_handle);
 
-  Isolate::Current()->compilation_cache()->Remove(shared_info);
+  function_wrapper->GetIsolate()->compilation_cache()->Remove(shared_info);
 }
 
 
@@ -1360,20 +1379,24 @@
                              Handle<JSArray> position_change_array) {
   int position_diff = 0;
   int array_len = GetArrayLength(position_change_array);
+  Isolate* isolate = position_change_array->GetIsolate();
   // TODO(635): binary search may be used here
   for (int i = 0; i < array_len; i += 3) {
-    Object* element = position_change_array->GetElementNoExceptionThrown(i);
+    Object* element =
+        position_change_array->GetElementNoExceptionThrown(isolate, i);
     CHECK(element->IsSmi());
     int chunk_start = Smi::cast(element)->value();
     if (original_position < chunk_start) {
       break;
     }
-    element = position_change_array->GetElementNoExceptionThrown(i + 1);
+    element = position_change_array->GetElementNoExceptionThrown(isolate,
+                                                                 i + 1);
     CHECK(element->IsSmi());
     int chunk_end = Smi::cast(element)->value();
     // Position mustn't be inside a chunk.
     ASSERT(original_position >= chunk_end);
-    element = position_change_array->GetElementNoExceptionThrown(i + 2);
+    element = position_change_array->GetElementNoExceptionThrown(isolate,
+                                                                 i + 2);
     CHECK(element->IsSmi());
     int chunk_changed_end = Smi::cast(element)->value();
     position_diff = chunk_changed_end - chunk_end;
@@ -1508,7 +1531,7 @@
 MaybeObject* LiveEdit::PatchFunctionPositions(
     Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
-    return Isolate::Current()->ThrowIllegalOperation();
+    return shared_info_array->GetIsolate()->ThrowIllegalOperation();
   }
 
   SharedInfoWrapper shared_info_wrapper(shared_info_array);
@@ -1630,7 +1653,8 @@
   Isolate* isolate = shared_info_array->GetIsolate();
   int len = GetArrayLength(shared_info_array);
   for (int i = 0; i < len; i++) {
-    Object* element = shared_info_array->GetElementNoExceptionThrown(i);
+    Object* element =
+        shared_info_array->GetElementNoExceptionThrown(isolate, i);
     CHECK(element->IsJSValue());
     Handle<JSValue> jsvalue(JSValue::cast(element));
     Handle<SharedFunctionInfo> shared =
@@ -1651,7 +1675,7 @@
 static bool FixTryCatchHandler(StackFrame* top_frame,
                                StackFrame* bottom_frame) {
   Address* pointer_address =
-      &Memory::Address_at(Isolate::Current()->get_address_from_id(
+      &Memory::Address_at(top_frame->isolate()->get_address_from_id(
           Isolate::kHandlerAddress));
 
   while (*pointer_address < top_frame->sp()) {
@@ -1687,7 +1711,7 @@
   ASSERT(bottom_js_frame->is_java_script());
 
   // Check the nature of the top frame.
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = bottom_js_frame->isolate();
   Code* pre_top_frame_code = pre_top_frame->LookupCode();
   bool frame_has_padding;
   if (pre_top_frame_code->is_inline_cache_stub() &&
@@ -1790,7 +1814,7 @@
   // Make sure FixTryCatchHandler is idempotent.
   ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
 
-  Handle<Code> code = Isolate::Current()->builtins()->FrameDropper_LiveEdit();
+  Handle<Code> code = isolate->builtins()->FrameDropper_LiveEdit();
   *top_frame_pc_address = code->entry();
   pre_top_frame->SetCallerFp(bottom_js_frame->fp());
 
@@ -1838,8 +1862,7 @@
 // Drops all call frame matched by target and all frames above them.
 template<typename TARGET>
 static const char* DropActivationsInActiveThreadImpl(
-    TARGET& target, bool do_drop) {
-  Isolate* isolate = Isolate::Current();
+    Isolate* isolate, TARGET& target, bool do_drop) {
   Debug* debug = isolate->debug();
   Zone zone(isolate);
   Vector<StackFrame*> frames = CreateStackMap(isolate, &zone);
@@ -1938,8 +1961,8 @@
     Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
   MultipleFunctionTarget target(shared_info_array, result);
 
-  const char* message =
-      DropActivationsInActiveThreadImpl(target, do_drop);
+  const char* message = DropActivationsInActiveThreadImpl(
+      shared_info_array->GetIsolate(), target, do_drop);
   if (message) {
     return message;
   }
@@ -1949,7 +1972,7 @@
 
   // Replace "blocked on active" with "replaced on active" status.
   for (int i = 0; i < array_len; i++) {
-    if (result->GetElement(i) ==
+    if (result->GetElement(result->GetIsolate(), i) ==
         Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
       Handle<Object> replaced(
           Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
@@ -2004,7 +2027,7 @@
   // First check inactive threads. Fail if some functions are blocked there.
   InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
                                                             result);
-  Isolate::Current()->thread_manager()->IterateArchivedThreads(
+  isolate->thread_manager()->IterateArchivedThreads(
       &inactive_threads_checker);
   if (inactive_threads_checker.HasBlockedFunctions()) {
     return result;
@@ -2056,7 +2079,8 @@
 const char* LiveEdit::RestartFrame(JavaScriptFrame* frame) {
   SingleFrameTarget target(frame);
 
-  const char* result = DropActivationsInActiveThreadImpl(target, true);
+  const char* result = DropActivationsInActiveThreadImpl(
+      frame->isolate(), target, true);
   if (result != NULL) {
     return result;
   }
diff --git a/src/log.cc b/src/log.cc
index 77bb9b3..1b3301e 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -974,7 +974,7 @@
     if (c == '%' && i <= format.length() - 2) {
       i++;
       ASSERT('0' <= format[i] && format[i] <= '9');
-      MaybeObject* maybe = args->GetElement(format[i] - '0');
+      MaybeObject* maybe = args->GetElement(isolate_, format[i] - '0');
       Object* obj;
       if (!maybe->ToObject(&obj)) {
         msg.Append("<exception>");
@@ -1764,21 +1764,21 @@
 }
 
 
-static void AddIsolateIdIfNeeded(StringStream* stream) {
-  Isolate* isolate = Isolate::Current();
+static void AddIsolateIdIfNeeded(Isolate* isolate, StringStream* stream) {
   if (isolate->IsDefaultIsolate()) return;
   stream->Add("isolate-%p-", isolate);
 }
 
 
-static SmartArrayPointer<const char> PrepareLogFileName(const char* file_name) {
+static SmartArrayPointer<const char> PrepareLogFileName(
+    Isolate* isolate, const char* file_name) {
   if (strchr(file_name, '%') != NULL ||
-      !Isolate::Current()->IsDefaultIsolate()) {
+      !isolate->IsDefaultIsolate()) {
     // If there's a '%' in the log file name we have to expand
     // placeholders.
     HeapStringAllocator allocator;
     StringStream stream(&allocator);
-    AddIsolateIdIfNeeded(&stream);
+    AddIsolateIdIfNeeded(isolate, &stream);
     for (const char* p = file_name; *p; p++) {
       if (*p == '%') {
         p++;
@@ -1832,7 +1832,7 @@
   }
 
   SmartArrayPointer<const char> log_file_name =
-      PrepareLogFileName(FLAG_logfile);
+      PrepareLogFileName(isolate, FLAG_logfile);
   log_->Initialize(*log_file_name);
 
   if (FLAG_ll_prof) {
diff --git a/src/macros.py b/src/macros.py
index f1a2130..38b9a08 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -42,8 +42,8 @@
 # These definitions must match the index of the properties in objects.h.
 const kApiTagOffset                 = 0;
 const kApiPropertyListOffset        = 1;
-const kApiSerialNumberOffset        = 2;
-const kApiConstructorOffset         = 2;
+const kApiSerialNumberOffset        = 3;
+const kApiConstructorOffset         = 3;
 const kApiPrototypeTemplateOffset   = 5;
 const kApiParentTemplateOffset      = 6;
 const kApiFlagOffset                = 14;
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 4eb51b5..7207f8d 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -74,7 +74,7 @@
       heap_(NULL),
       code_flusher_(NULL),
       encountered_weak_collections_(NULL),
-      code_to_deoptimize_(NULL) { }
+      have_code_to_deoptimize_(false) { }
 
 #ifdef VERIFY_HEAP
 class VerifyMarkingVisitor: public ObjectVisitor {
@@ -961,22 +961,10 @@
   // objects (empty string, illegal builtin).
   isolate()->stub_cache()->Clear();
 
-  if (code_to_deoptimize_ != Smi::FromInt(0)) {
-    // Convert the linked list of Code objects into a ZoneList.
-    Zone zone(isolate());
-    ZoneList<Code*> codes(4, &zone);
-
-    Object *list = code_to_deoptimize_;
-    while (list->IsCode()) {
-      Code *code = Code::cast(list);
-      list = code->code_to_deoptimize_link();
-      codes.Add(code, &zone);
-      // Destroy the link and don't ever try to deoptimize this code again.
-      code->set_code_to_deoptimize_link(Smi::FromInt(0));
-    }
-    code_to_deoptimize_ = Smi::FromInt(0);
-
-    Deoptimizer::DeoptimizeCodeList(isolate(), &codes);
+  if (have_code_to_deoptimize_) {
+    // Some code objects were marked for deoptimization during the GC.
+    Deoptimizer::DeoptimizeMarkedCode(isolate());
+    have_code_to_deoptimize_ = false;
   }
 }
 
@@ -2623,16 +2611,9 @@
     ASSERT(entries->is_code_at(i));
     Code* code = entries->code_at(i);
 
-    if (IsMarked(code) && !WillBeDeoptimized(code)) {
-      // Insert the code into the code_to_deoptimize linked list.
-      Object* next = code_to_deoptimize_;
-      if (next != Smi::FromInt(0)) {
-        // Record the slot so that it is updated.
-        Object** slot = code->code_to_deoptimize_link_slot();
-        RecordSlot(slot, slot, next);
-      }
-      code->set_code_to_deoptimize_link(next);
-      code_to_deoptimize_ = code;
+    if (IsMarked(code) && !code->marked_for_deoptimization()) {
+      code->set_marked_for_deoptimization(true);
+      have_code_to_deoptimize_ = true;
     }
     entries->clear_at(i);
   }
@@ -3283,11 +3264,7 @@
 
 // Return true if the given code is deoptimized or will be deoptimized.
 bool MarkCompactCollector::WillBeDeoptimized(Code* code) {
-  // We assume the code_to_deoptimize_link is initialized to undefined.
-  // If it is 0, or refers to another Code object, then this code
-  // is already linked, or was already linked into the list.
-  return code->code_to_deoptimize_link() != heap()->undefined_value()
-      || code->marked_for_deoptimization();
+  return code->marked_for_deoptimization();
 }
 
 
@@ -3474,9 +3451,8 @@
     }
   }
 
-  // Update the heads of the native contexts list the code to deoptimize list.
+  // Update the head of the native contexts list in the heap.
   updating_visitor.VisitPointer(heap_->native_contexts_list_address());
-  updating_visitor.VisitPointer(&code_to_deoptimize_);
 
   heap_->string_table()->Iterate(&updating_visitor);
 
diff --git a/src/mark-compact.h b/src/mark-compact.h
index ee845a0..df2f782 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -949,7 +949,7 @@
   MarkingDeque marking_deque_;
   CodeFlusher* code_flusher_;
   Object* encountered_weak_collections_;
-  Object* code_to_deoptimize_;
+  bool have_code_to_deoptimize_;
 
   List<Page*> evacuation_candidates_;
   List<Code*> invalidated_code_;
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 93f3fde..ff15738 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -567,10 +567,80 @@
   Register input_low = scratch3;
   __ Move(input_low, input_high, double_input);
 
-  __ EmitOutOfInt32RangeTruncate(result_reg,
-                                 input_high,
-                                 input_low,
-                                 scratch);
+  Label normal_exponent, restore_sign;
+  // Extract the biased exponent in result.
+  __ Ext(result_reg,
+         input_high,
+         HeapNumber::kExponentShift,
+         HeapNumber::kExponentBits);
+
+  // Check for Infinity and NaNs, which should return 0.
+  __ Subu(scratch, result_reg, HeapNumber::kExponentMask);
+  __ Movz(result_reg, zero_reg, scratch);
+  __ Branch(&done, eq, scratch, Operand(zero_reg));
+
+  // Express exponent as delta to (number of mantissa bits + 31).
+  __ Subu(result_reg,
+          result_reg,
+          Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31));
+
+  // If the delta is strictly positive, all bits would be shifted away,
+  // which means that we can return 0.
+  __ Branch(&normal_exponent, le, result_reg, Operand(zero_reg));
+  __ mov(result_reg, zero_reg);
+  __ Branch(&done);
+
+  __ bind(&normal_exponent);
+  const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
+  // Calculate shift.
+  __ Addu(scratch, result_reg, Operand(kShiftBase + HeapNumber::kMantissaBits));
+
+  // Save the sign.
+  Register sign = result_reg;
+  result_reg = no_reg;
+  __ And(sign, input_high, Operand(HeapNumber::kSignMask));
+
+  // On ARM shifts > 31 bits are valid and will result in zero. On MIPS we need
+  // to check for this specific case.
+  Label high_shift_needed, high_shift_done;
+  __ Branch(&high_shift_needed, lt, scratch, Operand(32));
+  __ mov(input_high, zero_reg);
+  __ Branch(&high_shift_done);
+  __ bind(&high_shift_needed);
+
+  // Set the implicit 1 before the mantissa part in input_high.
+  __ Or(input_high,
+        input_high,
+        Operand(1 << HeapNumber::kMantissaBitsInTopWord));
+  // Shift the mantissa bits to the correct position.
+  // We don't need to clear non-mantissa bits as they will be shifted away.
+  // If they weren't, it would mean that the answer is in the 32bit range.
+  __ sllv(input_high, input_high, scratch);
+
+  __ bind(&high_shift_done);
+
+  // Replace the shifted bits with bits from the lower mantissa word.
+  Label pos_shift, shift_done;
+  __ li(at, 32);
+  __ subu(scratch, at, scratch);
+  __ Branch(&pos_shift, ge, scratch, Operand(zero_reg));
+
+  // Negate scratch.
+  __ Subu(scratch, zero_reg, scratch);
+  __ sllv(input_low, input_low, scratch);
+  __ Branch(&shift_done);
+
+  __ bind(&pos_shift);
+  __ srlv(input_low, input_low, scratch);
+
+  __ bind(&shift_done);
+  __ Or(input_high, input_high, Operand(input_low));
+  // Restore sign if necessary.
+  __ mov(scratch, sign);
+  result_reg = sign;
+  sign = no_reg;
+  __ Subu(result_reg, zero_reg, input_high);
+  __ Movz(result_reg, input_high, scratch);
 
   __ bind(&done);
 
@@ -1486,7 +1556,6 @@
   Register right = a0;
   Register scratch1 = t3;
   Register scratch2 = t5;
-  Register scratch3 = t0;
 
   ASSERT(smi_operands || (not_numbers != NULL));
   if (smi_operands) {
@@ -1590,12 +1659,8 @@
         __ SmiUntag(a2, right);
       } else {
         // Convert operands to 32-bit integers. Right in a2 and left in a3.
-        __ TruncateNumberToI(
-            left, a3, heap_number_map,
-            scratch1, scratch2, scratch3, not_numbers);
-        __ TruncateNumberToI(
-            right, a2, heap_number_map,
-            scratch1, scratch2, scratch3, not_numbers);
+        __ TruncateNumberToI(left, a3, heap_number_map, scratch1, not_numbers);
+        __ TruncateNumberToI(right, a2, heap_number_map, scratch1, not_numbers);
       }
       Label result_not_a_smi;
       switch (op) {
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index cd1d38e..a85b0d8 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -1298,60 +1298,6 @@
 }
 
 
-// Tries to get a signed int32 out of a double precision floating point heap
-// number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
-// 32bits signed integer range.
-// This method implementation differs from the ARM version for performance
-// reasons.
-void MacroAssembler::ConvertToInt32(Register source,
-                                    Register dest,
-                                    Register scratch,
-                                    Register scratch2,
-                                    FPURegister double_scratch,
-                                    Label *not_int32) {
-  Label right_exponent, done;
-  // Get exponent word (ENDIAN issues).
-  lw(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
-  // Get exponent alone in scratch2.
-  And(scratch2, scratch, Operand(HeapNumber::kExponentMask));
-  // Load dest with zero.  We use this either for the final shift or
-  // for the answer.
-  mov(dest, zero_reg);
-  // Check whether the exponent matches a 32 bit signed int that is not a Smi.
-  // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).  This is
-  // the exponent that we are fastest at and also the highest exponent we can
-  // handle here.
-  const uint32_t non_smi_exponent =
-      (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
-  // If we have a match of the int32-but-not-Smi exponent then skip some logic.
-  Branch(&right_exponent, eq, scratch2, Operand(non_smi_exponent));
-  // If the exponent is higher than that then go to not_int32 case.  This
-  // catches numbers that don't fit in a signed int32, infinities and NaNs.
-  Branch(not_int32, gt, scratch2, Operand(non_smi_exponent));
-
-  // We know the exponent is smaller than 30 (biased).  If it is less than
-  // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
-  // it rounds to zero.
-  const uint32_t zero_exponent =
-      (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
-  Subu(scratch2, scratch2, Operand(zero_exponent));
-  // Dest already has a Smi zero.
-  Branch(&done, lt, scratch2, Operand(zero_reg));
-  bind(&right_exponent);
-
-  // MIPS FPU instructions implementing double precision to integer
-  // conversion using round to zero. Since the FP value was qualified
-  // above, the resulting integer should be a legal int32.
-  // The original 'Exponent' word is still in scratch.
-  lwc1(double_scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
-  mtc1(scratch, FPURegister::from_code(double_scratch.code() + 1));
-  trunc_w_d(double_scratch, double_scratch);
-  mfc1(dest, double_scratch);
-
-  bind(&done);
-}
-
-
 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
                                      Register result,
                                      DoubleRegister double_input,
@@ -1416,88 +1362,6 @@
 }
 
 
-void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
-                                                 Register input_high,
-                                                 Register input_low,
-                                                 Register scratch) {
-  Label done, normal_exponent, restore_sign;
-  // Extract the biased exponent in result.
-  Ext(result,
-      input_high,
-      HeapNumber::kExponentShift,
-      HeapNumber::kExponentBits);
-
-  // Check for Infinity and NaNs, which should return 0.
-  Subu(scratch, result, HeapNumber::kExponentMask);
-  Movz(result, zero_reg, scratch);
-  Branch(&done, eq, scratch, Operand(zero_reg));
-
-  // Express exponent as delta to (number of mantissa bits + 31).
-  Subu(result,
-       result,
-       Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31));
-
-  // If the delta is strictly positive, all bits would be shifted away,
-  // which means that we can return 0.
-  Branch(&normal_exponent, le, result, Operand(zero_reg));
-  mov(result, zero_reg);
-  Branch(&done);
-
-  bind(&normal_exponent);
-  const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
-  // Calculate shift.
-  Addu(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits));
-
-  // Save the sign.
-  Register sign = result;
-  result = no_reg;
-  And(sign, input_high, Operand(HeapNumber::kSignMask));
-
-  // On ARM shifts > 31 bits are valid and will result in zero. On MIPS we need
-  // to check for this specific case.
-  Label high_shift_needed, high_shift_done;
-  Branch(&high_shift_needed, lt, scratch, Operand(32));
-  mov(input_high, zero_reg);
-  Branch(&high_shift_done);
-  bind(&high_shift_needed);
-
-  // Set the implicit 1 before the mantissa part in input_high.
-  Or(input_high,
-     input_high,
-     Operand(1 << HeapNumber::kMantissaBitsInTopWord));
-  // Shift the mantissa bits to the correct position.
-  // We don't need to clear non-mantissa bits as they will be shifted away.
-  // If they weren't, it would mean that the answer is in the 32bit range.
-  sllv(input_high, input_high, scratch);
-
-  bind(&high_shift_done);
-
-  // Replace the shifted bits with bits from the lower mantissa word.
-  Label pos_shift, shift_done;
-  li(at, 32);
-  subu(scratch, at, scratch);
-  Branch(&pos_shift, ge, scratch, Operand(zero_reg));
-
-  // Negate scratch.
-  Subu(scratch, zero_reg, scratch);
-  sllv(input_low, input_low, scratch);
-  Branch(&shift_done);
-
-  bind(&pos_shift);
-  srlv(input_low, input_low, scratch);
-
-  bind(&shift_done);
-  Or(input_high, input_high, Operand(input_low));
-  // Restore sign if necessary.
-  mov(scratch, sign);
-  result = sign;
-  sign = no_reg;
-  Subu(result, zero_reg, input_high);
-  Movz(result, input_high, scratch);
-  bind(&done);
-}
-
-
 void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
                                                 DoubleRegister double_input,
                                                 Label* done) {
@@ -1570,31 +1434,14 @@
 void MacroAssembler::TruncateNumberToI(Register object,
                                        Register result,
                                        Register heap_number_map,
-                                       Register scratch1,
-                                       Register scratch2,
-                                       Register scratch3,
+                                       Register scratch,
                                        Label* not_number) {
   Label done;
-  Label not_in_int32_range;
-  DoubleRegister double_scratch = f12;
+  ASSERT(!result.is(object));
 
   UntagAndJumpIfSmi(result, object, &done);
-  JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
-  ConvertToInt32(object,
-                 result,
-                 scratch1,
-                 scratch2,
-                 double_scratch,
-                 &not_in_int32_range);
-  jmp(&done);
-
-  bind(&not_in_int32_range);
-  lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
-  lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
-  EmitOutOfInt32RangeTruncate(result,
-                              scratch1,
-                              scratch2,
-                              scratch3);
+  JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
+  TruncateHeapNumberToI(result, object);
 
   bind(&done);
 }
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index 8f0b3b1..75ded88 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -758,17 +758,6 @@
     BranchF(target, nan, cc, cmp1, cmp2, bd);
   };
 
-  // Convert the HeapNumber pointed to by source to a 32bits signed integer
-  // dest. If the HeapNumber does not fit into a 32bits signed integer branch
-  // to not_int32 label. If FPU is available double_scratch is used but not
-  // scratch2.
-  void ConvertToInt32(Register source,
-                      Register dest,
-                      Register scratch,
-                      Register scratch2,
-                      FPURegister double_scratch,
-                      Label *not_int32);
-
   // Truncates a double using a specific rounding mode, and writes the value
   // to the result register.
   // The except_flag will contain any exceptions caused by the instruction.
@@ -783,17 +772,6 @@
                        CheckForInexactConversion check_inexact
                            = kDontCheckForInexactConversion);
 
-  // Helper for EmitECMATruncate.
-  // This will truncate a floating-point value outside of the singed 32bit
-  // integer range to a 32bit signed integer.
-  // Expects the double value loaded in input_high and input_low.
-  // Exits with the answer in 'result'.
-  // Note that this code does not work for values in the 32bit range!
-  void EmitOutOfInt32RangeTruncate(Register result,
-                                   Register input_high,
-                                   Register input_low,
-                                   Register scratch);
-
   // Performs a truncating conversion of a floating point number as used by
   // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
   // succeeds, otherwise falls through if result is saturated. On return
@@ -821,9 +799,7 @@
   void TruncateNumberToI(Register object,
                          Register result,
                          Register heap_number_map,
-                         Register scratch1,
-                         Register scratch2,
-                         Register scratch3,
+                         Register scratch,
                          Label* not_int32);
 
   // Loads the number from object into dst register.
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 9e63555..156cd77 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -333,8 +333,9 @@
     exit(1);
   }
 #endif
-  i::Serializer::Enable();
   Isolate* isolate = Isolate::GetCurrent();
+  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::Serializer::Enable(internal_isolate);
   Persistent<Context> context;
   {
     HandleScope handle_scope(isolate);
@@ -391,7 +392,7 @@
   // Make sure all builtin scripts are cached.
   { HandleScope scope(isolate);
     for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
-      i::Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
+      internal_isolate->bootstrapper()->NativesSourceLookup(i);
     }
   }
   // If we don't do this then we end up with a stray root pointing at the
@@ -402,10 +403,11 @@
   CppByteSink sink(argv[1]);
   // This results in a somewhat smaller snapshot, probably because it gets rid
   // of some things that are cached between garbage collections.
-  i::StartupSerializer ser(&sink);
+  i::StartupSerializer ser(internal_isolate, &sink);
   ser.SerializeStrongReferences();
 
-  i::PartialSerializer partial_ser(&ser, sink.partial_sink());
+  i::PartialSerializer partial_ser(
+      internal_isolate, &ser, sink.partial_sink());
   partial_ser.Serialize(&raw_context);
 
   ser.SerializeWeakReferences();
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index a61eacf..3eb7817 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -501,7 +501,7 @@
   }
   if (cache_stamp()->IsSmi()) {
     CHECK(Smi::cast(cache_stamp())->value() <=
-          Smi::cast(Isolate::Current()->date_cache()->stamp())->value());
+          Smi::cast(GetIsolate()->date_cache()->stamp())->value());
   }
 }
 
@@ -889,6 +889,7 @@
 void TemplateInfo::TemplateInfoVerify() {
   VerifyPointer(tag());
   VerifyPointer(property_list());
+  VerifyPointer(property_accessors());
 }
 
 
@@ -897,7 +898,6 @@
   TemplateInfoVerify();
   VerifyPointer(serial_number());
   VerifyPointer(call_code());
-  VerifyPointer(property_accessors());
   VerifyPointer(prototype_template());
   VerifyPointer(parent_template());
   VerifyPointer(named_property_handler());
diff --git a/src/objects-inl.h b/src/objects-inl.h
index f629d9f..fc5ed24 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -917,17 +917,17 @@
 }
 
 
-MaybeObject* Object::GetElement(uint32_t index) {
+MaybeObject* Object::GetElement(Isolate* isolate, uint32_t index) {
   // GetElement can trigger a getter which can cause allocation.
   // This was not always the case. This ASSERT is here to catch
   // leftover incorrect uses.
   ASSERT(AllowHeapAllocation::IsAllowed());
-  return GetElementWithReceiver(this, index);
+  return GetElementWithReceiver(isolate, this, index);
 }
 
 
-Object* Object::GetElementNoExceptionThrown(uint32_t index) {
-  MaybeObject* maybe = GetElementWithReceiver(this, index);
+Object* Object::GetElementNoExceptionThrown(Isolate* isolate, uint32_t index) {
+  MaybeObject* maybe = GetElementWithReceiver(isolate, this, index);
   ASSERT(!maybe->IsFailure());
   Object* result = NULL;  // Initialization to please compiler.
   maybe->ToObject(&result);
@@ -4195,7 +4195,7 @@
   TransitionArray* transitions;
   MaybeObject* maybe_transitions;
   if (!map->HasTransitionArray()) {
-    maybe_transitions = TransitionArray::Allocate(0);
+    maybe_transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
     transitions->set_back_pointer_storage(map->GetBackPointer());
   } else if (!map->transitions()->IsFullTransitionArray()) {
@@ -4466,11 +4466,10 @@
 
 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
+ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
 
 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
-ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
-          kPropertyAccessorsOffset)
 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
           kPrototypeTemplateOffset)
 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
@@ -4840,7 +4839,7 @@
 
 bool SharedFunctionInfo::is_compiled() {
   return code() !=
-      Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
+      GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
 }
 
 
@@ -5004,6 +5003,7 @@
     context()->native_context()->AddOptimizedFunction(this);
   }
   if (was_optimized && !is_optimized) {
+    // TODO(titzer): linear in the number of optimized functions; fix!
     context()->native_context()->RemoveOptimizedFunction(this);
   }
 }
@@ -5266,6 +5266,20 @@
 }
 
 
+Object* Code::next_code_link() {
+  CHECK(kind() == OPTIMIZED_FUNCTION);
+  return Object::cast(READ_FIELD(this, kTypeFeedbackInfoOffset));
+}
+
+
+void Code::set_next_code_link(Object* value, WriteBarrierMode mode) {
+  CHECK(kind() == OPTIMIZED_FUNCTION);
+  WRITE_FIELD(this, kTypeFeedbackInfoOffset, value);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
+                            value, mode);
+}
+
+
 int Code::stub_info() {
   ASSERT(kind() == COMPARE_IC || kind() == COMPARE_NIL_IC ||
          kind() == BINARY_OP_IC || kind() == LOAD_IC);
@@ -5287,25 +5301,6 @@
 }
 
 
-Object* Code::code_to_deoptimize_link() {
-  // Optimized code should not have type feedback.
-  ASSERT(kind() == OPTIMIZED_FUNCTION);
-  return READ_FIELD(this, kTypeFeedbackInfoOffset);
-}
-
-
-void Code::set_code_to_deoptimize_link(Object* value) {
-  ASSERT(kind() == OPTIMIZED_FUNCTION);
-  WRITE_FIELD(this, kTypeFeedbackInfoOffset, value);
-}
-
-
-Object** Code::code_to_deoptimize_link_slot() {
-  ASSERT(kind() == OPTIMIZED_FUNCTION);
-  return HeapObject::RawField(this, kTypeFeedbackInfoOffset);
-}
-
-
 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
 INT_ACCESSORS(Code, ic_age, kICAgeOffset)
 
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 9ea060f..0b8fdfd 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -1070,6 +1070,8 @@
   tag()->ShortPrint(out);
   PrintF(out, "\n - property_list: ");
   property_list()->ShortPrint(out);
+  PrintF(out, "\n - property_accessors: ");
+  property_accessors()->ShortPrint(out);
   PrintF(out, "\n - constructor: ");
   constructor()->ShortPrint(out);
   PrintF(out, "\n - internal_field_count: ");
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index 9398d6d..e90c74c 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -304,7 +304,7 @@
       && (target->ic_state() == MEGAMORPHIC || target->ic_state() == GENERIC ||
           target->ic_state() == POLYMORPHIC || heap->flush_monomorphic_ics() ||
           Serializer::enabled() || target->ic_age() != heap->global_ic_age())) {
-    IC::Clear(rinfo->pc());
+    IC::Clear(target->GetIsolate(), rinfo->pc());
     target = Code::GetCodeFromTargetAddress(rinfo->target_address());
   }
   heap->mark_compact_collector()->RecordRelocSlot(rinfo, target);
diff --git a/src/objects.cc b/src/objects.cc
index 80ca046..9cb077b 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -83,23 +83,19 @@
 }
 
 
-MaybeObject* Object::ToObject() {
+MaybeObject* Object::ToObject(Isolate* isolate) {
   if (IsJSReceiver()) {
     return this;
   } else if (IsNumber()) {
-    Isolate* isolate = Isolate::Current();
     Context* native_context = isolate->context()->native_context();
     return CreateJSValue(native_context->number_function(), this);
   } else if (IsBoolean()) {
-    Isolate* isolate = HeapObject::cast(this)->GetIsolate();
     Context* native_context = isolate->context()->native_context();
     return CreateJSValue(native_context->boolean_function(), this);
   } else if (IsString()) {
-    Isolate* isolate = HeapObject::cast(this)->GetIsolate();
     Context* native_context = isolate->context()->native_context();
     return CreateJSValue(native_context->string_function(), this);
   } else if (IsSymbol()) {
-    Isolate* isolate = HeapObject::cast(this)->GetIsolate();
     Context* native_context = isolate->context()->native_context();
     return CreateJSValue(native_context->symbol_function(), this);
   }
@@ -135,7 +131,7 @@
     } else if (IsBoolean()) {
       holder = native_context->boolean_function()->instance_prototype();
     } else {
-      Isolate::Current()->PushStackTraceAndDie(
+      result->isolate()->PushStackTraceAndDie(
           0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
     }
   }
@@ -422,24 +418,22 @@
 }
 
 
-Handle<Object> Object::GetProperty(Handle<Object> object, Handle<Name> name) {
+Handle<Object> Object::GetProperty(Handle<Object> object,
+                                   Handle<Name> name) {
   // TODO(rossberg): The index test should not be here but in the GetProperty
   // method (or somewhere else entirely). Needs more global clean-up.
   uint32_t index;
+  Isolate* isolate = name->GetIsolate();
   if (name->AsArrayIndex(&index))
-    return GetElement(object, index);
-  Isolate* isolate = object->IsHeapObject()
-      ? Handle<HeapObject>::cast(object)->GetIsolate()
-      : Isolate::Current();
+    return GetElement(isolate, object, index);
   CALL_HEAP_FUNCTION(isolate, object->GetProperty(*name), Object);
 }
 
 
-Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) {
-  Isolate* isolate = object->IsHeapObject()
-      ? Handle<HeapObject>::cast(object)->GetIsolate()
-      : Isolate::Current();
-  CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
+Handle<Object> Object::GetElement(Isolate* isolate,
+                                  Handle<Object> object,
+                                  uint32_t index) {
+  CALL_HEAP_FUNCTION(isolate, object->GetElement(isolate, index), Object);
 }
 
 
@@ -801,9 +795,7 @@
                                    LookupResult* result,
                                    Handle<Name> key,
                                    PropertyAttributes* attributes) {
-  Isolate* isolate = object->IsHeapObject()
-      ? Handle<HeapObject>::cast(object)->GetIsolate()
-      : Isolate::Current();
+  Isolate* isolate = result->isolate();
   CALL_HEAP_FUNCTION(
       isolate,
       object->GetProperty(*receiver, result, *key, attributes),
@@ -816,9 +808,7 @@
                                        LookupResult* result,
                                        Handle<Name> key,
                                        PropertyAttributes* attributes) {
-  Isolate* isolate = object->IsHeapObject()
-      ? Handle<HeapObject>::cast(object)->GetIsolate()
-      : Isolate::Current();
+  Isolate* isolate = result->isolate();
   CALL_HEAP_FUNCTION_PASS_EXCEPTION(
       isolate,
       object->GetProperty(*receiver, result, *key, attributes));
@@ -910,10 +900,9 @@
 }
 
 
-MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
-  Isolate* isolate = IsSmi()
-      ? Isolate::Current()
-      : HeapObject::cast(this)->GetIsolate();
+MaybeObject* Object::GetElementWithReceiver(Isolate* isolate,
+                                            Object* receiver,
+                                            uint32_t index) {
   Heap* heap = isolate->heap();
   Object* holder = this;
 
@@ -3012,48 +3001,101 @@
 }
 
 
-void Map::AppendCallbackDescriptors(Handle<Map> map,
-                                    Handle<Object> descriptors) {
-  Isolate* isolate = map->GetIsolate();
-  Handle<DescriptorArray> array(map->instance_descriptors());
-  NeanderArray callbacks(descriptors);
-  int nof_callbacks = callbacks.length();
+template<class T>
+static int AppendUniqueCallbacks(NeanderArray* callbacks,
+                                 Handle<typename T::Array> array,
+                                 int valid_descriptors) {
+  int nof_callbacks = callbacks->length();
 
-  ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
-
+  Isolate* isolate = array->GetIsolate();
   // Ensure the keys are unique names before writing them into the
   // instance descriptor. Since it may cause a GC, it has to be done before we
   // temporarily put the heap in an invalid state while appending descriptors.
   for (int i = 0; i < nof_callbacks; ++i) {
-    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
-    if (!entry->name()->IsUniqueName()) {
-      Handle<String> key =
-          isolate->factory()->InternalizedStringFromString(
-              Handle<String>(String::cast(entry->name())));
-      entry->set_name(*key);
-    }
+    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
+    if (entry->name()->IsUniqueName()) continue;
+    Handle<String> key =
+        isolate->factory()->InternalizedStringFromString(
+            Handle<String>(String::cast(entry->name())));
+    entry->set_name(*key);
   }
 
-  int nof = map->NumberOfOwnDescriptors();
-
   // Fill in new callback descriptors.  Process the callbacks from
   // back to front so that the last callback with a given name takes
   // precedence over previously added callbacks with that name.
   for (int i = nof_callbacks - 1; i >= 0; i--) {
-    AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
+    AccessorInfo* entry = AccessorInfo::cast(callbacks->get(i));
     Name* key = Name::cast(entry->name());
     // Check if a descriptor with this name already exists before writing.
-    if (array->Search(key, nof) == DescriptorArray::kNotFound) {
-      CallbacksDescriptor desc(key, entry, entry->property_attributes());
-      array->Append(&desc);
-      nof += 1;
+    if (!T::Contains(key, entry, valid_descriptors, array)) {
+      T::Insert(key, entry, valid_descriptors, array);
+      valid_descriptors++;
     }
   }
 
+  return valid_descriptors;
+}
+
+struct DescriptorArrayAppender {
+  typedef DescriptorArray Array;
+  static bool Contains(Name* key,
+                       AccessorInfo* entry,
+                       int valid_descriptors,
+                       Handle<DescriptorArray> array) {
+    return array->Search(key, valid_descriptors) != DescriptorArray::kNotFound;
+  }
+  static void Insert(Name* key,
+                     AccessorInfo* entry,
+                     int valid_descriptors,
+                     Handle<DescriptorArray> array) {
+    CallbacksDescriptor desc(key, entry, entry->property_attributes());
+    array->Append(&desc);
+  }
+};
+
+
+struct FixedArrayAppender {
+  typedef FixedArray Array;
+  static bool Contains(Name* key,
+                       AccessorInfo* entry,
+                       int valid_descriptors,
+                       Handle<FixedArray> array) {
+    for (int i = 0; i < valid_descriptors; i++) {
+      if (key == AccessorInfo::cast(array->get(i))->name()) return true;
+    }
+    return false;
+  }
+  static void Insert(Name* key,
+                     AccessorInfo* entry,
+                     int valid_descriptors,
+                     Handle<FixedArray> array) {
+    array->set(valid_descriptors, entry);
+  }
+};
+
+
+void Map::AppendCallbackDescriptors(Handle<Map> map,
+                                    Handle<Object> descriptors) {
+  int nof = map->NumberOfOwnDescriptors();
+  Handle<DescriptorArray> array(map->instance_descriptors());
+  NeanderArray callbacks(descriptors);
+  ASSERT(array->NumberOfSlackDescriptors() >= callbacks.length());
+  nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
   map->SetNumberOfOwnDescriptors(nof);
 }
 
 
+int AccessorInfo::AppendUnique(Handle<Object> descriptors,
+                               Handle<FixedArray> array,
+                               int valid_descriptors) {
+  NeanderArray callbacks(descriptors);
+  ASSERT(array->length() >= callbacks.length() + valid_descriptors);
+  return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
+                                                   array,
+                                                   valid_descriptors);
+}
+
+
 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
   ASSERT(!map.is_null());
   for (int i = 0; i < maps->length(); ++i) {
@@ -4067,7 +4109,8 @@
   PropertyAttributes old_attributes = ABSENT;
   bool is_observed = FLAG_harmony_observation && self->map()->is_observed();
   if (is_observed && lookup.IsProperty()) {
-    if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name);
+    if (lookup.IsDataProperty()) old_value =
+        Object::GetProperty(self, name);
     old_attributes = lookup.GetAttributes();
   }
 
@@ -5093,7 +5136,7 @@
     if (should_enqueue_change_record) {
       old_value = object->GetLocalElementAccessorPair(index) != NULL
           ? Handle<Object>::cast(factory->the_hole_value())
-          : Object::GetElement(object, index);
+          : Object::GetElement(isolate, object, index);
     }
   }
 
@@ -6129,7 +6172,7 @@
     if (is_element) {
       preexists = object->HasLocalElement(index);
       if (preexists && object->GetLocalElementAccessorPair(index) == NULL) {
-        old_value = Object::GetElement(object, index);
+        old_value = Object::GetElement(isolate, object, index);
       }
     } else {
       LookupResult lookup(isolate);
@@ -6541,7 +6584,7 @@
   } else {
     // Descriptor arrays grow by 50%.
     MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
-        old_size, old_size < 4 ? 1 : old_size / 2);
+        GetIsolate(), old_size, old_size < 4 ? 1 : old_size / 2);
     if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
 
     DescriptorArray::WhitenessWitness witness(new_descriptors);
@@ -6791,7 +6834,8 @@
   }
 
   DescriptorArray* new_descriptors;
-  MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1);
+  MaybeObject* maybe_descriptors =
+      DescriptorArray::Allocate(GetIsolate(), old_size, 1);
   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
 
   DescriptorArray::WhitenessWitness witness(new_descriptors);
@@ -6838,7 +6882,7 @@
   int size = enumeration_index;
 
   DescriptorArray* descriptors;
-  MaybeObject* maybe_descriptors = Allocate(size);
+  MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size);
   if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
   DescriptorArray::WhitenessWitness witness(descriptors);
 
@@ -6885,7 +6929,8 @@
   ASSERT_LT(insertion_index, new_size);
 
   DescriptorArray* new_descriptors;
-  MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
+  MaybeObject* maybe_descriptors =
+      DescriptorArray::Allocate(GetIsolate(), new_size);
   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   DescriptorArray::WhitenessWitness witness(new_descriptors);
 
@@ -7675,8 +7720,10 @@
 #endif
 
 
-MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) {
-  Heap* heap = Isolate::Current()->heap();
+MaybeObject* DescriptorArray::Allocate(Isolate* isolate,
+                                       int number_of_descriptors,
+                                       int slack) {
+  Heap* heap = isolate->heap();
   // Do not use DescriptorArray::cast on incomplete object.
   int size = number_of_descriptors + slack;
   if (size == 0) return heap->empty_descriptor_array();
@@ -7744,7 +7791,8 @@
   // Allocate a new descriptor array large enough to hold the required
   // descriptors, with minimally the exact same size as this descriptor array.
   MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
-      new_size, Max(new_size, other->number_of_descriptors()) - new_size);
+      GetIsolate(), new_size,
+      Max(new_size, other->number_of_descriptors()) - new_size);
   if (!maybe_descriptors->To(&result)) return maybe_descriptors;
   ASSERT(result->length() > length() ||
          result->NumberOfSlackDescriptors() > 0 ||
@@ -7960,7 +8008,7 @@
 
 
 bool String::LooksValid() {
-  if (!Isolate::Current()->heap()->Contains(this)) return false;
+  if (!GetIsolate()->heap()->Contains(this)) return false;
   return true;
 }
 
@@ -8120,8 +8168,7 @@
 }
 
 
-void Relocatable::PostGarbageCollectionProcessing() {
-  Isolate* isolate = Isolate::Current();
+void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
   Relocatable* current = isolate->relocatable_top();
   while (current != NULL) {
     current->PostGarbageCollection();
@@ -8132,7 +8179,7 @@
 
 // Reserve space for statics needing saving and restoring.
 int Relocatable::ArchiveSpacePerThread() {
-  return sizeof(Isolate::Current()->relocatable_top());
+  return sizeof(Relocatable*);  // NOLINT
 }
 
 
@@ -8158,8 +8205,7 @@
 }
 
 
-void Relocatable::Iterate(ObjectVisitor* v) {
-  Isolate* isolate = Isolate::Current();
+void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
   Iterate(v, isolate->relocatable_top());
 }
 
@@ -9273,7 +9319,7 @@
   ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
   ASSERT(!info->isolate()->has_pending_exception());
   bool result = Compiler::CompileLazy(info);
-  ASSERT(result != Isolate::Current()->has_pending_exception());
+  ASSERT(result != info->isolate()->has_pending_exception());
   if (!result && flag == CLEAR_EXCEPTION) {
     info->isolate()->clear_pending_exception();
   }
@@ -9663,12 +9709,13 @@
 }
 
 
-MaybeObject* Oddball::Initialize(const char* to_string,
+MaybeObject* Oddball::Initialize(Heap* heap,
+                                 const char* to_string,
                                  Object* to_number,
                                  byte kind) {
   String* internalized_to_string;
   { MaybeObject* maybe_string =
-      Isolate::Current()->heap()->InternalizeUtf8String(
+      heap->InternalizeUtf8String(
           CStrVector(to_string));
     if (!maybe_string->To(&internalized_to_string)) return maybe_string;
   }
@@ -10305,7 +10352,7 @@
     RelocInfo* info = it.rinfo();
     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
     if (target->is_inline_cache_stub()) {
-      IC::Clear(info->pc());
+      IC::Clear(this->GetIsolate(), info->pc());
     }
   }
 }
@@ -10329,6 +10376,18 @@
 }
 
 
+BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
+  DisallowHeapAllocation no_gc;
+  ASSERT(kind() == FUNCTION);
+  for (FullCodeGenerator::BackEdgeTableIterator it(this, &no_gc);
+       !it.Done();
+       it.Next()) {
+    if (it.pc_offset() == pc_offset) return it.ast_id();
+  }
+  return BailoutId::None();
+}
+
+
 bool Code::allowed_in_shared_map_code_cache() {
   return is_keyed_load_stub() || is_keyed_store_stub() ||
       (is_compare_ic_stub() &&
@@ -10389,7 +10448,7 @@
 
 void Code::GetCodeAgeAndParity(Code* code, Age* age,
                                MarkingParity* parity) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = code->GetIsolate();
   Builtins* builtins = isolate->builtins();
   Code* stub = NULL;
 #define HANDLE_CODE_AGE(AGE)                                            \
@@ -10789,7 +10848,8 @@
     // If there is no back edge table, the "table start" will be at or after
     // (due to alignment) the end of the instruction stream.
     if (static_cast<int>(offset) < instruction_size()) {
-      FullCodeGenerator::BackEdgeTableIterator back_edges(this);
+      DisallowHeapAllocation no_gc;
+      FullCodeGenerator::BackEdgeTableIterator back_edges(this, &no_gc);
 
       PrintF(out, "Back edges (size = %u)\n", back_edges.table_length());
       PrintF(out, "ast_id  pc_offset  loop_depth\n");
@@ -10965,7 +11025,7 @@
   ASSERT(attributes != ABSENT);
   if (attributes == DONT_DELETE) return false;
   old_values->Add(object->GetLocalElementAccessorPair(index) == NULL
-      ? Object::GetElement(object, index)
+      ? Object::GetElement(isolate, object, index)
       : Handle<Object>::cast(isolate->factory()->the_hole_value()));
   indices->Add(index);
   return true;
@@ -11350,13 +11410,15 @@
   int code_entries = starts.number_of_entries();
   if (start == end) return;
 
-  // Collect all the code to deoptimize.
-  Zone zone(isolate);
-  ZoneList<Code*> codes(end - start, &zone);
+  // Mark all the code that needs to be deoptimized.
+  bool marked = false;
   for (int i = start; i < end; i++) {
     if (is_code_at(i)) {
       Code* code = code_at(i);
-      if (!code->marked_for_deoptimization()) codes.Add(code, &zone);
+      if (!code->marked_for_deoptimization()) {
+        code->set_marked_for_deoptimization(true);
+        marked = true;
+      }
     } else {
       CompilationInfo* info = compilation_info_at(i);
       info->AbortDueToDependencyChange();
@@ -11372,7 +11434,8 @@
     clear_at(i);
   }
   set_number_of_entries(group, 0);
-  Deoptimizer::DeoptimizeCodeList(isolate, &codes);
+
+  if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
 }
 
 
@@ -12205,7 +12268,7 @@
 
   if (old_attributes != ABSENT) {
     if (self->GetLocalElementAccessorPair(index) == NULL)
-      old_value = Object::GetElement(self, index);
+      old_value = Object::GetElement(isolate, self, index);
   } else if (self->IsJSArray()) {
     // Store old array length in case adding an element grows the array.
     old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate);
@@ -12247,7 +12310,7 @@
   } else if (old_value->IsTheHole()) {
     EnqueueChangeRecord(self, "reconfigured", name, old_value);
   } else {
-    Handle<Object> new_value = Object::GetElement(self, index);
+    Handle<Object> new_value = Object::GetElement(isolate, self, index);
     bool value_changed = !old_value->SameValue(*new_value);
     if (old_attributes != new_attributes) {
       if (!value_changed) old_value = isolate->factory()->the_hole_value();
@@ -12575,7 +12638,7 @@
 
   Object* pt = holder_handle->GetPrototype();
   if (pt == heap->null_value()) return heap->undefined_value();
-  return pt->GetElementWithReceiver(*this_handle, index);
+  return pt->GetElementWithReceiver(isolate, *this_handle, index);
 }
 
 
@@ -15220,7 +15283,7 @@
   // Allocate the instance descriptor.
   DescriptorArray* descriptors;
   MaybeObject* maybe_descriptors =
-      DescriptorArray::Allocate(instance_descriptor_length);
+      DescriptorArray::Allocate(GetIsolate(), instance_descriptor_length);
   if (!maybe_descriptors->To(&descriptors)) {
     return maybe_descriptors;
   }
@@ -15513,7 +15576,7 @@
                                 int code_position,
                                 Handle<Object> break_point_object) {
   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
-                                  Isolate::Current());
+                                  debug_info->GetIsolate());
   if (break_point_info->IsUndefined()) return;
   BreakPointInfo::ClearBreakPoint(
       Handle<BreakPointInfo>::cast(break_point_info),
@@ -15526,7 +15589,7 @@
                               int source_position,
                               int statement_position,
                               Handle<Object> break_point_object) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = debug_info->GetIsolate();
   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
                                   isolate);
   if (!break_point_info->IsUndefined()) {
@@ -15640,7 +15703,7 @@
 // Remove the specified break point object.
 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
                                      Handle<Object> break_point_object) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = break_point_info->GetIsolate();
   // If there are no break points just ignore.
   if (break_point_info->break_point_objects()->IsUndefined()) return;
   // If there is a single break point clear it if it is the same.
diff --git a/src/objects.h b/src/objects.h
index e4017ef..f001feb 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1436,8 +1436,8 @@
 
   inline bool HasSpecificClassOf(String* name);
 
-  MUST_USE_RESULT MaybeObject* ToObject();             // ECMA-262 9.9.
-  bool BooleanValue();                                 // ECMA-262 9.2.
+  MUST_USE_RESULT MaybeObject* ToObject(Isolate* isolate);  // ECMA-262 9.9.
+  bool BooleanValue();                                      // ECMA-262 9.2.
 
   // Convert to a JSObject if needed.
   // native_context is used when creating wrapper object.
@@ -1459,7 +1459,8 @@
       Name* key,
       PropertyAttributes* attributes);
 
-  static Handle<Object> GetProperty(Handle<Object> object, Handle<Name> key);
+  static Handle<Object> GetProperty(Handle<Object> object,
+                                    Handle<Name> key);
   static Handle<Object> GetProperty(Handle<Object> object,
                                     Handle<Object> receiver,
                                     LookupResult* result,
@@ -1481,11 +1482,15 @@
   MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
                                                             JSReceiver* getter);
 
-  static Handle<Object> GetElement(Handle<Object> object, uint32_t index);
-  MUST_USE_RESULT inline MaybeObject* GetElement(uint32_t index);
+  static Handle<Object> GetElement(Isolate* isolate,
+                                   Handle<Object> object,
+                                   uint32_t index);
+  MUST_USE_RESULT inline MaybeObject* GetElement(Isolate* isolate,
+                                                 uint32_t index);
   // For use when we know that no exception can be thrown.
-  inline Object* GetElementNoExceptionThrown(uint32_t index);
-  MUST_USE_RESULT MaybeObject* GetElementWithReceiver(Object* receiver,
+  inline Object* GetElementNoExceptionThrown(Isolate* isolate, uint32_t index);
+  MUST_USE_RESULT MaybeObject* GetElementWithReceiver(Isolate* isolate,
+                                                      Object* receiver,
                                                       uint32_t index);
 
   // Return the object's prototype (might be Heap::null_value()).
@@ -3181,7 +3186,8 @@
 
   // Allocates a DescriptorArray, but returns the singleton
   // empty descriptor array object if number_of_descriptors is 0.
-  MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors,
+  MUST_USE_RESULT static MaybeObject* Allocate(Isolate* isolate,
+                                               int number_of_descriptors,
                                                int slack = 0);
 
   // Casting.
@@ -4807,21 +4813,19 @@
   // [deoptimization_data]: Array containing data for deopt.
   DECL_ACCESSORS(deoptimization_data, FixedArray)
 
-  // [type_feedback_info]: Struct containing type feedback information for
-  // unoptimized code. Optimized code can temporarily store the head of
-  // the list of code to be deoptimized during mark-compact GC.
-  // STUBs can use this slot to store arbitrary information as a Smi.
-  // Will contain either a TypeFeedbackInfo object, or JSFunction object,
-  // or undefined, or a Smi.
+  // [type_feedback_info]: This field stores various things, depending on the
+  // kind of the code object.
+  //   FUNCTION           => type feedback information.
+  //   STUB               => various things, e.g. a SMI
+  //   OPTIMIZED_FUNCTION => the next_code_link for optimized code list.
   DECL_ACCESSORS(type_feedback_info, Object)
   inline void InitializeTypeFeedbackInfoNoWriteBarrier(Object* value);
   inline int stub_info();
   inline void set_stub_info(int info);
 
-  // Used during GC to code a list of code objects to deoptimize.
-  inline Object* code_to_deoptimize_link();
-  inline void set_code_to_deoptimize_link(Object* value);
-  inline Object** code_to_deoptimize_link_slot();
+  // [next_code_link]: Link for lists of optimized or deoptimized code.
+  // Note that storage for this field is overlapped with typefeedback_info.
+  DECL_ACCESSORS(next_code_link, Object)
 
   // [gc_metadata]: Field used to hold GC related metadata. The contents of this
   // field does not have to be traced during garbage collection since
@@ -5101,6 +5105,8 @@
   void ClearInlineCaches();
   void ClearTypeFeedbackCells(Heap* heap);
 
+  BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset);
+
 #define DECLARE_CODE_AGE_ENUM(X) k##X##CodeAge,
   enum Age {
     kNoAge = 0,
@@ -5140,6 +5146,7 @@
       kHandlerTableOffset + kPointerSize;
   static const int kTypeFeedbackInfoOffset =
       kDeoptimizationDataOffset + kPointerSize;
+  static const int kNextCodeLinkOffset = kTypeFeedbackInfoOffset;  // Shared.
   static const int kGCMetadataOffset = kTypeFeedbackInfoOffset + kPointerSize;
   static const int kICAgeOffset =
       kGCMetadataOffset + kPointerSize;
@@ -7013,8 +7020,10 @@
   // Returns if this function has been compiled to native code yet.
   inline bool is_compiled();
 
-  // [next_function_link]: Field for linking functions. This list is treated as
-  // a weak list by the GC.
+  // [next_function_link]: Links functions into various lists, e.g. the list
+  // of optimized functions hanging off the native_context. The CodeFlusher
+  // uses this link to chain together flushing candidates. Treated weakly
+  // by the garbage collector.
   DECL_ACCESSORS(next_function_link, Object)
 
   // Prints the name of the function using PrintF.
@@ -8719,13 +8728,14 @@
   virtual void IterateInstance(ObjectVisitor* v) { }
   virtual void PostGarbageCollection() { }
 
-  static void PostGarbageCollectionProcessing();
+  static void PostGarbageCollectionProcessing(Isolate* isolate);
   static int ArchiveSpacePerThread();
   static char* ArchiveState(Isolate* isolate, char* to);
   static char* RestoreState(Isolate* isolate, char* from);
-  static void Iterate(ObjectVisitor* v);
+  static void Iterate(Isolate* isolate, ObjectVisitor* v);
   static void Iterate(ObjectVisitor* v, Relocatable* top);
   static char* Iterate(ObjectVisitor* v, char* t);
+
  private:
   Isolate* isolate_;
   Relocatable* prev_;
@@ -8861,7 +8871,8 @@
   DECLARE_VERIFIER(Oddball)
 
   // Initialize the fields.
-  MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
+  MUST_USE_RESULT MaybeObject* Initialize(Heap* heap,
+                                          const char* to_string,
                                           Object* to_number,
                                           byte kind);
 
@@ -9484,6 +9495,11 @@
   // Dispatched behavior.
   DECLARE_VERIFIER(AccessorInfo)
 
+  // Append all descriptors to the array that are not already there.
+  // Return number added.
+  static int AppendUnique(Handle<Object> descriptors,
+                          Handle<FixedArray> array,
+                          int valid_descriptors);
 
   static const int kNameOffset = HeapObject::kHeaderSize;
   static const int kFlagOffset = kNameOffset + kPointerSize;
@@ -9790,12 +9806,15 @@
  public:
   DECL_ACCESSORS(tag, Object)
   DECL_ACCESSORS(property_list, Object)
+  DECL_ACCESSORS(property_accessors, Object)
 
   DECLARE_VERIFIER(TemplateInfo)
 
-  static const int kTagOffset          = HeapObject::kHeaderSize;
+  static const int kTagOffset = HeapObject::kHeaderSize;
   static const int kPropertyListOffset = kTagOffset + kPointerSize;
-  static const int kHeaderSize         = kPropertyListOffset + kPointerSize;
+  static const int kPropertyAccessorsOffset =
+      kPropertyListOffset + kPointerSize;
+  static const int kHeaderSize = kPropertyAccessorsOffset + kPointerSize;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
@@ -9806,7 +9825,6 @@
  public:
   DECL_ACCESSORS(serial_number, Object)
   DECL_ACCESSORS(call_code, Object)
-  DECL_ACCESSORS(property_accessors, Object)
   DECL_ACCESSORS(prototype_template, Object)
   DECL_ACCESSORS(parent_template, Object)
   DECL_ACCESSORS(named_property_handler, Object)
@@ -9838,9 +9856,8 @@
 
   static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
   static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
-  static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
   static const int kPrototypeTemplateOffset =
-      kPropertyAccessorsOffset + kPointerSize;
+      kCallCodeOffset + kPointerSize;
   static const int kParentTemplateOffset =
       kPrototypeTemplateOffset + kPointerSize;
   static const int kNamedPropertyHandlerOffset =
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index 96847dc..b0e37fd 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -108,12 +108,18 @@
   // The function may have already been optimized by OSR.  Simply continue.
   // Use a mutex to make sure that functions marked for install
   // are always also queued.
-  LockGuard<Mutex> mark_and_queue(&install_mutex_);
-  { Heap::RelocationLock relocation_lock(isolate_->heap());
+  if (!optimizing_compiler->info()->osr_ast_id().IsNone()) {
+    ASSERT(FLAG_concurrent_osr);
+    LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
+    osr_candidates_.RemoveElement(optimizing_compiler);
+    ready_for_osr_.Add(optimizing_compiler);
+  } else {
+    LockGuard<Mutex> mark_and_queue(&install_mutex_);
+    Heap::RelocationLock relocation_lock(isolate_->heap());
     AllowHandleDereference ahd;
     optimizing_compiler->info()->closure()->MarkForInstallingRecompiledCode();
+    output_queue_.Enqueue(optimizing_compiler);
   }
-  output_queue_.Enqueue(optimizing_compiler);
 }
 
 
@@ -145,6 +151,9 @@
     }
     delete info;
   }
+
+  osr_candidates_.Clear();
+  RemoveStaleOSRCandidates(0);
 }
 
 
@@ -179,6 +188,10 @@
     PrintF("  ** Compiler thread did %.2f%% useful work\n", percentage);
   }
 
+  if (FLAG_trace_osr && FLAG_concurrent_osr) {
+    PrintF("[COSR hit rate %d / %d]\n", osr_hits_, osr_attempts_);
+  }
+
   Join();
 }
 
@@ -194,6 +207,10 @@
     }
     Compiler::InstallOptimizedCode(compiler);
   }
+
+  // Remove the oldest OSR candidates that are ready so that we
+  // only have limited number of them waiting.
+  if (FLAG_concurrent_osr) RemoveStaleOSRCandidates();
 }
 
 
@@ -202,12 +219,62 @@
   ASSERT(IsQueueAvailable());
   ASSERT(!IsOptimizerThread());
   Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1));
-  optimizing_compiler->info()->closure()->MarkInRecompileQueue();
+  if (optimizing_compiler->info()->osr_ast_id().IsNone()) {
+    optimizing_compiler->info()->closure()->MarkInRecompileQueue();
+  } else {
+    LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
+    osr_candidates_.Add(optimizing_compiler);
+    osr_attempts_++;
+  }
   input_queue_.Enqueue(optimizing_compiler);
   input_queue_semaphore_.Signal();
 }
 
 
+OptimizingCompiler* OptimizingCompilerThread::FindReadyOSRCandidate(
+    Handle<JSFunction> function, uint32_t osr_pc_offset) {
+  ASSERT(!IsOptimizerThread());
+  LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
+  for (int i = 0; i < ready_for_osr_.length(); i++) {
+    if (ready_for_osr_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) {
+      osr_hits_++;
+      return ready_for_osr_.Remove(i);
+    }
+  }
+  return NULL;
+}
+
+
+bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function,
+                                              uint32_t osr_pc_offset) {
+  ASSERT(!IsOptimizerThread());
+  LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
+  for (int i = 0; i < osr_candidates_.length(); i++) {
+    if (osr_candidates_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+void OptimizingCompilerThread::RemoveStaleOSRCandidates(int limit) {
+  ASSERT(!IsOptimizerThread());
+  LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
+  while (ready_for_osr_.length() > limit) {
+    OptimizingCompiler* compiler = ready_for_osr_.Remove(0);
+    CompilationInfo* throw_away = compiler->info();
+    if (FLAG_trace_osr) {
+      PrintF("[COSR - Discarded ");
+      throw_away->closure()->PrintName();
+      PrintF(", AST id %d]\n",
+             throw_away->osr_ast_id().ToInt());
+    }
+    delete throw_away;
+  }
+}
+
+
 #ifdef DEBUG
 bool OptimizingCompilerThread::IsOptimizerThread() {
   if (!FLAG_concurrent_recompilation) return false;
diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h
index bb96c74..01cd2a0 100644
--- a/src/optimizing-compiler-thread.h
+++ b/src/optimizing-compiler-thread.h
@@ -30,6 +30,7 @@
 
 #include "atomicops.h"
 #include "flags.h"
+#include "list.h"
 #include "platform.h"
 #include "platform/mutex.h"
 #include "platform/time.h"
@@ -51,7 +52,11 @@
 #endif
       isolate_(isolate),
       stop_semaphore_(0),
-      input_queue_semaphore_(0) {
+      input_queue_semaphore_(0),
+      osr_candidates_(2),
+      ready_for_osr_(2),
+      osr_hits_(0),
+      osr_attempts_(0) {
     NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE));
     NoBarrier_Store(&queue_length_, static_cast<AtomicWord>(0));
   }
@@ -62,6 +67,13 @@
   void Flush();
   void QueueForOptimization(OptimizingCompiler* optimizing_compiler);
   void InstallOptimizedFunctions();
+  OptimizingCompiler* FindReadyOSRCandidate(Handle<JSFunction> function,
+                                            uint32_t osr_pc_offset);
+  bool IsQueuedForOSR(Handle<JSFunction> function, uint32_t osr_pc_offset);
+
+  // Remove the oldest OSR candidates that are ready so that we
+  // only have |limit| left waiting.
+  void RemoveStaleOSRCandidates(int limit = kReadyForOSRLimit);
 
   inline bool IsQueueAvailable() {
     // We don't need a barrier since we have a data dependency right
@@ -86,7 +98,6 @@
 
   void FlushInputQueue(bool restore_function_code);
   void FlushOutputQueue(bool restore_function_code);
-
   void CompileNext();
 
 #ifdef DEBUG
@@ -97,13 +108,27 @@
   Isolate* isolate_;
   Semaphore stop_semaphore_;
   Semaphore input_queue_semaphore_;
+
+  // Queue of incoming recompilation tasks (including OSR).
   UnboundQueue<OptimizingCompiler*> input_queue_;
+  // Queue of recompilation tasks ready to be installed (excluding OSR).
   UnboundQueue<OptimizingCompiler*> output_queue_;
+  // List of all OSR related recompilation tasks (both incoming and ready ones).
+  List<OptimizingCompiler*> osr_candidates_;
+  // List of recompilation tasks ready for OSR.
+  List<OptimizingCompiler*> ready_for_osr_;
+
   Mutex install_mutex_;
   volatile AtomicWord stop_thread_;
   volatile Atomic32 queue_length_;
   TimeDelta time_spent_compiling_;
   TimeDelta time_spent_total_;
+
+  Mutex osr_list_mutex_;
+  int osr_hits_;
+  int osr_attempts_;
+
+  static const int kReadyForOSRLimit = 4;
 };
 
 } }  // namespace v8::internal
diff --git a/src/parser.cc b/src/parser.cc
index e4a6bb2..257f80d 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -3744,8 +3744,9 @@
 }
 
 
-Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
-  Factory* factory = Isolate::Current()->factory();
+Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
+                                              Expression* expression) {
+  Factory* factory = isolate->factory();
   ASSERT(IsCompileTimeValue(expression));
   Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
   ObjectLiteral* object_literal = expression->AsObjectLiteral();
@@ -3784,7 +3785,7 @@
     return expression->AsLiteral()->value();
   }
   if (CompileTimeValue::IsCompileTimeValue(expression)) {
-    return CompileTimeValue::GetValue(expression);
+    return CompileTimeValue::GetValue(isolate(), expression);
   }
   return isolate()->factory()->uninitialized_value();
 }
@@ -5023,7 +5024,7 @@
                            Handle<String>* error,
                            bool multiline,
                            Zone* zone)
-    : isolate_(Isolate::Current()),
+    : isolate_(zone->isolate()),
       zone_(zone),
       error_(error),
       captures_(NULL),
@@ -5895,9 +5896,9 @@
 
 
 // Create a Scanner for the preparser to use as input, and preparse the source.
-ScriptDataImpl* PreParserApi::PreParse(Utf16CharacterStream* source) {
+ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate,
+                                       Utf16CharacterStream* source) {
   CompleteParserRecorder recorder;
-  Isolate* isolate = Isolate::Current();
   HistogramTimerScope timer(isolate->counters()->pre_parse());
   Scanner scanner(isolate->unicode_cache());
   intptr_t stack_limit = isolate->stack_guard()->real_climit();
diff --git a/src/parser.h b/src/parser.h
index 2f26b84..783626a 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -170,7 +170,8 @@
   // This interface is here instead of in preparser.h because it instantiates a
   // preparser recorder object that is suited to the parser's purposes.  Also,
   // the preparser doesn't know about ScriptDataImpl.
-  static ScriptDataImpl* PreParse(Utf16CharacterStream* source);
+  static ScriptDataImpl* PreParse(Isolate* isolate,
+                                  Utf16CharacterStream* source);
 };
 
 
@@ -894,7 +895,7 @@
   static bool IsCompileTimeValue(Expression* expression);
 
   // Get the value as a compile time value.
-  static Handle<FixedArray> GetValue(Expression* expression);
+  static Handle<FixedArray> GetValue(Isolate* isolate, Expression* expression);
 
   // Get the type of a compile time value returned by GetValue().
   static LiteralType GetLiteralType(Handle<FixedArray> value);
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index aaf0ca7..504d140 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -739,202 +739,4 @@
 }
 
 
-// ----------------------------------------------------------------------------
-// POSIX socket support.
-//
-
-class POSIXSocket : public Socket {
- public:
-  explicit POSIXSocket() {
-    // Create the socket.
-    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (IsValid()) {
-      // Allow rapid reuse.
-      static const int kOn = 1;
-      int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
-                           &kOn, sizeof(kOn));
-      ASSERT(ret == 0);
-      USE(ret);
-    }
-  }
-  explicit POSIXSocket(int socket): socket_(socket) { }
-  virtual ~POSIXSocket() { Shutdown(); }
-
-  // Server initialization.
-  bool Bind(const int port);
-  bool Listen(int backlog) const;
-  Socket* Accept() const;
-
-  // Client initialization.
-  bool Connect(const char* host, const char* port);
-
-  // Shutdown socket for both read and write.
-  bool Shutdown();
-
-  // Data Transimission
-  int Send(const char* data, int len) const;
-  int Receive(char* data, int len) const;
-
-  bool SetReuseAddress(bool reuse_address);
-
-  bool IsValid() const { return socket_ != -1; }
-
- private:
-  int socket_;
-};
-
-
-bool POSIXSocket::Bind(const int port) {
-  if (!IsValid())  {
-    return false;
-  }
-
-  sockaddr_in addr;
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-  addr.sin_port = htons(port);
-  int status = bind(socket_,
-                    BitCast<struct sockaddr *>(&addr),
-                    sizeof(addr));
-  return status == 0;
-}
-
-
-bool POSIXSocket::Listen(int backlog) const {
-  if (!IsValid()) {
-    return false;
-  }
-
-  int status = listen(socket_, backlog);
-  return status == 0;
-}
-
-
-Socket* POSIXSocket::Accept() const {
-  if (!IsValid()) {
-    return NULL;
-  }
-
-  int socket;
-  do {
-    socket = accept(socket_, NULL, NULL);
-  } while (socket == -1 && errno == EINTR);
-
-  if (socket == -1) {
-    return NULL;
-  } else {
-    return new POSIXSocket(socket);
-  }
-}
-
-
-bool POSIXSocket::Connect(const char* host, const char* port) {
-  if (!IsValid()) {
-    return false;
-  }
-
-  // Lookup host and port.
-  struct addrinfo *result = NULL;
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof(addrinfo));
-  hints.ai_family = AF_INET;
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_protocol = IPPROTO_TCP;
-  int status = getaddrinfo(host, port, &hints, &result);
-  if (status != 0) {
-    return false;
-  }
-
-  // Connect.
-  do {
-    status = connect(socket_, result->ai_addr, result->ai_addrlen);
-  } while (status == -1 && errno == EINTR);
-  freeaddrinfo(result);
-  return status == 0;
-}
-
-
-bool POSIXSocket::Shutdown() {
-  if (IsValid()) {
-    // Shutdown socket for both read and write.
-    int status = shutdown(socket_, SHUT_RDWR);
-    close(socket_);
-    socket_ = -1;
-    return status == 0;
-  }
-  return true;
-}
-
-
-int POSIXSocket::Send(const char* data, int len) const {
-  if (len <= 0) return 0;
-  int written = 0;
-  while (written < len) {
-    int status = send(socket_, data + written, len - written, 0);
-    if (status == 0) {
-      break;
-    } else if (status > 0) {
-      written += status;
-    } else if (errno != EINTR) {
-      return 0;
-    }
-  }
-  return written;
-}
-
-
-int POSIXSocket::Receive(char* data, int len) const {
-  if (len <= 0) return 0;
-  int status;
-  do {
-    status = recv(socket_, data, len, 0);
-  } while (status == -1 && errno == EINTR);
-  return (status < 0) ? 0 : status;
-}
-
-
-bool POSIXSocket::SetReuseAddress(bool reuse_address) {
-  int on = reuse_address ? 1 : 0;
-  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-  return status == 0;
-}
-
-
-bool Socket::SetUp() {
-  // Nothing to do on POSIX.
-  return true;
-}
-
-
-int Socket::LastError() {
-  return errno;
-}
-
-
-uint16_t Socket::HToN(uint16_t value) {
-  return htons(value);
-}
-
-
-uint16_t Socket::NToH(uint16_t value) {
-  return ntohs(value);
-}
-
-
-uint32_t Socket::HToN(uint32_t value) {
-  return htonl(value);
-}
-
-
-uint32_t Socket::NToH(uint32_t value) {
-  return ntohl(value);
-}
-
-
-Socket* OS::CreateSocket() {
-  return new POSIXSocket();
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 199ed2d..87387e7 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1615,198 +1615,6 @@
 }
 
 
-// ----------------------------------------------------------------------------
-// Win32 socket support.
-//
-
-class Win32Socket : public Socket {
- public:
-  explicit Win32Socket() {
-    // Create the socket.
-    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-  }
-  explicit Win32Socket(SOCKET socket): socket_(socket) { }
-  virtual ~Win32Socket() { Shutdown(); }
-
-  // Server initialization.
-  bool Bind(const int port);
-  bool Listen(int backlog) const;
-  Socket* Accept() const;
-
-  // Client initialization.
-  bool Connect(const char* host, const char* port);
-
-  // Shutdown socket for both read and write.
-  bool Shutdown();
-
-  // Data Transimission
-  int Send(const char* data, int len) const;
-  int Receive(char* data, int len) const;
-
-  bool SetReuseAddress(bool reuse_address);
-
-  bool IsValid() const { return socket_ != INVALID_SOCKET; }
-
- private:
-  SOCKET socket_;
-};
-
-
-bool Win32Socket::Bind(const int port) {
-  if (!IsValid())  {
-    return false;
-  }
-
-  sockaddr_in addr;
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-  addr.sin_port = htons(port);
-  int status = bind(socket_,
-                    reinterpret_cast<struct sockaddr *>(&addr),
-                    sizeof(addr));
-  return status == 0;
-}
-
-
-bool Win32Socket::Listen(int backlog) const {
-  if (!IsValid()) {
-    return false;
-  }
-
-  int status = listen(socket_, backlog);
-  return status == 0;
-}
-
-
-Socket* Win32Socket::Accept() const {
-  if (!IsValid()) {
-    return NULL;
-  }
-
-  SOCKET socket = accept(socket_, NULL, NULL);
-  if (socket == INVALID_SOCKET) {
-    return NULL;
-  } else {
-    return new Win32Socket(socket);
-  }
-}
-
-
-bool Win32Socket::Connect(const char* host, const char* port) {
-  if (!IsValid()) {
-    return false;
-  }
-
-  // Lookup host and port.
-  struct addrinfo *result = NULL;
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof(addrinfo));
-  hints.ai_family = AF_INET;
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_protocol = IPPROTO_TCP;
-  int status = getaddrinfo(host, port, &hints, &result);
-  if (status != 0) {
-    return false;
-  }
-
-  // Connect.
-  status = connect(socket_,
-                   result->ai_addr,
-                   static_cast<int>(result->ai_addrlen));
-  freeaddrinfo(result);
-  return status == 0;
-}
-
-
-bool Win32Socket::Shutdown() {
-  if (IsValid()) {
-    // Shutdown socket for both read and write.
-    int status = shutdown(socket_, SD_BOTH);
-    closesocket(socket_);
-    socket_ = INVALID_SOCKET;
-    return status == SOCKET_ERROR;
-  }
-  return true;
-}
-
-
-int Win32Socket::Send(const char* data, int len) const {
-  if (len <= 0) return 0;
-  int written = 0;
-  while (written < len) {
-    int status = send(socket_, data + written, len - written, 0);
-    if (status == 0) {
-      break;
-    } else if (status > 0) {
-      written += status;
-    } else {
-      return 0;
-    }
-  }
-  return written;
-}
-
-
-int Win32Socket::Receive(char* data, int len) const {
-  if (len <= 0) return 0;
-  int status = recv(socket_, data, len, 0);
-  return (status == SOCKET_ERROR) ? 0 : status;
-}
-
-
-bool Win32Socket::SetReuseAddress(bool reuse_address) {
-  BOOL on = reuse_address ? true : false;
-  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
-                          reinterpret_cast<char*>(&on), sizeof(on));
-  return status == SOCKET_ERROR;
-}
-
-
-bool Socket::SetUp() {
-  // Initialize Winsock32
-  int err;
-  WSADATA winsock_data;
-  WORD version_requested = MAKEWORD(1, 0);
-  err = WSAStartup(version_requested, &winsock_data);
-  if (err != 0) {
-    PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError());
-  }
-
-  return err == 0;
-}
-
-
-int Socket::LastError() {
-  return WSAGetLastError();
-}
-
-
-uint16_t Socket::HToN(uint16_t value) {
-  return htons(value);
-}
-
-
-uint16_t Socket::NToH(uint16_t value) {
-  return ntohs(value);
-}
-
-
-uint32_t Socket::HToN(uint32_t value) {
-  return htonl(value);
-}
-
-
-uint32_t Socket::NToH(uint32_t value) {
-  return ntohl(value);
-}
-
-
-Socket* OS::CreateSocket() {
-  return new Win32Socket();
-}
-
-
 void OS::SetUp() {
   // Seed the random number generator.
   // Convert the current time to a 64-bit integer first, before converting it
diff --git a/src/platform.h b/src/platform.h
index 8565775..18bf6b0 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -108,9 +108,6 @@
 // on demand.
 void lazily_initialize_fast_exp();
 
-// Forward declarations.
-class Socket;
-
 // ----------------------------------------------------------------------------
 // Fast TLS support
 
@@ -287,10 +284,6 @@
 
   static int StackWalk(Vector<StackFrame> frames);
 
-  // Factory method for creating platform dependent Socket.
-  // Please use delete to reclaim the storage for the returned Socket.
-  static Socket* CreateSocket();
-
   class MemoryMappedFile {
    public:
     static MemoryMappedFile* open(const char* name);
@@ -619,47 +612,6 @@
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
 
-
-// ----------------------------------------------------------------------------
-// Socket
-//
-
-class Socket {
- public:
-  virtual ~Socket() {}
-
-  // Server initialization.
-  virtual bool Bind(const int port) = 0;
-  virtual bool Listen(int backlog) const = 0;
-  virtual Socket* Accept() const = 0;
-
-  // Client initialization.
-  virtual bool Connect(const char* host, const char* port) = 0;
-
-  // Shutdown socket for both read and write. This causes blocking Send and
-  // Receive calls to exit. After Shutdown the Socket object cannot be used for
-  // any communication.
-  virtual bool Shutdown() = 0;
-
-  // Data Transimission
-  // Return 0 on failure.
-  virtual int Send(const char* data, int len) const = 0;
-  virtual int Receive(char* data, int len) const = 0;
-
-  // Set the value of the SO_REUSEADDR socket option.
-  virtual bool SetReuseAddress(bool reuse_address) = 0;
-
-  virtual bool IsValid() const = 0;
-
-  static bool SetUp();
-  static int LastError();
-  static uint16_t HToN(uint16_t value);
-  static uint16_t NToH(uint16_t value);
-  static uint32_t HToN(uint32_t value);
-  static uint32_t NToH(uint32_t value);
-};
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_PLATFORM_H_
diff --git a/src/platform/condition-variable.cc b/src/platform/condition-variable.cc
index 84df976..e2bf388 100644
--- a/src/platform/condition-variable.cc
+++ b/src/platform/condition-variable.cc
@@ -41,8 +41,8 @@
   // TODO(bmeurer): The test for V8_LIBRT_NOT_AVAILABLE is a temporary
   // hack to support cross-compiling Chrome for Android in AOSP. Remove
   // this once AOSP is fixed.
-#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || V8_LIBC_GLIBC) && \
-    !V8_LIBRT_NOT_AVAILABLE
+#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+     (V8_OS_LINUX && V8_LIBC_GLIBC)) && !V8_LIBRT_NOT_AVAILABLE
   // On Free/Net/OpenBSD and Linux with glibc we can change the time
   // source for pthread_cond_timedwait() to use the monotonic clock.
   pthread_condattr_t attr;
@@ -107,8 +107,8 @@
   // TODO(bmeurer): The test for V8_LIBRT_NOT_AVAILABLE is a temporary
   // hack to support cross-compiling Chrome for Android in AOSP. Remove
   // this once AOSP is fixed.
-#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || V8_LIBC_GLIBC) && \
-    !V8_LIBRT_NOT_AVAILABLE
+#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+     (V8_OS_LINUX && V8_LIBC_GLIBC)) && !V8_LIBRT_NOT_AVAILABLE
   // On Free/Net/OpenBSD and Linux with glibc we can change the time
   // source for pthread_cond_timedwait() to use the monotonic clock.
   result = clock_gettime(CLOCK_MONOTONIC, &ts);
diff --git a/src/platform/mutex.h b/src/platform/mutex.h
index c760c20..ff519b9 100644
--- a/src/platform/mutex.h
+++ b/src/platform/mutex.h
@@ -230,8 +230,7 @@
  private:
   Mutex* mutex_;
 
-  LockGuard(const LockGuard<Mutex>& other) V8_DELETE;
-  LockGuard<Mutex>& operator=(const LockGuard<Mutex>& other) V8_DELETE;
+  DISALLOW_COPY_AND_ASSIGN(LockGuard);
 };
 
 } }  // namespace v8::internal
diff --git a/src/platform/socket.cc b/src/platform/socket.cc
new file mode 100644
index 0000000..2fce6f2
--- /dev/null
+++ b/src/platform/socket.cc
@@ -0,0 +1,224 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "platform/socket.h"
+
+#if V8_OS_POSIX
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <unistd.h>
+#endif
+
+#include <cerrno>
+
+#include "checks.h"
+#include "once.h"
+
+namespace v8 {
+namespace internal {
+
+#if V8_OS_WIN
+
+static V8_DECLARE_ONCE(initialize_winsock) = V8_ONCE_INIT;
+
+
+static void InitializeWinsock() {
+  WSADATA wsa_data;
+  int result = WSAStartup(MAKEWORD(1, 0), &wsa_data);
+  CHECK_EQ(0, result);
+}
+
+#endif  // V8_OS_WIN
+
+
+Socket::Socket() {
+#if V8_OS_WIN
+  // Be sure to initialize the WinSock DLL first.
+  CallOnce(&initialize_winsock, &InitializeWinsock);
+#endif  // V8_OS_WIN
+
+  // Create the native socket handle.
+  native_handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+}
+
+
+bool Socket::Bind(int port) {
+  ASSERT_GE(port, 0);
+  ASSERT_LT(port, 65536);
+  if (!IsValid()) return false;
+  struct sockaddr_in sin;
+  memset(&sin, 0, sizeof(sin));
+  sin.sin_family = AF_INET;
+  sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  sin.sin_port = htons(static_cast<uint16_t>(port));
+  int result = ::bind(
+      native_handle_, reinterpret_cast<struct sockaddr*>(&sin), sizeof(sin));
+  return result == 0;
+}
+
+
+bool Socket::Listen(int backlog) {
+  if (!IsValid()) return false;
+  int result = ::listen(native_handle_, backlog);
+  return result == 0;
+}
+
+
+Socket* Socket::Accept() {
+  if (!IsValid()) return NULL;
+  while (true) {
+    NativeHandle native_handle = ::accept(native_handle_, NULL, NULL);
+    if (native_handle == kInvalidNativeHandle) {
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      return NULL;
+    }
+    return new Socket(native_handle);
+  }
+}
+
+
+bool Socket::Connect(const char* host, const char* port) {
+  ASSERT_NE(NULL, host);
+  ASSERT_NE(NULL, port);
+  if (!IsValid()) return false;
+
+  // Lookup host and port.
+  struct addrinfo* info = NULL;
+  struct addrinfo hint;
+  memset(&hint, 0, sizeof(hint));
+  hint.ai_family = AF_INET;
+  hint.ai_socktype = SOCK_STREAM;
+  hint.ai_protocol = IPPROTO_TCP;
+  int result = ::getaddrinfo(host, port, &hint, &info);
+  if (result != 0) {
+    return false;
+  }
+
+  // Connect to the host on the given port.
+  for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) {
+    // Try to connect using this addr info.
+    while (true) {
+      result = ::connect(
+          native_handle_, ai->ai_addr, static_cast<int>(ai->ai_addrlen));
+      if (result == 0) {
+        freeaddrinfo(info);
+        return true;
+      }
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      break;
+    }
+  }
+  freeaddrinfo(info);
+  return false;
+}
+
+
+bool Socket::Shutdown() {
+  if (!IsValid()) return false;
+  // Shutdown socket for both read and write.
+#if V8_OS_POSIX
+  int result = ::shutdown(native_handle_, SHUT_RDWR);
+  ::close(native_handle_);
+#elif V8_OS_WIN
+  int result = ::shutdown(native_handle_, SD_BOTH);
+  ::closesocket(native_handle_);
+#endif
+  native_handle_ = kInvalidNativeHandle;
+  return result == 0;
+}
+
+
+int Socket::Send(const char* buffer, int length) {
+  ASSERT(length <= 0 || buffer != NULL);
+  if (!IsValid()) return 0;
+  int offset = 0;
+  while (offset < length) {
+    int result = ::send(native_handle_, buffer + offset, length - offset, 0);
+    if (result == 0) {
+      break;
+    } else if (result > 0) {
+      ASSERT(result <= length - offset);
+      offset += result;
+    } else {
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      return 0;
+    }
+  }
+  return offset;
+}
+
+
+int Socket::Receive(char* buffer, int length) {
+  if (!IsValid()) return 0;
+  if (length <= 0) return 0;
+  ASSERT_NE(NULL, buffer);
+  while (true) {
+    int result = ::recv(native_handle_, buffer, length, 0);
+    if (result < 0) {
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      return 0;
+    }
+    return result;
+  }
+}
+
+
+bool Socket::SetReuseAddress(bool reuse_address) {
+  if (!IsValid()) return 0;
+  int v = reuse_address ? 1 : 0;
+  int result = ::setsockopt(native_handle_, SOL_SOCKET, SO_REUSEADDR,
+                            reinterpret_cast<char*>(&v), sizeof(v));
+  return result == 0;
+}
+
+
+// static
+int Socket::GetLastError() {
+#if V8_OS_POSIX
+  return errno;
+#elif V8_OS_WIN
+  // Be sure to initialize the WinSock DLL first.
+  CallOnce(&initialize_winsock, &InitializeWinsock);
+
+  // Now we can safely perform WSA calls.
+  return ::WSAGetLastError();
+#endif
+}
+
+} }  // namespace v8::internal
diff --git a/src/platform/socket.h b/src/platform/socket.h
new file mode 100644
index 0000000..6710692
--- /dev/null
+++ b/src/platform/socket.h
@@ -0,0 +1,101 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PLATFORM_SOCKET_H_
+#define V8_PLATFORM_SOCKET_H_
+
+#include "globals.h"
+#if V8_OS_WIN
+#include "win32-headers.h"
+#endif
+
+namespace v8 {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+// Socket
+//
+
+class Socket V8_FINAL {
+ public:
+  Socket();
+  ~Socket() { Shutdown(); }
+
+  // Server initialization.
+  bool Bind(int port) V8_WARN_UNUSED_RESULT;
+  bool Listen(int backlog) V8_WARN_UNUSED_RESULT;
+  Socket* Accept() V8_WARN_UNUSED_RESULT;
+
+  // Client initialization.
+  bool Connect(const char* host, const char* port) V8_WARN_UNUSED_RESULT;
+
+  // Shutdown socket for both read and write. This causes blocking Send and
+  // Receive calls to exit. After |Shutdown()| the Socket object cannot be
+  // used for any communication.
+  bool Shutdown();
+
+  // Data Transimission
+  // Return 0 on failure.
+  int Send(const char* buffer, int length) V8_WARN_UNUSED_RESULT;
+  int Receive(char* buffer, int length) V8_WARN_UNUSED_RESULT;
+
+  // Set the value of the SO_REUSEADDR socket option.
+  bool SetReuseAddress(bool reuse_address);
+
+  V8_INLINE(bool IsValid()) const V8_WARN_UNUSED_RESULT {
+    return native_handle_ != kInvalidNativeHandle;
+  }
+
+  static int GetLastError() V8_WARN_UNUSED_RESULT;
+
+  // The implementation-defined native handle type.
+#if V8_OS_POSIX
+  typedef int NativeHandle;
+  static const NativeHandle kInvalidNativeHandle = -1;
+#elif V8_OS_WIN
+  typedef SOCKET NativeHandle;
+  static const NativeHandle kInvalidNativeHandle = INVALID_SOCKET;
+#endif
+
+  NativeHandle& native_handle() V8_WARN_UNUSED_RESULT {
+    return native_handle_;
+  }
+  const NativeHandle& native_handle() const V8_WARN_UNUSED_RESULT {
+    return native_handle_;
+  }
+
+ private:
+  explicit Socket(NativeHandle native_handle) : native_handle_(native_handle) {}
+
+  NativeHandle native_handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(Socket);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PLATFORM_SOCKET_H_
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index 57c50dd..cfce1df 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -172,9 +172,9 @@
   // any back edge in any unoptimized frame will trigger on-stack
   // replacement for that frame.
   if (FLAG_trace_osr) {
-    PrintF("[patching back edges in ");
+    PrintF("[OSR - patching back edges in ");
     function->PrintName();
-    PrintF(" for on-stack replacement]\n");
+    PrintF("]\n");
   }
 
   Deoptimizer::PatchInterruptCode(isolate_, shared->code());
diff --git a/src/runtime.cc b/src/runtime.cc
index d183a6b..5c6bf39 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -4774,10 +4774,10 @@
   }
 
   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
-    return object->GetPrototype(isolate)->GetElement(index);
+    return object->GetPrototype(isolate)->GetElement(isolate, index);
   }
 
-  return object->GetElement(index);
+  return object->GetElement(isolate, index);
 }
 
 
@@ -5904,7 +5904,7 @@
     if (index < n) {
       return frame->GetParameter(index);
     } else {
-      return isolate->initial_object_prototype()->GetElement(index);
+      return isolate->initial_object_prototype()->GetElement(isolate, index);
     }
   }
 
@@ -6679,7 +6679,7 @@
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(String, value, 0);
-  return value->ToObject();
+  return value->ToObject(isolate);
 }
 
 
@@ -7528,7 +7528,7 @@
     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
   }
   ASSERT(result ==
-      StringCharacterStreamCompare(Isolate::Current()->runtime_state(), x, y));
+      StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
   return result;
 }
 
@@ -8343,7 +8343,9 @@
   }
   function->shared()->code()->set_profiler_ticks(0);
   ASSERT(FLAG_concurrent_recompilation);
-  Compiler::RecompileConcurrent(function);
+  if (!Compiler::RecompileConcurrent(function)) {
+    function->ReplaceCode(function->shared()->code());
+  }
   return isolate->heap()->undefined_value();
 }
 
@@ -8512,7 +8514,11 @@
       unoptimized->kind() == Code::FUNCTION) {
     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
     if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
-      for (int i = 0; i <= Code::kMaxLoopNestingMarker; i++) {
+      // Start patching from the currently patched loop nesting level.
+      int current_level = unoptimized->allow_osr_at_loop_nesting_level();
+      ASSERT(Deoptimizer::VerifyInterruptCode(
+                 isolate, unoptimized, current_level));
+      for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
         unoptimized->set_allow_osr_at_loop_nesting_level(i);
         isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
       }
@@ -8586,98 +8592,19 @@
   // We're not prepared to handle a function with arguments object.
   ASSERT(!function->shared()->uses_arguments());
 
-  // We have hit a back edge in an unoptimized frame for a function that was
-  // selected for on-stack replacement.  Find the unoptimized code object.
-  Handle<Code> unoptimized(function->shared()->code(), isolate);
-  // Keep track of whether we've succeeded in optimizing.
-  bool succeeded = unoptimized->optimizable();
-  if (succeeded) {
-    // If we are trying to do OSR when there are already optimized
-    // activations of the function, it means (a) the function is directly or
-    // indirectly recursive and (b) an optimized invocation has been
-    // deoptimized so that we are currently in an unoptimized activation.
-    // Check for optimized activations of this function.
-    JavaScriptFrameIterator it(isolate);
-    while (succeeded && !it.done()) {
-      JavaScriptFrame* frame = it.frame();
-      succeeded = !frame->is_optimized() || frame->function() != *function;
-      it.Advance();
-    }
-  }
-
-  BailoutId ast_id = BailoutId::None();
-  if (succeeded) {
-    // The top JS function is this one, the PC is somewhere in the
-    // unoptimized code.
-    JavaScriptFrameIterator it(isolate);
-    JavaScriptFrame* frame = it.frame();
-    ASSERT(frame->function() == *function);
-    ASSERT(frame->LookupCode() == *unoptimized);
-    ASSERT(unoptimized->contains(frame->pc()));
-
-    // Use linear search of the unoptimized code's back edge table to find
-    // the AST id matching the PC.
-    uint32_t target_pc_offset =
-      static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
-    uint32_t loop_depth = 0;
-
-    for (FullCodeGenerator::BackEdgeTableIterator back_edges(*unoptimized);
-         !back_edges.Done();
-         back_edges.Next()) {
-      if (back_edges.pc_offset() == target_pc_offset) {
-        ast_id = back_edges.ast_id();
-        loop_depth = back_edges.loop_depth();
-        break;
-      }
-    }
-    ASSERT(!ast_id.IsNone());
-
-    if (FLAG_trace_osr) {
-      PrintF("[replacing on-stack at AST id %d, loop depth %d in ",
-              ast_id.ToInt(), loop_depth);
-      function->PrintName();
-      PrintF("]\n");
-    }
-
-    // Try to compile the optimized code.  A true return value from
-    // CompileOptimized means that compilation succeeded, not necessarily
-    // that optimization succeeded.
-    if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
-        function->IsOptimized()) {
-      DeoptimizationInputData* data = DeoptimizationInputData::cast(
-          function->code()->deoptimization_data());
-      if (data->OsrPcOffset()->value() >= 0) {
-        if (FLAG_trace_osr) {
-          PrintF("[on-stack replacement offset %d in optimized code]\n",
-               data->OsrPcOffset()->value());
-        }
-        ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
-      } else {
-        // We may never generate the desired OSR entry if we emit an
-        // early deoptimize.
-        succeeded = false;
-      }
-    } else {
-      succeeded = false;
-    }
-  }
-
-  // Revert to the original interrupt calls in the original unoptimized code.
-  if (FLAG_trace_osr) {
-    PrintF("[restoring original interrupt calls in ");
-    function->PrintName();
-    PrintF("]\n");
-  }
-  Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
-
   // If the optimization attempt succeeded, return the AST id tagged as a
   // smi. This tells the builtin that we need to translate the unoptimized
   // frame to an optimized one.
-  if (succeeded) {
+  BailoutId ast_id =
+      (FLAG_concurrent_recompilation && FLAG_concurrent_osr)
+          ? Compiler::CompileForConcurrentOSR(function)
+          : Compiler::CompileForOnStackReplacement(function);
+  if (!ast_id.IsNone()) {
     ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
     return Smi::FromInt(ast_id.ToInt());
   } else {
-    if (function->IsMarkedForLazyRecompilation()) {
+    if (function->IsMarkedForLazyRecompilation() ||
+        function->IsMarkedForConcurrentRecompilation()) {
       function->ReplaceCode(function->shared()->code());
     }
     return Smi::FromInt(-1);
@@ -8771,7 +8698,7 @@
   }
 
   for (int i = 0; i < argc; ++i) {
-    argv[i] = Object::GetElement(arguments, offset + i);
+    argv[i] = Object::GetElement(isolate, arguments, offset + i);
   }
 
   bool threw;
@@ -8844,7 +8771,7 @@
     extension_object = JSReceiver::cast(args[0]);
   } else {
     // Convert the object to a proper JavaScript object.
-    MaybeObject* maybe_js_object = args[0]->ToObject();
+    MaybeObject* maybe_js_object = args[0]->ToObject(isolate);
     if (!maybe_js_object->To(&extension_object)) {
       if (Failure::cast(maybe_js_object)->IsInternalError()) {
         HandleScope scope(isolate);
@@ -10158,7 +10085,7 @@
         } else if (receiver->HasElement(j)) {
           // Call GetElement on receiver, not its prototype, or getters won't
           // have the correct receiver.
-          element_value = Object::GetElement(receiver, j);
+          element_value = Object::GetElement(isolate, receiver, j);
           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
           visitor->visit(j, element_value);
         }
@@ -10183,7 +10110,8 @@
         } else if (receiver->HasElement(j)) {
           // Call GetElement on receiver, not its prototype, or getters won't
           // have the correct receiver.
-          Handle<Object> element_value = Object::GetElement(receiver, j);
+          Handle<Object> element_value =
+              Object::GetElement(isolate, receiver, j);
           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
           visitor->visit(j, element_value);
         }
@@ -10202,7 +10130,7 @@
       while (j < n) {
         HandleScope loop_scope(isolate);
         uint32_t index = indices[j];
-        Handle<Object> element = Object::GetElement(receiver, index);
+        Handle<Object> element = Object::GetElement(isolate, receiver, index);
         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
         visitor->visit(index, element);
         // Skip to next different index (i.e., omit duplicates).
@@ -13590,7 +13518,7 @@
   Handle<Name> base =
       isolate->factory()->NewStringFromAscii(CStrVector("base"));
   for (unsigned int i = 0; i < length; ++i) {
-    MaybeObject* maybe_string = input->GetElement(i);
+    MaybeObject* maybe_string = input->GetElement(isolate, i);
     Object* locale_id;
     if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
       return isolate->Throw(isolate->heap()->illegal_argument_string());
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index c9df1fb..3d09d3a 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -74,7 +74,7 @@
       + parameter_count + stack_local_count + 2 * context_local_count
       + (has_function_name ? 2 : 0);
 
-  Factory* factory = Isolate::Current()->factory();
+  Factory* factory = zone->isolate()->factory();
   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
 
   // Encode the flags.
diff --git a/src/scopes.cc b/src/scopes.cc
index e38e903..ce1741a 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -129,7 +129,7 @@
              ScopeType scope_type,
              Handle<ScopeInfo> scope_info,
              Zone* zone)
-    : isolate_(Isolate::Current()),
+    : isolate_(zone->isolate()),
       inner_scopes_(4, zone),
       variables_(zone),
       internals_(4, zone),
@@ -152,7 +152,7 @@
 
 
 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
-    : isolate_(Isolate::Current()),
+    : isolate_(zone->isolate()),
       inner_scopes_(1, zone),
       variables_(zone),
       internals_(0, zone),
@@ -1092,7 +1092,7 @@
     // Assignment to const. Throw a syntax error.
     MessageLocation location(
         info->script(), proxy->position(), proxy->position());
-    Isolate* isolate = Isolate::Current();
+    Isolate* isolate = info->isolate();
     Factory* factory = isolate->factory();
     Handle<JSArray> array = factory->NewJSArray(0);
     Handle<Object> result =
@@ -1123,7 +1123,7 @@
       // TODO(rossberg): generate more helpful error message.
       MessageLocation location(
           info->script(), proxy->position(), proxy->position());
-      Isolate* isolate = Isolate::Current();
+      Isolate* isolate = info->isolate();
       Factory* factory = isolate->factory();
       Handle<JSArray> array = factory->NewJSArray(1);
       USE(JSObject::SetElement(array, 0, var->name(), NONE, kStrictMode));
diff --git a/src/serialize.cc b/src/serialize.cc
index 746c926..6f84aed 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -596,9 +596,9 @@
 }
 
 
-ExternalReferenceEncoder::ExternalReferenceEncoder()
+ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate)
     : encodings_(Match),
-      isolate_(Isolate::Current()) {
+      isolate_(isolate) {
   ExternalReferenceTable* external_references =
       ExternalReferenceTable::instance(isolate_);
   for (int i = 0; i < external_references->size(); ++i) {
@@ -638,9 +638,9 @@
 }
 
 
-ExternalReferenceDecoder::ExternalReferenceDecoder()
+ExternalReferenceDecoder::ExternalReferenceDecoder(Isolate* isolate)
     : encodings_(NewArray<Address*>(kTypeCodeCount)),
-      isolate_(Isolate::Current()) {
+      isolate_(isolate) {
   ExternalReferenceTable* external_references =
       ExternalReferenceTable::instance(isolate_);
   for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
@@ -780,13 +780,12 @@
 CodeAddressMap* Serializer::code_address_map_ = NULL;
 
 
-void Serializer::Enable() {
+void Serializer::Enable(Isolate* isolate) {
   if (!serialization_enabled_) {
     ASSERT(!too_late_to_enable_now_);
   }
   if (serialization_enabled_) return;
   serialization_enabled_ = true;
-  i::Isolate* isolate = Isolate::Current();
   isolate->InitializeLoggingAndCounters();
   code_address_map_ = new CodeAddressMap(isolate);
 }
@@ -810,8 +809,8 @@
 }
 
 
-void Deserializer::Deserialize() {
-  isolate_ = Isolate::Current();
+void Deserializer::Deserialize(Isolate* isolate) {
+  isolate_ = isolate;
   ASSERT(isolate_ != NULL);
   isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
   // No active threads.
@@ -819,7 +818,7 @@
   // No active handles.
   ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty());
   ASSERT_EQ(NULL, external_reference_decoder_);
-  external_reference_decoder_ = new ExternalReferenceDecoder();
+  external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
   isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
   isolate_->heap()->RepairFreeListsAfterBoot();
   isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
@@ -850,14 +849,14 @@
 }
 
 
-void Deserializer::DeserializePartial(Object** root) {
-  isolate_ = Isolate::Current();
+void Deserializer::DeserializePartial(Isolate* isolate, Object** root) {
+  isolate_ = isolate;
   for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
     ASSERT(reservations_[i] != kUninitializedReservation);
   }
   isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
   if (external_reference_decoder_ == NULL) {
-    external_reference_decoder_ = new ExternalReferenceDecoder();
+    external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
   }
 
   // Keep track of the code space start and end pointers in case new
@@ -1277,12 +1276,12 @@
 }
 
 
-Serializer::Serializer(SnapshotByteSink* sink)
-    : sink_(sink),
+Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
+    : isolate_(isolate),
+      sink_(sink),
       current_root_index_(0),
-      external_reference_encoder_(new ExternalReferenceEncoder),
+      external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
       root_index_wave_front_(0) {
-  isolate_ = Isolate::Current();
   // The serializer is meant to be used only to generate initial heap images
   // from a context in which there is only one isolate.
   ASSERT(isolate_->IsDefaultIsolate());
@@ -1298,9 +1297,9 @@
 
 
 void StartupSerializer::SerializeStrongReferences() {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = this->isolate();
   // No active threads.
-  CHECK_EQ(NULL, Isolate::Current()->thread_manager()->FirstThreadStateInUse());
+  CHECK_EQ(NULL, isolate->thread_manager()->FirstThreadStateInUse());
   // No active or weak handles.
   CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
   CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
@@ -1319,7 +1318,7 @@
 
 
 void Serializer::VisitPointers(Object** start, Object** end) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = this->isolate();;
 
   for (Object** current = start; current < end; current++) {
     if (start == isolate->heap()->roots_array_start()) {
@@ -1350,9 +1349,9 @@
 // that correspond to the elements of this cache array.  On deserialization we
 // therefore need to visit the cache array.  This fills it up with pointers to
 // deserialized objects.
-void SerializerDeserializer::Iterate(ObjectVisitor* visitor) {
+void SerializerDeserializer::Iterate(Isolate* isolate,
+                                     ObjectVisitor* visitor) {
   if (Serializer::enabled()) return;
-  Isolate* isolate = Isolate::Current();
   for (int i = 0; ; i++) {
     if (isolate->serialize_partial_snapshot_cache_length() <= i) {
       // Extend the array ready to get a value from the visitor when
@@ -1371,7 +1370,7 @@
 
 
 int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = this->isolate();
 
   for (int i = 0;
        i < isolate->serialize_partial_snapshot_cache_length();
@@ -1394,7 +1393,7 @@
 
 
 int Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
-  Heap* heap = HEAP;
+  Heap* heap = isolate()->heap();
   if (heap->InNewSpace(heap_object)) return kInvalidRootIndex;
   for (int i = 0; i < root_index_wave_front_; i++) {
     Object* root = heap->roots_array_start()[i];
@@ -1484,8 +1483,7 @@
   // will contain some references needed to decode the partial snapshot.  We
   // add one entry with 'undefined' which is the sentinel that the deserializer
   // uses to know it is done deserializing the array.
-  Isolate* isolate = Isolate::Current();
-  Object* undefined = isolate->heap()->undefined_value();
+  Object* undefined = isolate()->heap()->undefined_value();
   VisitPointer(&undefined);
   HEAP->IterateWeakRoots(this, VISIT_ALL);
   Pad();
diff --git a/src/serialize.h b/src/serialize.h
index 563f0a0..0b07e1f 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -110,7 +110,7 @@
 
 class ExternalReferenceEncoder {
  public:
-  ExternalReferenceEncoder();
+  explicit ExternalReferenceEncoder(Isolate* isolate);
 
   uint32_t Encode(Address key) const;
 
@@ -134,7 +134,7 @@
 
 class ExternalReferenceDecoder {
  public:
-  ExternalReferenceDecoder();
+  explicit ExternalReferenceDecoder(Isolate* isolate);
   ~ExternalReferenceDecoder();
 
   Address Decode(uint32_t key) const {
@@ -208,7 +208,7 @@
 // both.
 class SerializerDeserializer: public ObjectVisitor {
  public:
-  static void Iterate(ObjectVisitor* visitor);
+  static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
 
   static int nop() { return kNop; }
 
@@ -325,10 +325,10 @@
   virtual ~Deserializer();
 
   // Deserialize the snapshot into an empty heap.
-  void Deserialize();
+  void Deserialize(Isolate* isolate);
 
   // Deserialize a single object and the objects reachable from it.
-  void DeserializePartial(Object** root);
+  void DeserializePartial(Isolate* isolate, Object** root);
 
   void set_reservation(int space_number, int reservation) {
     ASSERT(space_number >= 0);
@@ -464,7 +464,7 @@
 // There can be only one serializer per V8 process.
 class Serializer : public SerializerDeserializer {
  public:
-  explicit Serializer(SnapshotByteSink* sink);
+  Serializer(Isolate* isolate, SnapshotByteSink* sink);
   ~Serializer();
   void VisitPointers(Object** start, Object** end);
   // You can call this after serialization to find out how much space was used
@@ -474,7 +474,8 @@
     return fullness_[space];
   }
 
-  static void Enable();
+  Isolate* isolate() const { return isolate_; }
+  static void Enable(Isolate* isolate);
   static void Disable();
 
   // Call this when you have made use of the fact that there is no serialization
@@ -593,9 +594,10 @@
 
 class PartialSerializer : public Serializer {
  public:
-  PartialSerializer(Serializer* startup_snapshot_serializer,
+  PartialSerializer(Isolate* isolate,
+                    Serializer* startup_snapshot_serializer,
                     SnapshotByteSink* sink)
-    : Serializer(sink),
+    : Serializer(isolate, sink),
       startup_serializer_(startup_snapshot_serializer) {
     set_root_index_wave_front(Heap::kStrongRootListLength);
   }
@@ -629,12 +631,13 @@
 
 class StartupSerializer : public Serializer {
  public:
-  explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) {
+  StartupSerializer(Isolate* isolate, SnapshotByteSink* sink)
+    : Serializer(isolate, sink) {
     // Clear the cache of objects used by the partial snapshot.  After the
     // strong roots have been serialized we can create a partial snapshot
     // which will repopulate the cache with objects needed by that partial
     // snapshot.
-    Isolate::Current()->set_serialize_partial_snapshot_cache_length(0);
+    isolate->set_serialize_partial_snapshot_cache_length(0);
   }
   // Serialize the current state of the heap.  The order is:
   // 1) Strong references.
diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc
index 576269d..96034e3 100644
--- a/src/snapshot-common.cc
+++ b/src/snapshot-common.cc
@@ -116,7 +116,7 @@
 }
 
 
-Handle<Context> Snapshot::NewContextFromSnapshot() {
+Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
   if (context_size_ == 0) {
     return Handle<Context>();
   }
@@ -132,7 +132,7 @@
   deserializer.set_reservation(CELL_SPACE, context_cell_space_used_);
   deserializer.set_reservation(PROPERTY_CELL_SPACE,
                                context_property_cell_space_used_);
-  deserializer.DeserializePartial(&root);
+  deserializer.DeserializePartial(isolate, &root);
   CHECK(root->IsContext());
   return Handle<Context>(Context::cast(root));
 }
diff --git a/src/snapshot.h b/src/snapshot.h
index 149306e..4041f29 100644
--- a/src/snapshot.h
+++ b/src/snapshot.h
@@ -43,7 +43,7 @@
   static bool HaveASnapshotToStartFrom();
 
   // Create a new context using the internal partial snapshot.
-  static Handle<Context> NewContextFromSnapshot();
+  static Handle<Context> NewContextFromSnapshot(Isolate* isolate);
 
   // Returns whether or not the snapshot is enabled.
   static bool IsEnabled() { return size_ != 0; }
diff --git a/src/spaces.cc b/src/spaces.cc
index e62d381..d527c73 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -1777,8 +1777,7 @@
 
 #ifdef DEBUG
 // heap_histograms is shared, always clear it before using it.
-static void ClearHistograms() {
-  Isolate* isolate = Isolate::Current();
+static void ClearHistograms(Isolate* isolate) {
   // We reset the name each time, though it hasn't changed.
 #define DEF_TYPE_NAME(name) isolate->heap_histograms()[name].set_name(#name);
   INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
@@ -1829,8 +1828,7 @@
 }
 
 
-static void ReportHistogram(bool print_spill) {
-  Isolate* isolate = Isolate::Current();
+static void ReportHistogram(Isolate* isolate, bool print_spill) {
   PrintF("\n  Object Histogram:\n");
   for (int i = 0; i <= LAST_TYPE; i++) {
     if (isolate->heap_histograms()[i].number() > 0) {
@@ -2685,8 +2683,7 @@
 
 
 #ifdef DEBUG
-void PagedSpace::ReportCodeStatistics() {
-  Isolate* isolate = Isolate::Current();
+void PagedSpace::ReportCodeStatistics(Isolate* isolate) {
   CommentStatistic* comments_statistics =
       isolate->paged_space_comments_statistics();
   ReportCodeKindStatistics(isolate->code_kind_statistics());
@@ -2703,8 +2700,7 @@
 }
 
 
-void PagedSpace::ResetCodeStatistics() {
-  Isolate* isolate = Isolate::Current();
+void PagedSpace::ResetCodeStatistics(Isolate* isolate) {
   CommentStatistic* comments_statistics =
       isolate->paged_space_comments_statistics();
   ClearCodeKindStatistics(isolate->code_kind_statistics());
@@ -2819,11 +2815,11 @@
          Capacity(), Waste(), Available(), pct);
 
   if (was_swept_conservatively_) return;
-  ClearHistograms();
+  ClearHistograms(heap()->isolate());
   HeapObjectIterator obj_it(this);
   for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next())
     CollectHistogramInfo(obj);
-  ReportHistogram(true);
+  ReportHistogram(heap()->isolate(), true);
 }
 #endif
 
@@ -3160,7 +3156,7 @@
 void LargeObjectSpace::ReportStatistics() {
   PrintF("  size: %" V8_PTR_PREFIX "d\n", size_);
   int num_objects = 0;
-  ClearHistograms();
+  ClearHistograms(heap()->isolate());
   LargeObjectIterator it(this);
   for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
     num_objects++;
@@ -3169,7 +3165,7 @@
 
   PrintF("  number of objects %d, "
          "size of objects %" V8_PTR_PREFIX "d\n", num_objects, objects_size_);
-  if (num_objects > 0) ReportHistogram(false);
+  if (num_objects > 0) ReportHistogram(heap()->isolate(), false);
 }
 
 
diff --git a/src/spaces.h b/src/spaces.h
index 7f8ab5e..92c135d 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -1753,8 +1753,8 @@
 
   // Report code object related statistics
   void CollectCodeStatistics();
-  static void ReportCodeStatistics();
-  static void ResetCodeStatistics();
+  static void ReportCodeStatistics(Isolate* isolate);
+  static void ResetCodeStatistics(Isolate* isolate);
 #endif
 
   bool was_swept_conservatively() { return was_swept_conservatively_; }
diff --git a/src/string-stream.cc b/src/string-stream.cc
index 9c4394e..f34f53d 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -194,7 +194,8 @@
     return;
   }
   if (o->IsHeapObject()) {
-    DebugObjectCache* debug_object_cache = Isolate::Current()->
+    HeapObject* ho = HeapObject::cast(o);
+    DebugObjectCache* debug_object_cache = ho->GetIsolate()->
         string_stream_debug_object_cache();
     for (int i = 0; i < debug_object_cache->length(); i++) {
       if ((*debug_object_cache)[i] == o) {
@@ -289,14 +290,13 @@
 }
 
 
-Handle<String> StringStream::ToString() {
-  Factory* factory = Isolate::Current()->factory();
-  return factory->NewStringFromUtf8(Vector<const char>(buffer_, length_));
+Handle<String> StringStream::ToString(Isolate* isolate) {
+  return isolate->factory()->NewStringFromUtf8(
+      Vector<const char>(buffer_, length_));
 }
 
 
-void StringStream::ClearMentionedObjectCache() {
-  Isolate* isolate = Isolate::Current();
+void StringStream::ClearMentionedObjectCache(Isolate* isolate) {
   isolate->set_string_stream_current_security_token(NULL);
   if (isolate->string_stream_debug_object_cache() == NULL) {
     isolate->set_string_stream_debug_object_cache(
@@ -307,9 +307,8 @@
 
 
 #ifdef DEBUG
-bool StringStream::IsMentionedObjectCacheClear() {
-  return (
-      Isolate::Current()->string_stream_debug_object_cache()->length() == 0);
+bool StringStream::IsMentionedObjectCacheClear(Isolate* isolate) {
+  return isolate->string_stream_debug_object_cache()->length() == 0;
 }
 #endif
 
@@ -422,9 +421,9 @@
 }
 
 
-void StringStream::PrintMentionedObjectCache() {
+void StringStream::PrintMentionedObjectCache(Isolate* isolate) {
   DebugObjectCache* debug_object_cache =
-      Isolate::Current()->string_stream_debug_object_cache();
+      isolate->string_stream_debug_object_cache();
   Add("==== Key         ============================================\n\n");
   for (int i = 0; i < debug_object_cache->length(); i++) {
     HeapObject* printee = (*debug_object_cache)[i];
@@ -457,12 +456,12 @@
 
 
 void StringStream::PrintSecurityTokenIfChanged(Object* f) {
-  Isolate* isolate = Isolate::Current();
+  if (!f->IsHeapObject()) return;
+  HeapObject* obj = HeapObject::cast(f);
+  Isolate* isolate = obj->GetIsolate();
   Heap* heap = isolate->heap();
-  if (!f->IsHeapObject() || !heap->Contains(HeapObject::cast(f))) {
-    return;
-  }
-  Map* map = HeapObject::cast(f)->map();
+  if (!heap->Contains(obj)) return;
+  Map* map = obj->map();
   if (!map->IsHeapObject() ||
       !heap->Contains(map) ||
       !map->IsMap() ||
diff --git a/src/string-stream.h b/src/string-stream.h
index 2367994..255a2c3 100644
--- a/src/string-stream.h
+++ b/src/string-stream.h
@@ -148,7 +148,7 @@
   void OutputToFile(FILE* out);
   void OutputToStdOut() { OutputToFile(stdout); }
   void Log();
-  Handle<String> ToString();
+  Handle<String> ToString(Isolate* isolate);
   SmartArrayPointer<const char> ToCString() const;
   int length() const { return length_; }
 
@@ -169,10 +169,10 @@
   }
 
   // Mentioned object cache support.
-  void PrintMentionedObjectCache();
-  static void ClearMentionedObjectCache();
+  void PrintMentionedObjectCache(Isolate* isolate);
+  static void ClearMentionedObjectCache(Isolate* isolate);
 #ifdef DEBUG
-  static bool IsMentionedObjectCacheClear();
+  static bool IsMentionedObjectCacheClear(Isolate* isolate);
 #endif
 
 
diff --git a/src/transitions.cc b/src/transitions.cc
index 086edcb..9d3f038 100644
--- a/src/transitions.cc
+++ b/src/transitions.cc
@@ -35,20 +35,20 @@
 namespace internal {
 
 
-static MaybeObject* AllocateRaw(int length) {
-  Heap* heap = Isolate::Current()->heap();
-
+static MaybeObject* AllocateRaw(Isolate* isolate, int length) {
   // Use FixedArray to not use TransitionArray::cast on incomplete object.
   FixedArray* array;
-  MaybeObject* maybe_array = heap->AllocateFixedArray(length);
+  MaybeObject* maybe_array = isolate->heap()->AllocateFixedArray(length);
   if (!maybe_array->To(&array)) return maybe_array;
   return array;
 }
 
 
-MaybeObject* TransitionArray::Allocate(int number_of_transitions) {
+MaybeObject* TransitionArray::Allocate(Isolate* isolate,
+                                       int number_of_transitions) {
   FixedArray* array;
-  MaybeObject* maybe_array = AllocateRaw(ToKeyIndex(number_of_transitions));
+  MaybeObject* maybe_array =
+      AllocateRaw(isolate, ToKeyIndex(number_of_transitions));
   if (!maybe_array->To(&array)) return maybe_array;
   array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
   return array;
@@ -77,11 +77,11 @@
   MaybeObject* maybe_result;
 
   if (flag == SIMPLE_TRANSITION) {
-    maybe_result = AllocateRaw(kSimpleTransitionSize);
+    maybe_result = AllocateRaw(target->GetIsolate(), kSimpleTransitionSize);
     if (!maybe_result->To(&result)) return maybe_result;
     result->set(kSimpleTransitionTarget, target);
   } else {
-    maybe_result = Allocate(1);
+    maybe_result = Allocate(target->GetIsolate(), 1);
     if (!maybe_result->To(&result)) return maybe_result;
     result->NoIncrementalWriteBarrierSet(0, key, target);
   }
@@ -94,7 +94,7 @@
   ASSERT(!IsFullTransitionArray());
   int nof = number_of_transitions();
   TransitionArray* result;
-  MaybeObject* maybe_result = Allocate(nof);
+  MaybeObject* maybe_result = Allocate(GetIsolate(), nof);
   if (!maybe_result->To(&result)) return maybe_result;
 
   if (nof == 1) {
@@ -116,7 +116,7 @@
   if (insertion_index == kNotFound) ++new_size;
 
   MaybeObject* maybe_array;
-  maybe_array = TransitionArray::Allocate(new_size);
+  maybe_array = TransitionArray::Allocate(GetIsolate(), new_size);
   if (!maybe_array->To(&result)) return maybe_array;
 
   if (HasPrototypeTransitions()) {
diff --git a/src/transitions.h b/src/transitions.h
index fde1279..b2e9839 100644
--- a/src/transitions.h
+++ b/src/transitions.h
@@ -119,7 +119,8 @@
   inline int Search(Name* name);
 
   // Allocates a TransitionArray.
-  MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions);
+  MUST_USE_RESULT static MaybeObject* Allocate(
+      Isolate* isolate, int number_of_transitions);
 
   bool IsSimpleTransition() {
     return length() == kSimpleTransitionSize &&
diff --git a/src/v8.cc b/src/v8.cc
index f2aa837..e47ff12 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -174,16 +174,6 @@
 }
 
 
-bool V8::IdleNotification(int hint) {
-  // Returning true tells the caller that there is no need to call
-  // IdleNotification again.
-  if (!FLAG_use_idle_notification) return true;
-
-  // Tell the heap that it may want to adjust.
-  return HEAP->IdleNotification(hint);
-}
-
-
 void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
   if (call_completed_callbacks_ == NULL) {  // Lazy init.
     call_completed_callbacks_ = new List<CallCompletedCallback>();
diff --git a/src/v8.h b/src/v8.h
index 707482f..69f4df9 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -105,9 +105,6 @@
   static Object* FillHeapNumberWithRandom(Object* heap_number,
                                           Context* context);
 
-  // Idle notification directly from the API.
-  static bool IdleNotification(int hint);
-
   static void AddCallCompletedCallback(CallCompletedCallback callback);
   static void RemoveCallCompletedCallback(CallCompletedCallback callback);
   static void FireCallCompletedCallback(Isolate* isolate);
diff --git a/src/v8threads.cc b/src/v8threads.cc
index c1f20b1..33b620d 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -144,12 +144,13 @@
 
 
 void Locker::StartPreemption(int every_n_ms) {
-  v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
+  v8::internal::ContextSwitcher::StartPreemption(
+      i::Isolate::Current(), every_n_ms);
 }
 
 
 void Locker::StopPreemption() {
-  v8::internal::ContextSwitcher::StopPreemption();
+  v8::internal::ContextSwitcher::StopPreemption(i::Isolate::Current());
 }
 
 
@@ -437,8 +438,7 @@
 
 // Set the scheduling interval of V8 threads. This function starts the
 // ContextSwitcher thread if needed.
-void ContextSwitcher::StartPreemption(int every_n_ms) {
-  Isolate* isolate = Isolate::Current();
+void ContextSwitcher::StartPreemption(Isolate* isolate, int every_n_ms) {
   ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
   if (isolate->context_switcher() == NULL) {
     // If the ContextSwitcher thread is not running at the moment start it now.
@@ -454,8 +454,7 @@
 
 // Disable preemption of V8 threads. If multiple threads want to use V8 they
 // must cooperatively schedule amongst them from this point on.
-void ContextSwitcher::StopPreemption() {
-  Isolate* isolate = Isolate::Current();
+void ContextSwitcher::StopPreemption(Isolate* isolate) {
   ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
   if (isolate->context_switcher() != NULL) {
     // The ContextSwitcher thread is running. We need to stop it and release
diff --git a/src/v8threads.h b/src/v8threads.h
index b8ed817..1edacfc 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -146,10 +146,10 @@
 class ContextSwitcher: public Thread {
  public:
   // Set the preemption interval for the ContextSwitcher thread.
-  static void StartPreemption(int every_n_ms);
+  static void StartPreemption(Isolate* isolate, int every_n_ms);
 
   // Stop sending preemption requests to threads.
-  static void StopPreemption();
+  static void StopPreemption(Isolate* isolate);
 
   // Preempted thread needs to call back to the ContextSwitcher to acknowledge
   // the handling of a preemption request.
diff --git a/src/version.cc b/src/version.cc
index 5bc3a06..dbc114c 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     21
-#define BUILD_NUMBER      9
+#define BUILD_NUMBER      10
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index acf2dc1..9984a46 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -1320,6 +1320,8 @@
       return "addsd";
     case 0x59:  // F2 prefix.
       return "mulsd";
+    case 0x5A:  // F2 prefix.
+      return "cvtsd2ss";
     case 0x5C:  // F2 prefix.
       return "subsd";
     case 0x5E:  // F2 prefix.