Merge v8 from https://chromium.googlesource.com/external/v8.git at e97852de34e44a479f092bd2449134e707cd9cf1

This commit was generated by merge_from_chromium.py.

Change-Id: I8c33f857b5ad473e39bdd5ccdfc91a120d46742f
diff --git a/ChangeLog b/ChangeLog
index 79be335..27ff5d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-09-12: Version 3.21.14
+
+        Added access check for observed objects.
+        (V8 issue 2778)
+
+        Cleaned up v8::ArrayBuffer::Allocator interface.
+        (V8 issue 2823)
+
+        Performance and stability improvements on all platforms.
+
 2013-09-11: Version 3.21.13
 
         Added a ResourceConstraint for the embedder to specify that V8 is
diff --git a/include/v8.h b/include/v8.h
index 9e9ea8a..d98a768 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2516,27 +2516,12 @@
      * Allocate |length| bytes. Return NULL if allocation is not successful.
      * Memory does not have to be initialized.
      */
-    virtual void* AllocateUninitialized(size_t length) {
-      // Override with call to |Allocate| for compatibility
-      // with legacy version.
-      return Allocate(length);
-    }
-
+    virtual void* AllocateUninitialized(size_t length) = 0;
     /**
      * Free the memory block of size |length|, pointed to by |data|.
      * That memory is guaranteed to be previously allocated by |Allocate|.
      */
-    virtual void Free(void* data, size_t length) {
-      // Override with call to |Free(void*)| for compatibility
-      // with legacy version.
-      Free(data);
-    }
-
-    /**
-     * Deprecated. Never called directly by V8.
-     * For compatibility with legacy version of this interface.
-     */
-    virtual void Free(void* data);
+    virtual void Free(void* data, size_t length) = 0;
   };
 
   /**
@@ -5378,7 +5363,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 133;
+  static const int kEmptyStringRootIndex = 131;
 
   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
diff --git a/src/api.cc b/src/api.cc
index d1f6b78..f75a851 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2988,12 +2988,6 @@
 }
 
 
-void v8::ArrayBuffer::Allocator::Free(void* data) {
-  API_Fatal("v8::ArrayBuffer::Allocator::Free",
-            "Override Allocator::Free(void*, size_t)");
-}
-
-
 void v8::ArrayBufferView::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsJSArrayBufferView(),
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index bfe9bc8..a1d1e1b 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -279,7 +279,7 @@
 }
 
 
-void RelocInfo::Visit(ObjectVisitor* visitor) {
+void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
     visitor->VisitEmbeddedPointer(this);
@@ -292,12 +292,11 @@
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     visitor->VisitCodeAgeSequence(this);
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  // TODO(isolates): Get a cached isolate below.
   } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
               IsPatchedDebugBreakSlotSequence())) &&
-             Isolate::Current()->debug()->has_break_points()) {
+             isolate->debug()->has_break_points()) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (RelocInfo::IsRuntimeEntry(mode)) {
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index ae6db3a..ed8639c 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -324,15 +324,12 @@
 // See assembler-arm-inl.h for inlined constructors
 
 Operand::Operand(Handle<Object> handle) {
-#ifdef DEBUG
-  Isolate* isolate = Isolate::Current();
-#endif
   AllowDeferredHandleDereference using_raw_address;
   rm_ = no_reg;
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
-  ASSERT(!isolate->heap()->InNewSpace(obj));
   if (obj->IsHeapObject()) {
+    ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
     imm32_ = reinterpret_cast<intptr_t>(handle.location());
     rmode_ = RelocInfo::EMBEDDED_OBJECT;
   } else {
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 8862702..e0c37e1 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -966,13 +966,22 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
-  // Lookup the function in the JavaScript frame and push it as an
-  // argument to the on-stack replacement function.
+  // Lookup the function in the JavaScript frame.
   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
+    // Lookup and calculate pc offset.
+    __ ldr(r1, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
+    __ ldr(r2, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
+    __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset));
+    __ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
+    __ sub(r1, r1, r2);
+    __ SmiTag(r1);
+
+    // Pass both function and pc offset as arguments.
     __ push(r0);
-    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
+    __ push(r1);
+    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2);
   }
 
   // If the code object is null, just return to the unoptimized code.
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 87a76f0..3a1d128 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -622,7 +622,7 @@
 }
 
 
-bool WriteInt32ToHeapNumberStub::IsPregenerated() {
+bool WriteInt32ToHeapNumberStub::IsPregenerated(Isolate* isolate) {
   // These variants are compiled ahead of time.  See next method.
   if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) {
     return true;
@@ -2694,8 +2694,8 @@
 }
 
 
-bool CEntryStub::IsPregenerated() {
-  return (!save_doubles_ || Isolate::Current()->fp_stubs_generated()) &&
+bool CEntryStub::IsPregenerated(Isolate* isolate) {
+  return (!save_doubles_ || isolate->fp_stubs_generated()) &&
           result_size_ == 1;
 }
 
@@ -6424,8 +6424,6 @@
   // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
   // Also used in KeyedStoreIC::GenerateGeneric.
   { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET },
-  // Used in CompileStoreGlobal.
-  { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET },
   // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
   { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET },
   { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET },
@@ -6457,7 +6455,7 @@
 #undef REG
 
 
-bool RecordWriteStub::IsPregenerated() {
+bool RecordWriteStub::IsPregenerated(Isolate* isolate) {
   for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
        !entry->object.is(no_reg);
        entry++) {
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index e7e7bfc..d05e9a1 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -68,7 +68,7 @@
 
   void Generate(MacroAssembler* masm);
 
-  virtual bool IsPregenerated() { return true; }
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
@@ -232,7 +232,7 @@
         the_heap_number_(the_heap_number),
         scratch_(scratch) { }
 
-  bool IsPregenerated();
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
 
  private:
@@ -305,7 +305,7 @@
     INCREMENTAL_COMPACTION
   };
 
-  virtual bool IsPregenerated();
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index 108435f..efd1106 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -55,7 +55,8 @@
   CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
   patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
   patcher.masm()->blx(v8::internal::ip);
-  patcher.Emit(Isolate::Current()->debug()->debug_break_return()->entry());
+  patcher.Emit(
+      debug_info_->GetIsolate()->debug()->debug_break_return()->entry());
   patcher.masm()->bkpt(0);
 }
 
@@ -95,7 +96,8 @@
   CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
   patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
   patcher.masm()->blx(v8::internal::ip);
-  patcher.Emit(Isolate::Current()->debug()->debug_break_slot()->entry());
+  patcher.Emit(
+      debug_info_->GetIsolate()->debug()->debug_break_slot()->entry());
 }
 
 
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 511a3c7..f15d4b1 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -354,7 +354,7 @@
                                          extra_state,
                                          Code::NORMAL,
                                          argc);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, r1, r2, r3, r4, r5, r6);
 
   // If the stub cache probing failed, the receiver might be a value.
@@ -393,7 +393,7 @@
 
   // Probe the stub cache for the value object.
   __ bind(&probe);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, r1, r2, r3, r4, r5, r6);
 
   __ bind(&miss);
@@ -658,7 +658,7 @@
   Code::Flags flags = Code::ComputeFlags(
       Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, r0, r2, r3, r4, r5, r6);
 
   // Cache miss: Jump to runtime.
@@ -1490,7 +1490,7 @@
       Code::STUB, MONOMORPHIC, strict_mode,
       Code::NORMAL, Code::STORE_IC);
 
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, r1, r2, r3, r4, r5, r6);
 
   // Cache miss: Jump to runtime.
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 2a81fac..a26aa9e 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -872,7 +872,7 @@
   masm_->GetCode(&code_desc);
   Handle<Code> code = isolate()->factory()->NewCode(
       code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject());
-  PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
+  PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source));
   return Handle<HeapObject>::cast(code);
 }
 
@@ -1097,7 +1097,6 @@
                                                   Code* re_code,
                                                   Address re_frame) {
   Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
-  ASSERT(isolate == Isolate::Current());
   if (isolate->stack_guard()->IsStackOverflow()) {
     isolate->StackOverflow();
     return EXCEPTION;
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index c1c87d9..5bab086 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -2912,47 +2912,6 @@
 }
 
 
-Handle<Code> StoreStubCompiler::CompileStoreGlobal(
-    Handle<GlobalObject> object,
-    Handle<PropertyCell> cell,
-    Handle<Name> name) {
-  Label miss;
-
-  // Check that the map of the global has not changed.
-  __ ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
-  __ cmp(scratch1(), Operand(Handle<Map>(object->map())));
-  __ b(ne, &miss);
-
-  // Check that the value in the cell is not the hole. If it is, this
-  // cell could have been deleted and reintroducing the global needs
-  // to update the property details in the property dictionary of the
-  // global object. We bail out to the runtime system to do that.
-  __ mov(scratch1(), Operand(cell));
-  __ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
-  __ ldr(scratch3(), FieldMemOperand(scratch1(), Cell::kValueOffset));
-  __ cmp(scratch3(), scratch2());
-  __ b(eq, &miss);
-
-  // Store the value in the cell.
-  __ str(value(), FieldMemOperand(scratch1(), Cell::kValueOffset));
-  // Cells are always rescanned, so no write barrier here.
-
-  Counters* counters = isolate()->counters();
-  __ IncrementCounter(
-      counters->named_store_global_inline(), 1, scratch1(), scratch2());
-  __ Ret();
-
-  // Handle store cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(
-      counters->named_store_global_inline_miss(), 1, scratch1(), scratch2());
-  TailCallBuiltin(masm(), MissBuiltin(kind()));
-
-  // Return the generated code.
-  return GetICCode(kind(), Code::NORMAL, name);
-}
-
-
 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
     Handle<JSObject> object,
     Handle<JSObject> last,
diff --git a/src/assembler.h b/src/assembler.h
index 671f813..3ebaee3 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -425,7 +425,7 @@
   INLINE(Object** call_object_address());
 
   template<typename StaticVisitor> inline void Visit(Heap* heap);
-  inline void Visit(ObjectVisitor* v);
+  inline void Visit(Isolate* isolate, ObjectVisitor* v);
 
   // Patch the code with some other code.
   void PatchCode(byte* instructions, int instruction_count);
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 764c846..58b115d 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -98,7 +98,7 @@
 
 
 void Bootstrapper::Initialize(bool create_heap_objects) {
-  extensions_cache_.Initialize(create_heap_objects);
+  extensions_cache_.Initialize(isolate_, create_heap_objects);
 }
 
 
@@ -147,7 +147,7 @@
     delete_these_arrays_on_tear_down_ = NULL;
   }
 
-  extensions_cache_.Initialize(false);  // Yes, symmetrical
+  extensions_cache_.Initialize(isolate_, false);  // Yes, symmetrical
 }
 
 
diff --git a/src/bootstrapper.h b/src/bootstrapper.h
index e6456bd..bac9f40 100644
--- a/src/bootstrapper.h
+++ b/src/bootstrapper.h
@@ -44,9 +44,8 @@
  public:
   explicit SourceCodeCache(Script::Type type): type_(type), cache_(NULL) { }
 
-  void Initialize(bool create_heap_objects) {
-    cache_ = create_heap_objects ?
-        Isolate::Current()->heap()->empty_fixed_array() : NULL;
+  void Initialize(Isolate* isolate, bool create_heap_objects) {
+    cache_ = create_heap_objects ? isolate->heap()->empty_fixed_array() : NULL;
   }
 
   void Iterate(ObjectVisitor* v) {
diff --git a/src/checks.cc b/src/checks.cc
index 8208682..7108d18 100644
--- a/src/checks.cc
+++ b/src/checks.cc
@@ -31,33 +31,19 @@
 
 #include "platform.h"
 
-// TODO(isolates): is it necessary to lift this?
-static int fatal_error_handler_nesting_depth = 0;
-
 // Contains protection against recursive calls (faults while handling faults).
 extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
   i::AllowHandleDereference allow_deref;
   i::AllowDeferredHandleDereference allow_deferred_deref;
   fflush(stdout);
   fflush(stderr);
-  fatal_error_handler_nesting_depth++;
-  // First time we try to print an error message
-  if (fatal_error_handler_nesting_depth < 2) {
-    i::OS::PrintError("\n\n#\n# Fatal error in %s, line %d\n# ", file, line);
-    va_list arguments;
-    va_start(arguments, format);
-    i::OS::VPrintError(format, arguments);
-    va_end(arguments);
-    i::OS::PrintError("\n#\n");
-    i::OS::DumpBacktrace();
-  }
-  // First two times we may try to print a stack dump.
-  if (fatal_error_handler_nesting_depth < 3) {
-    if (i::FLAG_stack_trace_on_abort) {
-      // Call this one twice on double fault
-      i::Isolate::Current()->PrintStack(stderr);
-    }
-  }
+  i::OS::PrintError("\n\n#\n# Fatal error in %s, line %d\n# ", file, line);
+  va_list arguments;
+  va_start(arguments, format);
+  i::OS::VPrintError(format, arguments);
+  va_end(arguments);
+  i::OS::PrintError("\n#\n");
+  i::OS::DumpBacktrace();
   i::OS::Abort();
 }
 
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 5383339..ace4af4 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -136,7 +136,7 @@
   if (UseSpecialCache()
       ? FindCodeInSpecialCache(&code, isolate)
       : FindCodeInCache(&code, isolate)) {
-    ASSERT(IsPregenerated() == code->is_pregenerated());
+    ASSERT(IsPregenerated(isolate) == code->is_pregenerated());
     return Handle<Code>(code);
   }
 
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 207af47..81bbb52 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -158,14 +158,14 @@
   virtual ~CodeStub() {}
 
   bool CompilingCallsToThisStubIsGCSafe(Isolate* isolate) {
-    bool is_pregenerated = IsPregenerated();
+    bool is_pregenerated = IsPregenerated(isolate);
     Code* code = NULL;
     CHECK(!is_pregenerated || FindCodeInCache(&code, isolate));
     return is_pregenerated;
   }
 
   // See comment above, where Instanceof is defined.
-  virtual bool IsPregenerated() { return false; }
+  virtual bool IsPregenerated(Isolate* isolate) { return false; }
 
   static void GenerateStubsAheadOfTime(Isolate* isolate);
   static void GenerateFPStubs(Isolate* isolate);
@@ -682,7 +682,7 @@
 
   virtual Handle<Code> GenerateCode(Isolate* isolate);
 
-  virtual bool IsPregenerated() { return true; }
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
 
   static void GenerateAheadOfTime(Isolate* isolate);
 
@@ -1305,7 +1305,7 @@
   // time, so it's OK to call it from other stubs that can't cope with GC during
   // their code generation.  On machines that always have gp registers (x64) we
   // can generate both variants ahead of time.
-  virtual bool IsPregenerated();
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
   static void GenerateAheadOfTime(Isolate* isolate);
 
  private:
@@ -1317,6 +1317,7 @@
                     bool always_allocate_scope);
 
   // Number of pointers/values returned.
+  Isolate* isolate_;
   const int result_size_;
   SaveFPRegsMode save_doubles_;
 
@@ -1895,7 +1896,7 @@
     return ContextCheckModeBits::decode(bit_field_);
   }
 
-  virtual bool IsPregenerated() {
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE {
     // We only pre-generate stubs that verify correct context
     return context_mode() == CONTEXT_CHECK_REQUIRED;
   }
@@ -1996,7 +1997,7 @@
     kind_ = kind;
   }
 
-  virtual bool IsPregenerated() { return true; }
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
   static void GenerateStubsAheadOfTime(Isolate* isolate);
   static void InstallDescriptors(Isolate* isolate);
 
@@ -2260,7 +2261,7 @@
   explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
       : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
 
-  virtual bool IsPregenerated() { return true; }
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
 
   static void GenerateAheadOfTime(Isolate* isolate);
 
diff --git a/src/compiler.cc b/src/compiler.cc
index 0699602..50db8e0 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -1120,166 +1120,6 @@
 }
 
 
-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;
-}
-
-
-Handle<Code> Compiler::CompileForOnStackReplacement(
-      Handle<JSFunction> function) {
-  Isolate* isolate = function->GetIsolate();
-  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)) {
-    // Find the PC offset in unoptimized code and translate to an AST id.
-    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");
-    }
-
-    // Attempt OSR compilation.
-    Handle<Code> result = JSFunction::CompileOsr(
-        function, ast_id, CLEAR_EXCEPTION);
-
-    if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
-      // OSR compilation succeeded.
-      DeoptimizationInputData* data =
-          DeoptimizationInputData::cast(result->deoptimization_data());
-      if (FLAG_trace_osr) {
-        PrintF("[OSR - entry, offset %d in optimized code]\n",
-            data->OsrPcOffset()->value());
-      }
-      ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
-      return result;
-    }
-  }
-
-  if (FLAG_trace_osr) {
-    PrintF("[OSR - attempt failed for ");
-    function->PrintName();
-    PrintF("]\n");
-  }
-  return Handle<Code>::null();
-}
-
-
-Handle<Code> 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 Handle<Code>::null();
-  }
-
-  OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()->
-                                     FindReadyOSRCandidate(function, pc_offset);
-
-  if (compiler != NULL) {
-    BailoutId ast_id = compiler->info()->osr_ast_id();
-
-    if (FLAG_trace_osr) {
-      PrintF("[COSR - optimization complete for ");
-      function->PrintName();
-      PrintF(", restoring interrupt calls]\n");
-    }
-    Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
-
-    // TODO(titzer): don't install the OSR code into the function.
-    Handle<Code> result = InstallOptimizedCode(compiler);
-
-    isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates();
-
-    if (result.is_null()) {
-      if (FLAG_trace_osr) {
-        PrintF("[COSR - optimization failed for ");
-        function->PrintName();
-        PrintF("]\n");
-      }
-      return Handle<Code>::null();
-    }
-    // Check the result matches our expectations, and don't use it otherwise.
-    if (result->kind() == Code::OPTIMIZED_FUNCTION) {
-      DeoptimizationInputData* data =
-          DeoptimizationInputData::cast(result->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 result;
-      }
-    }
-    return Handle<Code>::null();
-  }
-
-  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 Handle<Code>::null();
-  }
-
-  if (!RecompileConcurrent(function, pc_offset)) {
-    Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
-  }
-  return Handle<Code>::null();
-}
-
-
 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
                                                        Handle<Script> script) {
   // Precondition: code has been parsed and scopes have been analyzed.
diff --git a/src/compiler.h b/src/compiler.h
index 15c4969..8ceb61d 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -627,10 +627,6 @@
 
   static Handle<Code> InstallOptimizedCode(OptimizingCompiler* info);
 
-  static Handle<Code> CompileForOnStackReplacement(Handle<JSFunction> function);
-
-  static Handle<Code> CompileForConcurrentOSR(Handle<JSFunction> function);
-
 #ifdef ENABLE_DEBUGGER_SUPPORT
   static bool MakeCodeForLiveEdit(CompilationInfo* info);
 #endif
diff --git a/src/handles-inl.h b/src/handles-inl.h
index 4f4490b..5b879d8 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -32,6 +32,7 @@
 #include "api.h"
 #include "apiutils.h"
 #include "handles.h"
+#include "heap.h"
 #include "isolate.h"
 
 namespace v8 {
@@ -85,11 +86,13 @@
   Object* object = *BitCast<T**>(location_);
   if (object->IsSmi()) return true;
   HeapObject* heap_object = HeapObject::cast(object);
-  Isolate* isolate = heap_object->GetIsolate();
+  Heap* heap = heap_object->GetHeap();
   Object** handle = reinterpret_cast<Object**>(location_);
-  Object** roots_array_start = isolate->heap()->roots_array_start();
+  Object** roots_array_start = heap->roots_array_start();
   if (roots_array_start <= handle &&
-      handle < roots_array_start + Heap::kStrongRootListLength) {
+      handle < roots_array_start + Heap::kStrongRootListLength &&
+      heap->RootCanBeTreatedAsConstant(
+        static_cast<Heap::RootListIndex>(handle - roots_array_start))) {
     return true;
   }
   if (!AllowHandleDereference::IsAllowed()) return false;
@@ -98,7 +101,7 @@
     // Accessing maps and internalized strings is safe.
     if (heap_object->IsMap()) return true;
     if (heap_object->IsInternalizedString()) return true;
-    return !isolate->IsDeferredHandle(handle);
+    return !heap->isolate()->IsDeferredHandle(handle);
   }
   return true;
 }
diff --git a/src/heap.h b/src/heap.h
index 94fbf46..4dfa076 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -199,7 +199,6 @@
   V(Array_string, "Array")                                               \
   V(Object_string, "Object")                                             \
   V(proto_string, "__proto__")                                           \
-  V(StringImpl_string, "StringImpl")                                     \
   V(arguments_string, "arguments")                                       \
   V(Arguments_string, "Arguments")                                       \
   V(call_string, "call")                                                 \
@@ -209,12 +208,10 @@
   V(Boolean_string, "Boolean")                                           \
   V(callee_string, "callee")                                             \
   V(constructor_string, "constructor")                                   \
-  V(code_string, ".code")                                                \
   V(result_string, ".result")                                            \
   V(dot_for_string, ".for.")                                             \
-  V(catch_var_string, ".catch-var")                                      \
-  V(empty_string, "")                                                    \
   V(eval_string, "eval")                                                 \
+  V(empty_string, "")                                                    \
   V(function_string, "function")                                         \
   V(length_string, "length")                                             \
   V(module_string, "module")                                             \
@@ -233,12 +230,10 @@
   V(index_string, "index")                                               \
   V(last_index_string, "lastIndex")                                      \
   V(object_string, "object")                                             \
-  V(payload_string, "payload")                                           \
   V(literals_string, "literals")                                         \
   V(prototype_string, "prototype")                                       \
   V(string_string, "string")                                             \
   V(String_string, "String")                                             \
-  V(unknown_field_string, "unknownField")                                \
   V(symbol_string, "symbol")                                             \
   V(Symbol_string, "Symbol")                                             \
   V(Date_string, "Date")                                                 \
@@ -257,7 +252,6 @@
     "KeyedStoreElementMonomorphic")                                      \
   V(stack_overflow_string, "kStackOverflowBoilerplate")                  \
   V(illegal_access_string, "illegal access")                             \
-  V(out_of_memory_string, "out-of-memory")                               \
   V(illegal_execution_state_string, "illegal execution state")           \
   V(get_string, "get")                                                   \
   V(set_string, "set")                                                   \
@@ -266,8 +260,6 @@
   V(length_field_string, "%length")                                      \
   V(cell_value_string, "%cell_value")                                    \
   V(function_class_string, "Function")                                   \
-  V(properties_field_symbol, "%properties")                              \
-  V(payload_field_symbol, "%payload")                                    \
   V(illegal_argument_string, "illegal argument")                         \
   V(MakeReferenceError_string, "MakeReferenceError")                     \
   V(MakeSyntaxError_string, "MakeSyntaxError")                           \
@@ -281,7 +273,6 @@
   V(illegal_continue_string, "illegal_continue")                         \
   V(unknown_label_string, "unknown_label")                               \
   V(redeclaration_string, "redeclaration")                               \
-  V(failure_string, "<failure>")                                         \
   V(space_string, " ")                                                   \
   V(exec_string, "exec")                                                 \
   V(zero_string, "0")                                                    \
diff --git a/src/hydrogen-alias-analysis.h b/src/hydrogen-alias-analysis.h
new file mode 100644
index 0000000..73e116e
--- /dev/null
+++ b/src/hydrogen-alias-analysis.h
@@ -0,0 +1,105 @@
+// 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_HYDROGEN_ALIAS_ANALYSIS_H_
+#define V8_HYDROGEN_ALIAS_ANALYSIS_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+enum HAliasing {
+  kMustAlias,
+  kMayAlias,
+  kNoAlias
+};
+
+
+// Defines the interface to alias analysis for the rest of the compiler.
+// A simple implementation can use only local reasoning, but a more powerful
+// analysis might employ points-to analysis.
+class HAliasAnalyzer : public ZoneObject {
+ public:
+  // Simple alias analysis distinguishes allocations, parameters,
+  // and constants using only local reasoning.
+  HAliasing Query(HValue* a, HValue* b) {
+    // The same SSA value always references the same object.
+    if (a == b) return kMustAlias;
+
+    if (a->IsAllocate() || a->IsInnerAllocatedObject()) {
+      // Two non-identical allocations can never be aliases.
+      if (b->IsAllocate()) return kNoAlias;
+      if (b->IsInnerAllocatedObject()) return kNoAlias;
+      // An allocation can never alias a parameter or a constant.
+      if (b->IsParameter()) return kNoAlias;
+      if (b->IsConstant()) return kNoAlias;
+    }
+    if (b->IsAllocate() || b->IsInnerAllocatedObject()) {
+      // An allocation can never alias a parameter or a constant.
+      if (a->IsParameter()) return kNoAlias;
+      if (a->IsConstant()) return kNoAlias;
+    }
+
+    // Constant objects can be distinguished statically.
+    if (a->IsConstant()) {
+      // TODO(titzer): DataEquals() is more efficient, but that's protected.
+      return a->Equals(b) ? kMustAlias : kNoAlias;
+    }
+    return kMayAlias;
+  }
+
+  // Checks whether the objects referred to by the given instructions may
+  // ever be aliases. Note that this is more conservative than checking
+  // {Query(a, b) == kMayAlias}, since this method considers kMustAlias
+  // objects to also be may-aliasing.
+  inline bool MayAlias(HValue* a, HValue* b) {
+    return Query(a, b) != kNoAlias;
+  }
+
+  inline bool MustAlias(HValue* a, HValue* b) {
+    return Query(a, b) == kMustAlias;
+  }
+
+  inline bool NoAlias(HValue* a, HValue* b) {
+    return Query(a, b) == kNoAlias;
+  }
+
+  // Returns the actual value of an instruction. In the case of a chain
+  // of informative definitions, return the root of the chain.
+  HValue* ActualValue(HValue* obj) {
+    while (obj->IsInformativeDefinition()) {  // Walk a chain of idefs.
+      obj = obj->RedefinedOperand();
+    }
+    return obj;
+  }
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_ALIAS_ANALYSIS_H_
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 4c2e308..cca95b9 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -3455,7 +3455,7 @@
       zone,
       context(),
       isolate()->factory()->free_space_map(),
-      UniqueValueId(isolate()->heap()->free_space_map()));
+      UniqueValueId::free_space_map(isolate()->heap()));
   filler_map->InsertAfter(free_space_instr);
   HInstruction* store_map = HStoreNamedField::New(zone, context(),
       free_space_instr, HObjectAccess::ForMap(), filler_map);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index aa2cdae..7d33141 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -309,12 +309,8 @@
  public:
   UniqueValueId() : raw_address_(NULL) { }
 
-  explicit UniqueValueId(Object* object) {
-    raw_address_ = reinterpret_cast<Address>(object);
-    ASSERT(IsInitialized());
-  }
-
   explicit UniqueValueId(Handle<Object> handle) {
+    ASSERT(!AllowHeapAllocation::IsAllowed());
     static const Address kEmptyHandleSentinel = reinterpret_cast<Address>(1);
     if (handle.is_null()) {
       raw_address_ = kEmptyHandleSentinel;
@@ -342,8 +338,28 @@
     return reinterpret_cast<intptr_t>(raw_address_);
   }
 
+#define IMMOVABLE_UNIQUE_VALUE_ID(name)   \
+  static UniqueValueId name(Heap* heap) { return UniqueValueId(heap->name()); }
+
+  IMMOVABLE_UNIQUE_VALUE_ID(free_space_map)
+  IMMOVABLE_UNIQUE_VALUE_ID(minus_zero_value)
+  IMMOVABLE_UNIQUE_VALUE_ID(nan_value)
+  IMMOVABLE_UNIQUE_VALUE_ID(undefined_value)
+  IMMOVABLE_UNIQUE_VALUE_ID(null_value)
+  IMMOVABLE_UNIQUE_VALUE_ID(true_value)
+  IMMOVABLE_UNIQUE_VALUE_ID(false_value)
+  IMMOVABLE_UNIQUE_VALUE_ID(the_hole_value)
+  IMMOVABLE_UNIQUE_VALUE_ID(empty_string)
+
+#undef IMMOVABLE_UNIQUE_VALUE_ID
+
  private:
   Address raw_address_;
+
+  explicit UniqueValueId(Object* object) {
+    raw_address_ = reinterpret_cast<Address>(object);
+    ASSERT(IsInitialized());
+  }
 };
 
 
@@ -3327,14 +3343,14 @@
 
     ASSERT(!handle_.is_null());
     Heap* heap = isolate()->heap();
-    ASSERT(unique_id_ != UniqueValueId(heap->minus_zero_value()));
-    ASSERT(unique_id_ != UniqueValueId(heap->nan_value()));
-    return unique_id_ == UniqueValueId(heap->undefined_value()) ||
-           unique_id_ == UniqueValueId(heap->null_value()) ||
-           unique_id_ == UniqueValueId(heap->true_value()) ||
-           unique_id_ == UniqueValueId(heap->false_value()) ||
-           unique_id_ == UniqueValueId(heap->the_hole_value()) ||
-           unique_id_ == UniqueValueId(heap->empty_string());
+    ASSERT(unique_id_ != UniqueValueId::minus_zero_value(heap));
+    ASSERT(unique_id_ != UniqueValueId::nan_value(heap));
+    return unique_id_ == UniqueValueId::undefined_value(heap) ||
+           unique_id_ == UniqueValueId::null_value(heap) ||
+           unique_id_ == UniqueValueId::true_value(heap) ||
+           unique_id_ == UniqueValueId::false_value(heap) ||
+           unique_id_ == UniqueValueId::the_hole_value(heap) ||
+           unique_id_ == UniqueValueId::empty_string(heap);
   }
 
   bool IsCell() const {
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 437d29b..7b623b5 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -649,7 +649,7 @@
   if (!constant_##name##_.is_set()) {                                          \
     HConstant* constant = new(zone()) HConstant(                               \
         isolate()->factory()->name##_value(),                                  \
-        UniqueValueId(isolate()->heap()->name##_value()),                      \
+        UniqueValueId::name##_value(isolate()->heap()),                        \
         Representation::Tagged(),                                              \
         htype,                                                                 \
         false,                                                                 \
@@ -1824,7 +1824,8 @@
 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object,
                                                     int previous_object_size,
                                                     HValue* alloc_site) {
-  ASSERT(alloc_site != NULL);
+  // TODO(mvstanton): ASSERT altered to CHECK to diagnose chromium bug 284577
+  CHECK(alloc_site != NULL);
   HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>(
       previous_object, previous_object_size);
   Handle<Map> alloc_memento_map(
diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
index b6ef242..5a35b20 100644
--- a/src/ia32/assembler-ia32-inl.h
+++ b/src/ia32/assembler-ia32-inl.h
@@ -251,7 +251,7 @@
 }
 
 
-void RelocInfo::Visit(ObjectVisitor* visitor) {
+void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
     visitor->VisitEmbeddedPointer(this);
@@ -266,12 +266,11 @@
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     visitor->VisitCodeAgeSequence(this);
   #ifdef ENABLE_DEBUGGER_SUPPORT
-  // TODO(isolates): Get a cached isolate below.
   } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
               IsPatchedDebugBreakSlotSequence())) &&
-             Isolate::Current()->debug()->has_break_points()) {
+             isolate->debug()->has_break_points()) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (IsRuntimeEntry(mode)) {
@@ -329,14 +328,11 @@
 
 
 Immediate::Immediate(Handle<Object> handle) {
-#ifdef DEBUG
-  Isolate* isolate = Isolate::Current();
-#endif
   AllowDeferredHandleDereference using_raw_address;
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
-  ASSERT(!isolate->heap()->InNewSpace(obj));
   if (obj->IsHeapObject()) {
+    ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
     x_ = reinterpret_cast<intptr_t>(handle.location());
     rmode_ = RelocInfo::EMBEDDED_OBJECT;
   } else {
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index a617da7..5f5d397 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -1327,14 +1327,21 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
+  // Lookup the function in the JavaScript frame.
   __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-
-  // Pass the function to optimize as the argument to the on-stack
-  // replacement runtime function.
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
+    // Lookup and calculate pc offset.
+    __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerPCOffset));
+    __ mov(ebx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
+    __ sub(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
+    __ sub(edx, FieldOperand(ebx, SharedFunctionInfo::kCodeOffset));
+    __ SmiTag(edx);
+
+    // Pass both function and pc offset as arguments.
     __ push(eax);
-    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
+    __ push(edx);
+    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2);
   }
 
   Label skip;
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 7133f3b..ee9e535 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -4430,8 +4430,8 @@
 }
 
 
-bool CEntryStub::IsPregenerated() {
-  return (!save_doubles_ || Isolate::Current()->fp_stubs_generated()) &&
+bool CEntryStub::IsPregenerated(Isolate* isolate) {
+  return (!save_doubles_ || isolate->fp_stubs_generated()) &&
           result_size_ == 1;
 }
 
@@ -6812,8 +6812,6 @@
   // Used in CompileArrayPushCall.
   { REG(ebx), REG(ecx), REG(edx), EMIT_REMEMBERED_SET },
   { REG(ebx), REG(edi), REG(edx), OMIT_REMEMBERED_SET },
-  // Used in CompileStoreGlobal and CallFunctionStub.
-  { REG(ebx), REG(ecx), REG(edx), OMIT_REMEMBERED_SET },
   // Used in StoreStubCompiler::CompileStoreField and
   // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
   { REG(edx), REG(ecx), REG(ebx), EMIT_REMEMBERED_SET },
@@ -6847,7 +6845,7 @@
 
 #undef REG
 
-bool RecordWriteStub::IsPregenerated() {
+bool RecordWriteStub::IsPregenerated(Isolate* isolate) {
   for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
        !entry->object.is(no_reg);
        entry++) {
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index e80acc6..5c8eca3 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -74,7 +74,7 @@
 
   void Generate(MacroAssembler* masm);
 
-  virtual bool IsPregenerated() { return true; }
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
@@ -327,7 +327,7 @@
     INCREMENTAL_COMPACTION
   };
 
-  virtual bool IsPregenerated();
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index fd703dc..76a7003 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -49,8 +49,8 @@
 void BreakLocationIterator::SetDebugBreakAtReturn() {
   ASSERT(Assembler::kJSReturnSequenceLength >=
          Assembler::kCallInstructionLength);
-  Isolate* isolate = Isolate::Current();
-  rinfo()->PatchCodeWithCall(isolate->debug()->debug_break_return()->entry(),
+  rinfo()->PatchCodeWithCall(
+      debug_info_->GetIsolate()->debug()->debug_break_return()->entry(),
       Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
 }
 
@@ -79,7 +79,7 @@
 
 void BreakLocationIterator::SetDebugBreakAtSlot() {
   ASSERT(IsDebugBreakSlot());
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = debug_info_->GetIsolate();
   rinfo()->PatchCodeWithCall(
       isolate->debug()->debug_break_slot()->entry(),
       Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index a1d4e9d..01fa999 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -698,6 +698,7 @@
   switch (escape_opcode) {
     case 0xD9: switch (regop) {
         case 0: mnem = "fld_s"; break;
+        case 2: mnem = "fst_s"; break;
         case 3: mnem = "fstp_s"; break;
         case 7: mnem = "fstcw"; break;
         default: UnimplementedInstruction();
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 1e0f14e..327ac57 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -1306,7 +1306,7 @@
   Code::Flags flags = Code::ComputeFlags(
       Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, edx, ecx, ebx, eax);
 
   // Cache miss: Jump to runtime.
@@ -1425,8 +1425,8 @@
   Code::Flags flags = Code::ComputeFlags(
       Code::STUB, MONOMORPHIC, strict_mode,
       Code::NORMAL, Code::STORE_IC);
-  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
-                                                  no_reg);
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, flags, edx, ecx, ebx, no_reg);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index 7d9e2f7..d371c45 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -1099,7 +1099,6 @@
                                                    Code* re_code,
                                                    Address re_frame) {
   Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
-  ASSERT(isolate == Isolate::Current());
   if (isolate->stack_guard()->IsStackOverflow()) {
     isolate->StackOverflow();
     return EXCEPTION;
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index bcf64ce..d2da43e 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -3004,48 +3004,6 @@
 }
 
 
-Handle<Code> StoreStubCompiler::CompileStoreGlobal(
-    Handle<GlobalObject> object,
-    Handle<PropertyCell> cell,
-    Handle<Name> name) {
-  Label miss;
-
-  // Check that the map of the global has not changed.
-  __ cmp(FieldOperand(receiver(), HeapObject::kMapOffset),
-         Immediate(Handle<Map>(object->map())));
-  __ j(not_equal, &miss);
-
-  // Compute the cell operand to use.
-  __ mov(scratch1(), Immediate(cell));
-  Operand cell_operand =
-      FieldOperand(scratch1(), PropertyCell::kValueOffset);
-
-  // Check that the value in the cell is not the hole. If it is, this
-  // cell could have been deleted and reintroducing the global needs
-  // to update the property details in the property dictionary of the
-  // global object. We bail out to the runtime system to do that.
-  __ cmp(cell_operand, factory()->the_hole_value());
-  __ j(equal, &miss);
-
-  // Store the value in the cell.
-  __ mov(cell_operand, value());
-  // No write barrier here, because cells are always rescanned.
-
-  // Return the value (register eax).
-  Counters* counters = isolate()->counters();
-  __ IncrementCounter(counters->named_store_global_inline(), 1);
-  __ ret(0);
-
-  // Handle store cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
-  TailCallBuiltin(masm(), MissBuiltin(kind()));
-
-  // Return the generated code.
-  return GetICCode(kind(), Code::NORMAL, name);
-}
-
-
 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
     MapHandleList* receiver_maps,
     CodeHandleList* handler_stubs,
diff --git a/src/isolate.cc b/src/isolate.cc
index 8e58135..6fa496a 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -866,7 +866,7 @@
     PrintStack(&accumulator);
     accumulator.OutputToFile(out);
     InitializeLoggingAndCounters();
-    accumulator.Log();
+    accumulator.Log(this);
     incomplete_message_ = NULL;
     stack_trace_nesting_level_ = 0;
     if (preallocated_message_space_ == NULL) {
diff --git a/src/isolate.h b/src/isolate.h
index 99283c9..b826ec5 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1426,12 +1426,15 @@
 class AssertNoContextChange BASE_EMBEDDED {
 #ifdef DEBUG
  public:
-  AssertNoContextChange() : context_(Isolate::Current()->context()) { }
+  AssertNoContextChange()
+    : isolate_(Isolate::Current()),
+      context_(isolate_->context()) { }
   ~AssertNoContextChange() {
-    ASSERT(Isolate::Current()->context() == *context_);
+    ASSERT(isolate_->context() == *context_);
   }
 
  private:
+  Isolate* isolate_;
   Handle<Context> context_;
 #else
  public:
@@ -1445,15 +1448,17 @@
 #ifdef DEBUG
  public:
   AssertNoContextChangeWithHandleScope() :
-      scope_(Isolate::Current()),
-      context_(Isolate::Current()->context(), Isolate::Current()) {
+      isolate_(Isolate::Current()),
+      scope_(isolate_),
+      context_(isolate_->context(), isolate_) {
   }
 
   ~AssertNoContextChangeWithHandleScope() {
-    ASSERT(Isolate::Current()->context() == *context_);
+    ASSERT(isolate_->context() == *context_);
   }
 
  private:
+  Isolate* isolate_;
   HandleScope scope_;
   Handle<Context> context_;
 #else
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index f1cb96d..3a3d915 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -1085,8 +1085,8 @@
 };
 
 
-static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
-  return RegExpEngine::CompilationResult("RegExp too big");
+static RegExpEngine::CompilationResult IrregexpRegExpTooBig(Isolate* isolate) {
+  return RegExpEngine::CompilationResult(isolate, "RegExp too big");
 }
 
 
@@ -1143,7 +1143,7 @@
   while (!work_list.is_empty()) {
     work_list.RemoveLast()->Emit(this, &new_trace);
   }
-  if (reg_exp_too_big_) return IrregexpRegExpTooBig();
+  if (reg_exp_too_big_) return IrregexpRegExpTooBig(zone_->isolate());
 
   Handle<HeapObject> code = macro_assembler_->GetCode(pattern);
   heap->IncreaseTotalRegexpCodeGenerated(code->Size());
@@ -5999,7 +5999,7 @@
     bool is_ascii,
     Zone* zone) {
   if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
-    return IrregexpRegExpTooBig();
+    return IrregexpRegExpTooBig(zone->isolate());
   }
   RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii, zone);
 
@@ -6063,7 +6063,7 @@
   analysis.EnsureAnalyzed(node);
   if (analysis.has_failed()) {
     const char* error_message = analysis.error_message();
-    return CompilationResult(error_message);
+    return CompilationResult(zone->isolate(), error_message);
   }
 
   // Create the correct assembler for the architecture.
diff --git a/src/jsregexp.h b/src/jsregexp.h
index 01ceaf4..dfd415d 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -1615,9 +1615,9 @@
 class RegExpEngine: public AllStatic {
  public:
   struct CompilationResult {
-    explicit CompilationResult(const char* error_message)
+    CompilationResult(Isolate* isolate, const char* error_message)
         : error_message(error_message),
-          code(Isolate::Current()->heap()->the_hole_value()),
+          code(isolate->heap()->the_hole_value()),
           num_registers(0) {}
     CompilationResult(Object* code, int registers)
       : error_message(NULL),
diff --git a/src/log.cc b/src/log.cc
index 7d1861e..0f0ad40 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -656,7 +656,7 @@
   if (engaged_) return;
   engaged_ = true;
 
-  OS::LogSharedLibraryAddresses();
+  OS::LogSharedLibraryAddresses(isolate_);
 
   // Start thread processing the profiler buffer.
   running_ = true;
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 17ac4a8..263de48 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -1788,8 +1788,6 @@
 
 
 void MarkCompactCollector::PrepareForCodeFlushing() {
-  ASSERT(heap() == Isolate::Current()->heap());
-
   // Enable code flushing for non-incremental cycles.
   if (FLAG_flush_code && !FLAG_flush_code_incrementally) {
     EnableCodeFlushing(!was_marked_incrementally_);
@@ -3051,13 +3049,14 @@
 };
 
 
-static inline void UpdateSlot(ObjectVisitor* v,
+static inline void UpdateSlot(Isolate* isolate,
+                              ObjectVisitor* v,
                               SlotsBuffer::SlotType slot_type,
                               Address addr) {
   switch (slot_type) {
     case SlotsBuffer::CODE_TARGET_SLOT: {
       RelocInfo rinfo(addr, RelocInfo::CODE_TARGET, 0, NULL);
-      rinfo.Visit(v);
+      rinfo.Visit(isolate, v);
       break;
     }
     case SlotsBuffer::CODE_ENTRY_SLOT: {
@@ -3071,17 +3070,17 @@
     }
     case SlotsBuffer::DEBUG_TARGET_SLOT: {
       RelocInfo rinfo(addr, RelocInfo::DEBUG_BREAK_SLOT, 0, NULL);
-      if (rinfo.IsPatchedDebugBreakSlotSequence()) rinfo.Visit(v);
+      if (rinfo.IsPatchedDebugBreakSlotSequence()) rinfo.Visit(isolate, v);
       break;
     }
     case SlotsBuffer::JS_RETURN_SLOT: {
       RelocInfo rinfo(addr, RelocInfo::JS_RETURN, 0, NULL);
-      if (rinfo.IsPatchedReturnSequence()) rinfo.Visit(v);
+      if (rinfo.IsPatchedReturnSequence()) rinfo.Visit(isolate, v);
       break;
     }
     case SlotsBuffer::EMBEDDED_OBJECT_SLOT: {
       RelocInfo rinfo(addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL);
-      rinfo.Visit(v);
+      rinfo.Visit(isolate, v);
       break;
     }
     default:
@@ -4268,7 +4267,8 @@
     } else {
       ++slot_idx;
       ASSERT(slot_idx < idx_);
-      UpdateSlot(&v,
+      UpdateSlot(heap->isolate(),
+                 &v,
                  DecodeSlotType(slot),
                  reinterpret_cast<Address>(slots_[slot_idx]));
     }
@@ -4290,7 +4290,8 @@
       ASSERT(slot_idx < idx_);
       Address pc = reinterpret_cast<Address>(slots_[slot_idx]);
       if (!IsOnInvalidatedCodeObject(pc)) {
-        UpdateSlot(&v,
+        UpdateSlot(heap->isolate(),
+                   &v,
                    DecodeSlotType(slot),
                    reinterpret_cast<Address>(slots_[slot_idx]));
       }
diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h
index 2ca0083..2fa6804 100644
--- a/src/mips/assembler-mips-inl.h
+++ b/src/mips/assembler-mips-inl.h
@@ -338,7 +338,7 @@
 }
 
 
-void RelocInfo::Visit(ObjectVisitor* visitor) {
+void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
     visitor->VisitEmbeddedPointer(this);
@@ -351,12 +351,11 @@
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     visitor->VisitCodeAgeSequence(this);
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  // TODO(isolates): Get a cached isolate below.
   } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
              IsPatchedDebugBreakSlotSequence())) &&
-             Isolate::Current()->debug()->has_break_points()) {
+             isolate->debug()->has_break_points()) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (RelocInfo::IsRuntimeEntry(mode)) {
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index 0bb00b4..345b642 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -238,15 +238,12 @@
 // See assembler-mips-inl.h for inlined constructors.
 
 Operand::Operand(Handle<Object> handle) {
-#ifdef DEBUG
-  Isolate* isolate = Isolate::Current();
-#endif
   AllowDeferredHandleDereference using_raw_address;
   rm_ = no_reg;
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
-  ASSERT(!isolate->heap()->InNewSpace(obj));
   if (obj->IsHeapObject()) {
+    ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
     imm32_ = reinterpret_cast<intptr_t>(handle.location());
     rmode_ = RelocInfo::EMBEDDED_OBJECT;
   } else {
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 1a5b302..f27ded7 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -1000,13 +1000,22 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
-  // Lookup the function in the JavaScript frame and push it as an
-  // argument to the on-stack replacement function.
+  // Lookup the function in the JavaScript frame.
   __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
+    // Lookup and calculate pc offset.
+    __ lw(a1, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
+    __ lw(a2, FieldMemOperand(a0, JSFunction::kSharedFunctionInfoOffset));
+    __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
+    __ Subu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
+    __ Subu(a1, a1, a2);
+    __ SmiTag(a1);
+
+    // Pass both function and pc offset as arguments.
     __ push(a0);
-    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
+    __ push(a1);
+    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2);
   }
 
   // If the code object is null, just return to the unoptimized code.
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 752a24c..b536209 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -649,7 +649,7 @@
 }
 
 
-bool WriteInt32ToHeapNumberStub::IsPregenerated() {
+bool WriteInt32ToHeapNumberStub::IsPregenerated(Isolate* isolate) {
   // These variants are compiled ahead of time.  See next method.
   if (the_int_.is(a1) &&
       the_heap_number_.is(v0) &&
@@ -2723,8 +2723,8 @@
 }
 
 
-bool CEntryStub::IsPregenerated() {
-  return (!save_doubles_ || Isolate::Current()->fp_stubs_generated()) &&
+bool CEntryStub::IsPregenerated(Isolate* isolate) {
+  return (!save_doubles_ || isolate->fp_stubs_generated()) &&
           result_size_ == 1;
 }
 
@@ -6554,8 +6554,6 @@
   // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
   // Also used in KeyedStoreIC::GenerateGeneric.
   { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET },
-  // Used in CompileStoreGlobal.
-  { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET },
   // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
   { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET },
   { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET },
@@ -6587,7 +6585,7 @@
 #undef REG
 
 
-bool RecordWriteStub::IsPregenerated() {
+bool RecordWriteStub::IsPregenerated(Isolate* isolate) {
   for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
        !entry->object.is(no_reg);
        entry++) {
@@ -6963,6 +6961,9 @@
 #else
   // Under the simulator we need to indirect the entry hook through a
   // trampoline function at a known address.
+  // It additionally takes an isolate as a third parameter.
+  __ li(a2, Operand(ExternalReference::isolate_address(masm->isolate())));
+
   ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
   __ li(at, Operand(ExternalReference(&dispatcher,
                                       ExternalReference::BUILTIN_CALL,
diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h
index 1800178..8c9d22a 100644
--- a/src/mips/code-stubs-mips.h
+++ b/src/mips/code-stubs-mips.h
@@ -69,7 +69,7 @@
 
   void Generate(MacroAssembler* masm);
 
-  virtual bool IsPregenerated() { return true; }
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
@@ -240,7 +240,7 @@
     ASSERT(SignRegisterBits::is_valid(sign_.code()));
   }
 
-  bool IsPregenerated();
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
 
  private:
@@ -316,7 +316,7 @@
     INCREMENTAL_COMPACTION
   };
 
-  virtual bool IsPregenerated();
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
diff --git a/src/mips/debug-mips.cc b/src/mips/debug-mips.cc
index 020228f..1535231 100644
--- a/src/mips/debug-mips.cc
+++ b/src/mips/debug-mips.cc
@@ -60,7 +60,7 @@
   // li and Call pseudo-instructions emit two instructions each.
   patcher.masm()->li(v8::internal::t9,
       Operand(reinterpret_cast<int32_t>(
-          Isolate::Current()->debug()->debug_break_return()->entry())));
+        debug_info_->GetIsolate()->debug()->debug_break_return()->entry())));
   patcher.masm()->Call(v8::internal::t9);
   patcher.masm()->nop();
   patcher.masm()->nop();
@@ -105,7 +105,7 @@
   //   call t9          (jalr t9 / nop instruction pair)
   CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
   patcher.masm()->li(v8::internal::t9, Operand(reinterpret_cast<int32_t>(
-      Isolate::Current()->debug()->debug_break_slot()->entry())));
+      debug_info_->GetIsolate()->debug()->debug_break_slot()->entry())));
   patcher.masm()->Call(v8::internal::t9);
 }
 
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index 847dea0..e250e0e 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -359,7 +359,7 @@
                                          extra_state,
                                          Code::NORMAL,
                                          argc);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, a1, a2, a3, t0, t1, t2);
 
   // If the stub cache probing failed, the receiver might be a value.
@@ -395,7 +395,7 @@
 
   // Probe the stub cache for the value object.
   __ bind(&probe);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, a1, a2, a3, t0, t1, t2);
 
   __ bind(&miss);
@@ -658,7 +658,7 @@
   Code::Flags flags = Code::ComputeFlags(
       Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, a0, a2, a3, t0, t1, t2);
 
   // Cache miss: Jump to runtime.
@@ -1498,7 +1498,7 @@
   Code::Flags flags = Code::ComputeFlags(
       Code::STUB, MONOMORPHIC, strict_mode,
       Code::NORMAL, Code::STORE_IC);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, a1, a2, a3, t0, t1, t2);
 
   // Cache miss: Jump to runtime.
diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc
index 7b67a7b..1a04fd1 100644
--- a/src/mips/regexp-macro-assembler-mips.cc
+++ b/src/mips/regexp-macro-assembler-mips.cc
@@ -882,7 +882,7 @@
   masm_->GetCode(&code_desc);
   Handle<Code> code = isolate()->factory()->NewCode(
       code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject());
-  LOG(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
+  LOG(masm_->isolate(), RegExpCodeCreateEvent(*code, *source));
   return Handle<HeapObject>::cast(code);
 }
 
@@ -1086,7 +1086,6 @@
                                                    Code* re_code,
                                                    Address re_frame) {
   Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
-  ASSERT(isolate == Isolate::Current());
   if (isolate->stack_guard()->IsStackOverflow()) {
     isolate->StackOverflow();
     return EXCEPTION;
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index cc75a61..a8004d9 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -2935,46 +2935,6 @@
 }
 
 
-Handle<Code> StoreStubCompiler::CompileStoreGlobal(
-    Handle<GlobalObject> object,
-    Handle<PropertyCell> cell,
-    Handle<Name> name) {
-  Label miss;
-
-  // Check that the map of the global has not changed.
-  __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
-  __ Branch(&miss, ne, scratch1(), Operand(Handle<Map>(object->map())));
-
-  // Check that the value in the cell is not the hole. If it is, this
-  // cell could have been deleted and reintroducing the global needs
-  // to update the property details in the property dictionary of the
-  // global object. We bail out to the runtime system to do that.
-  __ li(scratch1(), Operand(cell));
-  __ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
-  __ lw(scratch3(), FieldMemOperand(scratch1(), Cell::kValueOffset));
-  __ Branch(&miss, eq, scratch3(), Operand(scratch2()));
-
-  // Store the value in the cell.
-  __ sw(value(), FieldMemOperand(scratch1(), Cell::kValueOffset));
-  __ mov(v0, a0);  // Stored value must be returned in v0.
-  // Cells are always rescanned, so no write barrier here.
-
-  Counters* counters = isolate()->counters();
-  __ IncrementCounter(
-      counters->named_store_global_inline(), 1, scratch1(), scratch2());
-  __ Ret();
-
-  // Handle store cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(
-      counters->named_store_global_inline_miss(), 1, scratch1(), scratch2());
-  TailCallBuiltin(masm(), MissBuiltin(kind()));
-
-  // Return the generated code.
-  return GetICCode(kind(), Code::NORMAL, name);
-}
-
-
 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
     Handle<JSObject> object,
     Handle<JSObject> last,
diff --git a/src/object-observe.js b/src/object-observe.js
index 81385c3..1035792 100644
--- a/src/object-observe.js
+++ b/src/object-observe.js
@@ -367,13 +367,22 @@
   return ObjectUnobserve(object, callback);
 }
 
-function ObserverEnqueueIfActive(observer, objectInfo, changeRecord) {
+function ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
+                                 needsAccessCheck) {
   if (!ObserverIsActive(observer, objectInfo) ||
       !TypeMapHasType(ObserverGetAcceptTypes(observer), changeRecord.type)) {
     return;
   }
 
   var callback = ObserverGetCallback(observer);
+  if (needsAccessCheck &&
+      // Drop all splice records on the floor for access-checked objects
+      (changeRecord.type == 'splice' ||
+       !%IsAccessAllowedForObserver(
+           callback, changeRecord.object, changeRecord.name))) {
+    return;
+  }
+
   var callbackInfo = CallbackInfoNormalize(callback);
   if (!observationState.pendingObservers)
     observationState.pendingObservers = { __proto__: null };
@@ -382,19 +391,25 @@
   %SetObserverDeliveryPending();
 }
 
-function ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord) {
+function ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord,
+                                       skipAccessCheck) {
   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
   if (IS_SYMBOL(changeRecord.name)) return;
 
+  var needsAccessCheck = !skipAccessCheck &&
+      %IsAccessCheckNeeded(changeRecord.object);
+
   if (ChangeObserversIsOptimized(objectInfo.changeObservers)) {
     var observer = objectInfo.changeObservers;
-    ObserverEnqueueIfActive(observer, objectInfo, changeRecord);
+    ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
+                            needsAccessCheck);
     return;
   }
 
   for (var priority in objectInfo.changeObservers) {
     var observer = objectInfo.changeObservers[priority];
-    ObserverEnqueueIfActive(observer, objectInfo, changeRecord);
+    ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
+                            needsAccessCheck);
   }
 }
 
@@ -463,10 +478,11 @@
   }
   ObjectFreeze(newRecord);
 
-  ObjectInfoEnqueueChangeRecord(objectInfo, newRecord);
+  ObjectInfoEnqueueChangeRecord(objectInfo, newRecord,
+                                true /* skip access check */);
 }
 
-function ObjectNotifierPerformChange(changeType, changeFn, receiver) {
+function ObjectNotifierPerformChange(changeType, changeFn) {
   if (!IS_SPEC_OBJECT(this))
     throw MakeTypeError("called_on_non_object", ["performChange"]);
 
@@ -479,15 +495,9 @@
   if (!IS_SPEC_FUNCTION(changeFn))
     throw MakeTypeError("observe_perform_non_function");
 
-  if (IS_NULL_OR_UNDEFINED(receiver)) {
-    receiver = %GetDefaultReceiver(changeFn) || receiver;
-  } else if (!IS_SPEC_OBJECT(receiver) && %IsClassicModeFunction(changeFn)) {
-    receiver = ToObject(receiver);
-  }
-
   ObjectInfoAddPerformingType(objectInfo, changeType);
   try {
-    %_CallFunction(receiver, changeFn);
+    %_CallFunction(void 0, changeFn);
   } finally {
     ObjectInfoRemovePerformingType(objectInfo, changeType);
   }
@@ -520,7 +530,7 @@
   %MoveArrayContents(callbackInfo, delivered);
 
   try {
-    %Call(void 0, delivered, callback);
+    %_CallFunction(void 0, delivered, callback);
   } catch (ex) {}
   return true;
 }
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 883afe9..3716df1 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -329,11 +329,17 @@
       }
     }
   }
-  CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
-             (elements() == GetHeap()->empty_fixed_array())),
-            (elements()->map() == GetHeap()->fixed_array_map() ||
-             elements()->map() == GetHeap()->fixed_cow_array_map()));
-  CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
+
+  // TODO(hpayer): deal gracefully with partially constructed JSObjects, when
+  // allocation folding is turned off.
+  if (reinterpret_cast<Map*>(elements()) !=
+      GetHeap()->one_pointer_filler_map()) {
+    CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
+              (elements() == GetHeap()->empty_fixed_array())),
+             (elements()->map() == GetHeap()->fixed_array_map() ||
+              elements()->map() == GetHeap()->fixed_cow_array_map()));
+    CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
+  }
 }
 
 
@@ -677,9 +683,19 @@
 void JSArray::JSArrayVerify() {
   JSObjectVerify();
   CHECK(length()->IsNumber() || length()->IsUndefined());
-  CHECK(elements()->IsUndefined() ||
-         elements()->IsFixedArray() ||
-         elements()->IsFixedDoubleArray());
+  // TODO(hpayer): deal gracefully with partially constructed JSObjects, when
+  // allocation folding is turned off.
+  if (reinterpret_cast<Map*>(elements()) !=
+      GetHeap()->one_pointer_filler_map()) {
+    CHECK(elements()->IsUndefined() ||
+          elements()->IsFixedArray() ||
+          elements()->IsFixedDoubleArray());
+    // TODO(mvstanton): to diagnose chromium bug 284577, remove after.
+    AllocationMemento* memento = AllocationMemento::FindForJSObject(this);
+    if (memento != NULL && memento->IsValid()) {
+      memento->AllocationMementoVerify();
+    }
+  }
 }
 
 
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index e90c74c..46cc9d7 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -848,8 +848,9 @@
   IteratePointer(v, kTypeFeedbackInfoOffset);
 
   RelocIterator it(this, mode_mask);
+  Isolate* isolate = this->GetIsolate();
   for (; !it.done(); it.next()) {
-    it.rinfo()->Visit(v);
+    it.rinfo()->Visit(isolate, v);
   }
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index 027506f..43e3f53 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -9011,6 +9011,8 @@
   // involves carefully checking the object immediately after the JSArray
   // (if there is one) to see if it's an AllocationMemento.
   if (FLAG_track_allocation_sites && object->GetHeap()->InNewSpace(object)) {
+    // TODO(mvstanton): CHECK to diagnose chromium bug 284577, remove after.
+    CHECK(object->GetHeap()->InToSpace(object));
     Address ptr_end = (reinterpret_cast<Address>(object) - kHeapObjectTag) +
         object->Size();
     if ((ptr_end + AllocationMemento::kSize) <=
@@ -9020,8 +9022,14 @@
           reinterpret_cast<Map**>(ptr_end);
       if (*possible_allocation_memento_map ==
           object->GetHeap()->allocation_memento_map()) {
+        Address ptr_object = reinterpret_cast<Address>(object);
+        // TODO(mvstanton): CHECK to diagnose chromium bug 284577, remove after.
+        // If this check fails it points to the very unlikely case that we've
+        // misinterpreted a page header as an allocation memento. Follow up
+        // with a real fix.
+        CHECK(Page::FromAddress(ptr_object) == Page::FromAddress(ptr_end));
         AllocationMemento* memento = AllocationMemento::cast(
-            reinterpret_cast<Object*>(ptr_end + 1));
+            reinterpret_cast<Object*>(ptr_end + kHeapObjectTag));
         return memento;
       }
     }
@@ -9892,7 +9900,7 @@
   if (code()->kind() == Code::FUNCTION) {
     code()->set_optimizable(false);
   }
-  PROFILE(Isolate::Current(),
+  PROFILE(GetIsolate(),
       LogExistingFunction(Handle<SharedFunctionInfo>(this),
                           Handle<Code>(code())));
   if (FLAG_trace_opt) {
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index b0e37fd..a040453 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -234,14 +234,18 @@
 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);
+  OptimizingCompiler* result = NULL;
+  { 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_++;
+        result = ready_for_osr_.Remove(i);
+        break;
+      }
     }
   }
-  return NULL;
+  RemoveStaleOSRCandidates();
+  return result;
 }
 
 
@@ -258,6 +262,18 @@
 }
 
 
+bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) {
+  ASSERT(!IsOptimizerThread());
+  LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
+  for (int i = 0; i < osr_candidates_.length(); i++) {
+    if (*osr_candidates_[i]->info()->closure() == function) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
 void OptimizingCompilerThread::RemoveStaleOSRCandidates(int limit) {
   ASSERT(!IsOptimizerThread());
   LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h
index 01cd2a0..f45665b 100644
--- a/src/optimizing-compiler-thread.h
+++ b/src/optimizing-compiler-thread.h
@@ -71,9 +71,7 @@
                                             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);
+  bool IsQueuedForOSR(JSFunction* function);
 
   inline bool IsQueueAvailable() {
     // We don't need a barrier since we have a data dependency right
@@ -96,6 +94,10 @@
  private:
   enum StopFlag { CONTINUE, STOP, FLUSH };
 
+  // Remove the oldest OSR candidates that are ready so that we
+  // only have |limit| left waiting.
+  void RemoveStaleOSRCandidates(int limit = kReadyForOSRLimit);
+
   void FlushInputQueue(bool restore_function_code);
   void FlushOutputQueue(bool restore_function_code);
   void CompileNext();
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index 9618d7e..4d3b1e3 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -141,7 +141,7 @@
 }
 
 
-void OS::LogSharedLibraryAddresses() {
+void OS::LogSharedLibraryAddresses(Isolate* isolate) {
   // This function assumes that the layout of the file is as follows:
   // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
   // If we encounter an unexpected situation we abort scanning further entries.
@@ -152,7 +152,6 @@
   const int kLibNameLen = FILENAME_MAX + 1;
   char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
 
-  i::Isolate* isolate = Isolate::Current();
   // This loop will terminate once the scanning hits an EOF.
   while (true) {
     uintptr_t start, end;
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 34ed709..d818278 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -155,7 +155,7 @@
 }
 
 
-void OS::LogSharedLibraryAddresses() {
+void OS::LogSharedLibraryAddresses(Isolate* isolate) {
   static const int MAP_LENGTH = 1024;
   int fd = open("/proc/self/maps", O_RDONLY);
   if (fd < 0) return;
@@ -189,7 +189,7 @@
     // There may be no filename in this line.  Skip to next.
     if (start_of_path == NULL) continue;
     buffer[bytes_read] = 0;
-    LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end));
+    LOG(isolate SharedLibraryEvent(start_of_path, start, end));
   }
   close(fd);
 }
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 39bf1cb..b8b9602 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -220,7 +220,7 @@
 }
 
 
-void OS::LogSharedLibraryAddresses() {
+void OS::LogSharedLibraryAddresses(Isolate* isolate) {
   // This function assumes that the layout of the file is as follows:
   // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
   // If we encounter an unexpected situation we abort scanning further entries.
@@ -231,7 +231,6 @@
   const int kLibNameLen = FILENAME_MAX + 1;
   char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
 
-  i::Isolate* isolate = Isolate::Current();
   // This loop will terminate once the scanning hits an EOF.
   while (true) {
     uintptr_t start, end;
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index f618737..67cc96f 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -173,7 +173,7 @@
 }
 
 
-void OS::LogSharedLibraryAddresses() {
+void OS::LogSharedLibraryAddresses(Isolate* isolate) {
   unsigned int images_count = _dyld_image_count();
   for (unsigned int i = 0; i < images_count; ++i) {
     const mach_header* header = _dyld_get_image_header(i);
@@ -192,7 +192,7 @@
     if (code_ptr == NULL) continue;
     const uintptr_t slide = _dyld_get_image_vmaddr_slide(i);
     const uintptr_t start = reinterpret_cast<uintptr_t>(code_ptr) + slide;
-    LOG(Isolate::Current(),
+    LOG(isolate,
         SharedLibraryEvent(_dyld_get_image_name(i), start, start + size));
   }
 }
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index bb20df3..30a484f 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -149,7 +149,7 @@
 }
 
 
-void OS::LogSharedLibraryAddresses() {
+void OS::LogSharedLibraryAddresses(Isolate* isolate) {
   // This function assumes that the layout of the file is as follows:
   // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
   // If we encounter an unexpected situation we abort scanning further entries.
@@ -160,7 +160,6 @@
   const int kLibNameLen = FILENAME_MAX + 1;
   char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
 
-  i::Isolate* isolate = Isolate::Current();
   // This loop will terminate once the scanning hits an EOF.
   while (true) {
     uintptr_t start, end;
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 512d995..f082af1 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -165,7 +165,7 @@
 }
 
 
-void OS::LogSharedLibraryAddresses() {
+void OS::LogSharedLibraryAddresses(Isolate* isolate) {
 }
 
 
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 2e82056..ea4f7ea 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1129,7 +1129,7 @@
 
 
 // Load the symbols for generating stack traces.
-static bool LoadSymbols(HANDLE process_handle) {
+static bool LoadSymbols(Isolate* isolate, HANDLE process_handle) {
   static bool symbols_loaded = false;
 
   if (symbols_loaded) return true;
@@ -1178,7 +1178,7 @@
       if (err != ERROR_MOD_NOT_FOUND &&
           err != ERROR_INVALID_HANDLE) return false;
     }
-    LOG(i::Isolate::Current(),
+    LOG(isolate,
         SharedLibraryEvent(
             module_entry.szExePath,
             reinterpret_cast<unsigned int>(module_entry.modBaseAddr),
@@ -1193,14 +1193,14 @@
 }
 
 
-void OS::LogSharedLibraryAddresses() {
+void OS::LogSharedLibraryAddresses(Isolate* isolate) {
   // SharedLibraryEvents are logged when loading symbol information.
   // Only the shared libraries loaded at the time of the call to
   // LogSharedLibraryAddresses are logged.  DLLs loaded after
   // initialization are not accounted for.
   if (!LoadDbgHelpAndTlHelp32()) return;
   HANDLE process_handle = GetCurrentProcess();
-  LoadSymbols(process_handle);
+  LoadSymbols(isolate, process_handle);
 }
 
 
@@ -1226,7 +1226,7 @@
   HANDLE thread_handle = GetCurrentThread();
 
   // Read the symbols.
-  if (!LoadSymbols(process_handle)) return kStackWalkError;
+  if (!LoadSymbols(Isolate::Current(), process_handle)) return kStackWalkError;
 
   // Capture current context.
   CONTEXT context;
@@ -1332,7 +1332,7 @@
 #pragma warning(pop)
 
 #else  // __MINGW32__
-void OS::LogSharedLibraryAddresses() { }
+void OS::LogSharedLibraryAddresses(Isolate* isolate) { }
 void OS::SignalCodeMovingGC() { }
 int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; }
 #endif  // __MINGW32__
diff --git a/src/platform.h b/src/platform.h
index 428ba55..ee8fb92 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -287,7 +287,7 @@
 
   // Support for the profiler.  Can do nothing, in which case ticks
   // occuring in shared libraries will not be properly accounted for.
-  static void LogSharedLibraryAddresses();
+  static void LogSharedLibraryAddresses(Isolate* isolate);
 
   // Support for the profiler.  Notifies the external profiling
   // process that a code moving garbage collection starts.  Can do
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index cfce1df..8676d81 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -139,7 +139,16 @@
     PrintF("]\n");
   }
 
+
   if (FLAG_concurrent_recompilation && !isolate_->bootstrapper()->IsActive()) {
+    if (FLAG_concurrent_osr &&
+        isolate_->optimizing_compiler_thread()->IsQueuedForOSR(function)) {
+      // Do not attempt regular recompilation if we already queued this for OSR.
+      // TODO(yangguo): This is necessary so that we don't install optimized
+      // code on a function that is already optimized, since OSR and regular
+      // recompilation race.  This goes away as soon as OSR becomes one-shot.
+      return;
+    }
     ASSERT(!function->IsMarkedForInstallingRecompiledCode());
     ASSERT(!function->IsInRecompileQueue());
     function->MarkForConcurrentRecompilation();
@@ -224,6 +233,8 @@
     isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
   }
 
+  DisallowHeapAllocation no_gc;
+
   // Run through the JavaScript frames and collect them. If we already
   // have a sample of the function, we mark it for optimizations
   // (eagerly or lazily).
diff --git a/src/runtime.cc b/src/runtime.cc
index 9f37411..00efa51 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8581,38 +8581,125 @@
 }
 
 
+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;
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
   HandleScope scope(isolate);
-  ASSERT(args.length() == 1);
+  ASSERT(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+  CONVERT_NUMBER_CHECKED(uint32_t, pc_offset, Uint32, args[1]);
+  Handle<Code> unoptimized(function->shared()->code(), isolate);
+
+#ifdef DEBUG
+  JavaScriptFrameIterator it(isolate);
+  JavaScriptFrame* frame = it.frame();
+  ASSERT_EQ(frame->function(), *function);
+  ASSERT_EQ(frame->LookupCode(), *unoptimized);
+  ASSERT(unoptimized->contains(frame->pc()));
+
+  ASSERT(pc_offset ==
+         static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start()));
+#endif  // DEBUG
 
   // We're not prepared to handle a function with arguments object.
   ASSERT(!function->shared()->uses_arguments());
 
-  // If the optimization attempt succeeds, return the code object which
-  // the unoptimized code can jump into.
-  Handle<Code> code =
-      (FLAG_concurrent_recompilation && FLAG_concurrent_osr)
-          ? Compiler::CompileForConcurrentOSR(function)
-          : Compiler::CompileForOnStackReplacement(function);
-  if (!code.is_null()) {
-#if DEBUG
-    ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
-    DeoptimizationInputData* data =
-        DeoptimizationInputData::cast(code->deoptimization_data());
-    ASSERT(!BailoutId(data->OsrAstId()->value()).IsNone());
-#endif
-    // TODO(titzer): this is a massive hack to make the deopt counts
-    // match. Fix heuristics for reenabling optimizations!
-    function->shared()->increment_deopt_count();
-    return *code;
-  } else {
-    if (function->IsMarkedForLazyRecompilation() ||
-        function->IsMarkedForConcurrentRecompilation()) {
-      function->ReplaceCode(function->shared()->code());
+  Handle<Code> result = Handle<Code>::null();
+  BailoutId ast_id = BailoutId::None();
+
+  if (FLAG_concurrent_recompilation && FLAG_concurrent_osr) {
+    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 NULL;
     }
-    return NULL;
+
+    OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()->
+        FindReadyOSRCandidate(function, pc_offset);
+
+    if (compiler == NULL) {
+      if (IsSuitableForOnStackReplacement(isolate, function, unoptimized) &&
+          Compiler::RecompileConcurrent(function, pc_offset)) {
+        if (function->IsMarkedForLazyRecompilation() ||
+            function->IsMarkedForConcurrentRecompilation()) {
+          // Prevent regular recompilation if we queue this for OSR.
+          // TODO(yangguo): remove this as soon as OSR becomes one-shot.
+          function->ReplaceCode(function->shared()->code());
+        }
+        return NULL;
+      }
+      // Fall through to the end in case of failure.
+    } else {
+      // TODO(titzer): don't install the OSR code into the function.
+      ast_id = compiler->info()->osr_ast_id();
+      result = Compiler::InstallOptimizedCode(compiler);
+    }
+  } else if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
+    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");
+    }
+    // Attempt OSR compilation.
+    result = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION);
   }
+
+  // Revert the patched interrupt now, regardless of whether OSR succeeds.
+  Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
+
+  // Check whether we ended up with usable optimized code.
+  if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
+    DeoptimizationInputData* data =
+        DeoptimizationInputData::cast(result->deoptimization_data());
+
+    if (data->OsrPcOffset()->value() >= 0) {
+      ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
+      if (FLAG_trace_osr) {
+        PrintF("[OSR - entry at AST id %d, offset %d in optimized code]\n",
+               ast_id.ToInt(), data->OsrPcOffset()->value());
+      }
+      // TODO(titzer): this is a massive hack to make the deopt counts
+      // match. Fix heuristics for reenabling optimizations!
+      function->shared()->increment_deopt_count();
+      return *result;
+    }
+  }
+
+  if (FLAG_trace_osr) {
+    PrintF("[OSR - optimization failed for ");
+    function->PrintName();
+    PrintF("]\n");
+  }
+
+  if (function->IsMarkedForLazyRecompilation() ||
+      function->IsMarkedForConcurrentRecompilation()) {
+    function->ReplaceCode(function->shared()->code());
+  }
+  return NULL;
 }
 
 
@@ -14418,6 +14505,14 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) {
+  SealHandleScope shs(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(HeapObject, obj, 0);
+  return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded());
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 1);
@@ -14495,6 +14590,34 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 3);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
+  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
+  ASSERT(object->IsAccessCheckNeeded());
+  Handle<Object> key = args.at<Object>(2);
+  SaveContext save(isolate);
+  isolate->set_context(observer->context());
+  if (!isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
+                               v8::ACCESS_KEYS)) {
+    return isolate->heap()->false_value();
+  }
+  bool access_allowed = false;
+  uint32_t index = 0;
+  if (key->ToArrayIndex(&index) ||
+      (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) {
+    access_allowed =
+        isolate->MayIndexedAccess(*object, index, v8::ACCESS_GET) &&
+        isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS);
+  } else {
+    access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) &&
+        isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS);
+  }
+  return isolate->heap()->ToBoolean(access_allowed);
+}
+
+
 static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
                                            Handle<JSFunction> constructor,
                                            Handle<Object> type_info,
diff --git a/src/runtime.h b/src/runtime.h
index 4c76098..bce09a4 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -100,7 +100,7 @@
   F(NeverOptimizeFunction, 1, 1) \
   F(GetOptimizationStatus, -1, 1) \
   F(GetOptimizationCount, 1, 1) \
-  F(CompileForOnStackReplacement, 1, 1) \
+  F(CompileForOnStackReplacement, 2, 1) \
   F(SetAllocationTimeout, 2, 1) \
   F(AllocateInNewSpace, 1, 1) \
   F(AllocateInOldPointerSpace, 1, 1) \
@@ -358,6 +358,7 @@
   F(GetObservationState, 0, 1) \
   F(ObservationWeakMapCreate, 0, 1) \
   F(UnwrapGlobalProxy, 1, 1) \
+  F(IsAccessAllowedForObserver, 3, 1) \
   \
   /* Harmony typed arrays */ \
   F(ArrayBufferInitialize, 2, 1)\
@@ -469,7 +470,8 @@
   F(HasExternalDoubleElements, 1, 1) \
   F(HasFastProperties, 1, 1) \
   F(TransitionElementsKind, 2, 1) \
-  F(HaveSameMap, 2, 1)
+  F(HaveSameMap, 2, 1) \
+  F(IsAccessCheckNeeded, 1, 1)
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/string-stream.cc b/src/string-stream.cc
index 7c45e2f..45b675f 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -269,8 +269,8 @@
 }
 
 
-void StringStream::Log() {
-  LOG(Isolate::Current(), StringEvent("StackDump", buffer_));
+void StringStream::Log(Isolate* isolate) {
+  LOG(isolate, StringEvent("StackDump", buffer_));
 }
 
 
diff --git a/src/string-stream.h b/src/string-stream.h
index 255a2c3..e3db2a8 100644
--- a/src/string-stream.h
+++ b/src/string-stream.h
@@ -147,7 +147,7 @@
   // Getting the message out.
   void OutputToFile(FILE* out);
   void OutputToStdOut() { OutputToFile(stdout); }
-  void Log();
+  void Log(Isolate* isolate);
   Handle<String> ToString(Isolate* isolate);
   SmartArrayPointer<const char> ToCString() const;
   int length() const { return length_; }
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 12afdd3..141e567 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -982,10 +982,6 @@
   Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
                                        Handle<Name> name);
 
-  Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
-                                  Handle<PropertyCell> holder,
-                                  Handle<Name> name);
-
  private:
   static Register* registers();
   virtual Code::Kind kind() { return Code::STORE_IC; }
diff --git a/src/version.cc b/src/version.cc
index 076c7ef..a491a4f 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      13
+#define BUILD_NUMBER      14
 #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/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index 826c06e..07d0703 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -448,7 +448,7 @@
 }
 
 
-void RelocInfo::Visit(ObjectVisitor* visitor) {
+void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
     visitor->VisitEmbeddedPointer(this);
@@ -463,12 +463,11 @@
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     visitor->VisitCodeAgeSequence(this);
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  // TODO(isolates): Get a cached isolate below.
   } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
               IsPatchedDebugBreakSlotSequence())) &&
-             Isolate::Current()->debug()->has_break_points()) {
+             isolate->debug()->has_break_points()) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (RelocInfo::IsRuntimeEntry(mode)) {
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 4730ed1..1960c3c 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -1408,14 +1408,21 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
+  // Lookup the function in the JavaScript frame.
   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-
-  // Pass the function to optimize as the argument to the on-stack
-  // replacement runtime function.
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
+    // Lookup and calculate pc offset.
+    __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerPCOffset));
+    __ movq(rbx, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
+    __ subq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
+    __ subq(rdx, FieldOperand(rbx, SharedFunctionInfo::kCodeOffset));
+    __ Integer32ToSmi(rdx, rdx);
+
+    // Pass both function and pc offset as arguments.
     __ push(rax);
-    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
+    __ push(rdx);
+    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2);
   }
 
   Label skip;
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 00c5367..f6cfb4f 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1200,7 +1200,7 @@
       ExternalReference::transcendental_cache_array_address(masm->isolate());
   __ movq(rax, cache_array);
   int cache_array_index =
-      type_ * sizeof(Isolate::Current()->transcendental_cache()->caches_[0]);
+      type_ * sizeof(masm->isolate()->transcendental_cache()->caches_[0]);
   __ movq(rax, Operand(rax, cache_array_index));
   // rax points to the cache for the type type_.
   // If NULL, the cache hasn't been initialized yet, so go through runtime.
@@ -3490,7 +3490,7 @@
   __ SetCallKind(rcx, CALL_AS_METHOD);
   __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
   Handle<Code> adaptor =
-      Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline();
+      isolate->builtins()->ArgumentsAdaptorTrampoline();
   __ Jump(adaptor, RelocInfo::CODE_TARGET);
 }
 
@@ -3545,7 +3545,7 @@
 }
 
 
-bool CEntryStub::IsPregenerated() {
+bool CEntryStub::IsPregenerated(Isolate* isolate) {
 #ifdef _WIN64
   return result_size_ == 1;
 #else
@@ -5899,8 +5899,6 @@
   { REG(rbx), REG(rax), REG(rdi), EMIT_REMEMBERED_SET },
   // Used in CompileArrayPushCall.
   { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET },
-  // Used in CompileStoreGlobal.
-  { REG(rbx), REG(rcx), REG(rdx), OMIT_REMEMBERED_SET },
   // Used in StoreStubCompiler::CompileStoreField and
   // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
   { REG(rdx), REG(rcx), REG(rbx), EMIT_REMEMBERED_SET },
@@ -5937,7 +5935,7 @@
 
 #undef REG
 
-bool RecordWriteStub::IsPregenerated() {
+bool RecordWriteStub::IsPregenerated(Isolate* isolate) {
   for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
        !entry->object.is(no_reg);
        entry++) {
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index e430bf2..41678ec 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -69,7 +69,7 @@
 
   void Generate(MacroAssembler* masm);
 
-  virtual bool IsPregenerated() { return true; }
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
@@ -321,7 +321,7 @@
     INCREMENTAL_COMPACTION
   };
 
-  virtual bool IsPregenerated();
+  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   virtual bool SometimesSetsUpAFrame() { return false; }
 
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index c8e1c96..6612242 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -50,7 +50,7 @@
 void BreakLocationIterator::SetDebugBreakAtReturn()  {
   ASSERT(Assembler::kJSReturnSequenceLength >= Assembler::kCallSequenceLength);
   rinfo()->PatchCodeWithCall(
-      Isolate::Current()->debug()->debug_break_return()->entry(),
+      debug_info_->GetIsolate()->debug()->debug_break_return()->entry(),
       Assembler::kJSReturnSequenceLength - Assembler::kCallSequenceLength);
 }
 
@@ -80,7 +80,7 @@
 void BreakLocationIterator::SetDebugBreakAtSlot() {
   ASSERT(IsDebugBreakSlot());
   rinfo()->PatchCodeWithCall(
-      Isolate::Current()->debug()->debug_break_slot()->entry(),
+      debug_info_->GetIsolate()->debug()->debug_break_slot()->entry(),
       Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength);
 }
 
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 84a47d6..4a7c68a 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -822,8 +822,8 @@
                                          extra_state,
                                          Code::NORMAL,
                                          argc);
-  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
-                                                  rax);
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, flags, rdx, rcx, rbx, rax);
 
   // If the stub cache probing failed, the receiver might be a value.
   // For value objects, we use the map of the prototype objects for
@@ -859,8 +859,8 @@
 
   // Probe the stub cache for the value object.
   __ bind(&probe);
-  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
-                                                  no_reg);
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, flags, rdx, rcx, rbx, no_reg);
 
   __ bind(&miss);
 }
@@ -1332,7 +1332,7 @@
   Code::Flags flags = Code::ComputeFlags(
       Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
-  Isolate::Current()->stub_cache()->GenerateProbe(
+  masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, rax, rcx, rbx, rdx);
 
   GenerateMiss(masm);
@@ -1453,8 +1453,8 @@
   Code::Flags flags = Code::ComputeFlags(
       Code::STUB, MONOMORPHIC, strict_mode,
       Code::NORMAL, Code::STORE_IC);
-  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
-                                                  no_reg);
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, flags, rdx, rcx, rbx, no_reg);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 999622a..ca834e2 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -1188,7 +1188,6 @@
                                                   Code* re_code,
                                                   Address re_frame) {
   Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
-  ASSERT(isolate == Isolate::Current());
   if (isolate->stack_guard()->IsStackOverflow()) {
     isolate->StackOverflow();
     return EXCEPTION;
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 31f60be..b2cfa86 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -2897,48 +2897,6 @@
 }
 
 
-Handle<Code> StoreStubCompiler::CompileStoreGlobal(
-    Handle<GlobalObject> object,
-    Handle<PropertyCell> cell,
-    Handle<Name> name) {
-  Label miss;
-
-  // Check that the map of the global has not changed.
-  __ Cmp(FieldOperand(receiver(), HeapObject::kMapOffset),
-         Handle<Map>(object->map()));
-  __ j(not_equal, &miss);
-
-  // Compute the cell operand to use.
-  __ Move(scratch1(), cell);
-  Operand cell_operand =
-      FieldOperand(scratch1(), PropertyCell::kValueOffset);
-
-  // Check that the value in the cell is not the hole. If it is, this
-  // cell could have been deleted and reintroducing the global needs
-  // to update the property details in the property dictionary of the
-  // global object. We bail out to the runtime system to do that.
-  __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex);
-  __ j(equal, &miss);
-
-  // Store the value in the cell.
-  __ movq(cell_operand, value());
-  // Cells are always rescanned, so no write barrier here.
-
-  // Return the value (register rax).
-  Counters* counters = isolate()->counters();
-  __ IncrementCounter(counters->named_store_global_inline(), 1);
-  __ ret(0);
-
-  // Handle store cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
-  TailCallBuiltin(masm(), MissBuiltin(kind()));
-
-  // Return the generated code.
-  return GetICCode(kind(), Code::NORMAL, name);
-}
-
-
 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
     MapHandleList* receiver_maps,
     CodeHandleList* handler_stubs,
diff --git a/test/cctest/cctest.cc b/test/cctest/cctest.cc
index b206966..616c6a3 100644
--- a/test/cctest/cctest.cc
+++ b/test/cctest/cctest.cc
@@ -100,6 +100,7 @@
 
 class CcTestArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
   virtual void* Allocate(size_t length) { return malloc(length); }
+  virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
   virtual void Free(void* data, size_t length) { free(data); }
   // TODO(dslomov): Remove when v8:2823 is fixed.
   virtual void Free(void* data) { UNREACHABLE(); }
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index a8dde16..8566109 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -77,6 +77,8 @@
 test-serialize/DeserializeAndRunScript2: SKIP
 test-serialize/DeserializeFromSecondSerialization: SKIP
 
+# BUG(2874): Threading problems.
+test-api/*: PASS || FLAKY
 ##############################################################################
 [ $arch == mipsel ]
 
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
index e7cf1e5..b129ff3 100644
--- a/test/cctest/test-object-observe.cc
+++ b/test/cctest/test-object-observe.cc
@@ -313,11 +313,13 @@
         recordObj->Get(String::New("object"))));
     CHECK(String::New(expectations[i].type)->Equals(
         recordObj->Get(String::New("type"))));
-    CHECK(String::New(expectations[i].name)->Equals(
-        recordObj->Get(String::New("name"))));
-    if (!expectations[i].old_value.IsEmpty()) {
-      CHECK(expectations[i].old_value->Equals(
-          recordObj->Get(String::New("oldValue"))));
+    if (strcmp("splice", expectations[i].type) != 0) {
+      CHECK(String::New(expectations[i].name)->Equals(
+          recordObj->Get(String::New("name"))));
+      if (!expectations[i].old_value.IsEmpty()) {
+        CHECK(expectations[i].old_value->Equals(
+            recordObj->Get(String::New("oldValue"))));
+      }
     }
   }
 }
@@ -446,3 +448,270 @@
   CHECK_EQ(0, NumberOfElements(objectInfoMap));
   CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap));
 }
+
+
+static bool NamedAccessAlwaysAllowed(Local<Object>, Local<Value>, AccessType,
+                                     Local<Value>) {
+  return true;
+}
+
+
+static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType,
+                                       Local<Value>) {
+  return true;
+}
+
+
+static AccessType g_access_block_type = ACCESS_GET;
+
+
+static bool NamedAccessAllowUnlessBlocked(Local<Object> host,
+                                             Local<Value> key,
+                                             AccessType type,
+                                             Local<Value>) {
+  if (type != g_access_block_type) return true;
+  Handle<Object> global = Context::GetCurrent()->Global();
+  Handle<Value> blacklist = global->Get(String::New("blacklist"));
+  if (!blacklist->IsObject()) return true;
+  if (key->IsString()) return !blacklist.As<Object>()->Has(key);
+  return true;
+}
+
+
+static bool IndexedAccessAllowUnlessBlocked(Local<Object> host,
+                                               uint32_t index,
+                                               AccessType type,
+                                               Local<Value>) {
+  if (type != ACCESS_GET) return true;
+  Handle<Object> global = Context::GetCurrent()->Global();
+  Handle<Value> blacklist = global->Get(String::New("blacklist"));
+  if (!blacklist->IsObject()) return true;
+  return !blacklist.As<Object>()->Has(index);
+}
+
+
+static bool BlockAccessKeys(Local<Object> host, Local<Value> key,
+                            AccessType type, Local<Value>) {
+  Handle<Object> global = Context::GetCurrent()->Global();
+  Handle<Value> blacklist = global->Get(String::New("blacklist"));
+  if (!blacklist->IsObject()) return true;
+  return type != ACCESS_KEYS ||
+      !blacklist.As<Object>()->Has(String::New("__block_access_keys"));
+}
+
+
+static Handle<Object> CreateAccessCheckedObject(
+    NamedSecurityCallback namedCallback,
+    IndexedSecurityCallback indexedCallback) {
+  Handle<ObjectTemplate> tmpl = ObjectTemplate::New();
+  tmpl->SetAccessCheckCallbacks(namedCallback, indexedCallback);
+  Handle<Object> instance = tmpl->NewInstance();
+  instance->CreationContext()->Global()->Set(String::New("obj"), instance);
+  return instance;
+}
+
+
+TEST(NamedAccessCheck) {
+  HarmonyIsolate isolate;
+  const AccessType types[] = { ACCESS_GET, ACCESS_HAS };
+  for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
+    HandleScope scope(isolate.GetIsolate());
+    LocalContext context;
+    g_access_block_type = types[i];
+    Handle<Object> instance = CreateAccessCheckedObject(
+        NamedAccessAllowUnlessBlocked, IndexedAccessAlwaysAllowed);
+    CompileRun("var records = null;"
+               "var objNoCheck = {};"
+               "var blacklist = {foo: true};"
+               "var observer = function(r) { records = r };"
+               "Object.observe(obj, observer);"
+               "Object.observe(objNoCheck, observer);");
+    Handle<Value> obj_no_check = CompileRun("objNoCheck");
+    {
+      LocalContext context2;
+      context2->Global()->Set(String::New("obj"), instance);
+      context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+      CompileRun("var records2 = null;"
+                 "var observer2 = function(r) { records2 = r };"
+                 "Object.observe(obj, observer2);"
+                 "Object.observe(objNoCheck, observer2);"
+                 "obj.foo = 'bar';"
+                 "Object.defineProperty(obj, 'foo', {value: 5});"
+                 "Object.defineProperty(obj, 'foo', {get: function(){}});"
+                 "obj.bar = 'baz';"
+                 "objNoCheck.baz = 'quux'");
+      const RecordExpectation expected_records2[] = {
+        { instance, "new", "foo", Handle<Value>() },
+        { instance, "updated", "foo", String::New("bar") },
+        { instance, "reconfigured", "foo", Number::New(5) },
+        { instance, "new", "bar", Handle<Value>() },
+        { obj_no_check, "new", "baz", Handle<Value>() },
+      };
+      EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+    }
+    const RecordExpectation expected_records[] = {
+      { instance, "new", "bar", Handle<Value>() },
+      { obj_no_check, "new", "baz", Handle<Value>() }
+    };
+    EXPECT_RECORDS(CompileRun("records"), expected_records);
+  }
+}
+
+
+TEST(IndexedAccessCheck) {
+  HarmonyIsolate isolate;
+  const AccessType types[] = { ACCESS_GET, ACCESS_HAS };
+  for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
+    HandleScope scope(isolate.GetIsolate());
+    LocalContext context;
+    g_access_block_type = types[i];
+    Handle<Object> instance = CreateAccessCheckedObject(
+        NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked);
+    CompileRun("var records = null;"
+               "var objNoCheck = {};"
+               "var blacklist = {7: true};"
+               "var observer = function(r) { records = r };"
+               "Object.observe(obj, observer);"
+               "Object.observe(objNoCheck, observer);");
+    Handle<Value> obj_no_check = CompileRun("objNoCheck");
+    {
+      LocalContext context2;
+      context2->Global()->Set(String::New("obj"), instance);
+      context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+      CompileRun("var records2 = null;"
+                 "var observer2 = function(r) { records2 = r };"
+                 "Object.observe(obj, observer2);"
+                 "Object.observe(objNoCheck, observer2);"
+                 "obj[7] = 'foo';"
+                 "Object.defineProperty(obj, '7', {value: 5});"
+                 "Object.defineProperty(obj, '7', {get: function(){}});"
+                 "obj[8] = 'bar';"
+                 "objNoCheck[42] = 'quux'");
+      const RecordExpectation expected_records2[] = {
+        { instance, "new", "7", Handle<Value>() },
+        { instance, "updated", "7", String::New("foo") },
+        { instance, "reconfigured", "7", Number::New(5) },
+        { instance, "new", "8", Handle<Value>() },
+        { obj_no_check, "new", "42", Handle<Value>() }
+      };
+      EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+    }
+    const RecordExpectation expected_records[] = {
+      { instance, "new", "8", Handle<Value>() },
+      { obj_no_check, "new", "42", Handle<Value>() }
+    };
+    EXPECT_RECORDS(CompileRun("records"), expected_records);
+  }
+}
+
+
+TEST(SpliceAccessCheck) {
+  HarmonyIsolate isolate;
+  HandleScope scope(isolate.GetIsolate());
+  LocalContext context;
+  g_access_block_type = ACCESS_GET;
+  Handle<Object> instance = CreateAccessCheckedObject(
+      NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked);
+  CompileRun("var records = null;"
+             "obj[1] = 'foo';"
+             "obj.length = 2;"
+             "var objNoCheck = {1: 'bar', length: 2};"
+             "var blacklist = {1: true};"
+             "observer = function(r) { records = r };"
+             "Array.observe(obj, observer);"
+             "Array.observe(objNoCheck, observer);");
+  Handle<Value> obj_no_check = CompileRun("objNoCheck");
+  {
+    LocalContext context2;
+    context2->Global()->Set(String::New("obj"), instance);
+    context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+    CompileRun("var records2 = null;"
+               "var observer2 = function(r) { records2 = r };"
+               "Array.observe(obj, observer2);"
+               "Array.observe(objNoCheck, observer2);"
+               // No one should hear about this: no splice records are emitted
+               // for access-checked objects
+               "[].push.call(obj, 5);"
+               "[].splice.call(obj, 1, 1);"
+               "[].pop.call(obj);"
+               "[].pop.call(objNoCheck);");
+    // TODO(adamk): Extend EXPECT_RECORDS to be able to assert more things
+    // about splice records. For this test it's not so important since
+    // we just want to guarantee the machinery is in operation at all.
+    const RecordExpectation expected_records2[] = {
+      { obj_no_check, "splice", "", Handle<Value>() }
+    };
+    EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+  }
+  const RecordExpectation expected_records[] = {
+    { obj_no_check, "splice", "", Handle<Value>() }
+  };
+  EXPECT_RECORDS(CompileRun("records"), expected_records);
+}
+
+
+TEST(DisallowAllForAccessKeys) {
+  HarmonyIsolate isolate;
+  HandleScope scope(isolate.GetIsolate());
+  LocalContext context;
+  Handle<Object> instance = CreateAccessCheckedObject(
+      BlockAccessKeys, IndexedAccessAlwaysAllowed);
+  CompileRun("var records = null;"
+             "var objNoCheck = {};"
+             "var observer = function(r) { records = r };"
+             "var blacklist = {__block_access_keys: true};"
+             "Object.observe(obj, observer);"
+             "Object.observe(objNoCheck, observer);");
+  Handle<Value> obj_no_check = CompileRun("objNoCheck");
+  {
+    LocalContext context2;
+    context2->Global()->Set(String::New("obj"), instance);
+    context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+    CompileRun("var records2 = null;"
+               "var observer2 = function(r) { records2 = r };"
+               "Object.observe(obj, observer2);"
+               "Object.observe(objNoCheck, observer2);"
+               "obj.foo = 'bar';"
+               "obj[5] = 'baz';"
+               "objNoCheck.baz = 'quux'");
+    const RecordExpectation expected_records2[] = {
+      { instance, "new", "foo", Handle<Value>() },
+      { instance, "new", "5", Handle<Value>() },
+      { obj_no_check, "new", "baz", Handle<Value>() },
+    };
+    EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+  }
+  const RecordExpectation expected_records[] = {
+    { obj_no_check, "new", "baz", Handle<Value>() }
+  };
+  EXPECT_RECORDS(CompileRun("records"), expected_records);
+}
+
+
+TEST(AccessCheckDisallowApiModifications) {
+  HarmonyIsolate isolate;
+  HandleScope scope(isolate.GetIsolate());
+  LocalContext context;
+  Handle<Object> instance = CreateAccessCheckedObject(
+      BlockAccessKeys, IndexedAccessAlwaysAllowed);
+  CompileRun("var records = null;"
+             "var observer = function(r) { records = r };"
+             "var blacklist = {__block_access_keys: true};"
+             "Object.observe(obj, observer);");
+  {
+    LocalContext context2;
+    context2->Global()->Set(String::New("obj"), instance);
+    CompileRun("var records2 = null;"
+               "var observer2 = function(r) { records2 = r };"
+               "Object.observe(obj, observer2);");
+    instance->Set(5, String::New("bar"));
+    instance->Set(String::New("foo"), String::New("bar"));
+    CompileRun("");  // trigger delivery
+    const RecordExpectation expected_records2[] = {
+      { instance, "new", "5", Handle<Value>() },
+      { instance, "new", "foo", Handle<Value>() }
+    };
+    EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+  }
+  CHECK(CompileRun("records")->IsNull());
+}
diff --git a/test/mjsunit/harmony/object-observe.js b/test/mjsunit/harmony/object-observe.js
index 830eb1b..75f0ff8 100644
--- a/test/mjsunit/harmony/object-observe.js
+++ b/test/mjsunit/harmony/object-observe.js
@@ -145,13 +145,8 @@
 assertThrows(function() { notifier.performChange(undefined, function(){}); }, TypeError);
 assertThrows(function() { notifier.performChange('foo', undefined); }, TypeError);
 assertThrows(function() { notifier.performChange('foo', 'bar'); }, TypeError);
-var testSelf = {};
 notifier.performChange('foo', function() {
-  assertTrue(testSelf === this);
-}, testSelf);
-var self = this;
-notifier.performChange('foo', function() {
-  assertTrue(self === this);
+  assertEquals(undefined, this);
 });
 
 var notify = notifier.notify;
@@ -400,10 +395,11 @@
   increment: function(amount) {
     var notifier = Object.getNotifier(this);
 
+    var self = this;
     notifier.performChange(Thingy.INCREMENT, function() {
-      this.a += amount;
-      this.b += amount;
-    }, this);
+      self.a += amount;
+      self.b += amount;
+    });
 
     notifier.notify({
       object: this,
@@ -415,10 +411,11 @@
   multiply: function(amount) {
     var notifier = Object.getNotifier(this);
 
+    var self = this;
     notifier.performChange(Thingy.MULTIPLY, function() {
-      this.a *= amount;
-      this.b *= amount;
-    }, this);
+      self.a *= amount;
+      self.b *= amount;
+    });
 
     notifier.notify({
       object: this,
@@ -430,10 +427,11 @@
   incrementAndMultiply: function(incAmount, multAmount) {
     var notifier = Object.getNotifier(this);
 
+    var self = this;
     notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() {
-      this.increment(incAmount);
-      this.multiply(multAmount);
-    }, this);
+      self.increment(incAmount);
+      self.multiply(multAmount);
+    });
 
     notifier.notify({
       object: this,
@@ -505,10 +503,11 @@
     if (!n)
       return;
     var notifier = Object.getNotifier(this);
+    var self = this;
     notifier.performChange(RecursiveThingy.MULTIPLY_FIRST_N, function() {
-      this[n-1] = this[n-1]*amount;
-      this.multiplyFirstN(amount, n-1);
-    }, this);
+      self[n-1] = self[n-1]*amount;
+      self.multiplyFirstN(amount, n-1);
+    });
 
     notifier.notify({
       object: this,
@@ -557,18 +556,19 @@
 
   shuffle: function() {
     var notifier = Object.getNotifier(this);
+    var self = this;
     notifier.performChange(DeckSuit.SHUFFLE, function() {
-      this.reverse();
-      this.sort(function() { return Math.random()* 2 - 1; });
-      var cut = this.splice(0, 6);
-      Array.prototype.push.apply(this, cut);
-      this.reverse();
-      this.sort(function() { return Math.random()* 2 - 1; });
-      var cut = this.splice(0, 6);
-      Array.prototype.push.apply(this, cut);
-      this.reverse();
-      this.sort(function() { return Math.random()* 2 - 1; });
-    }, this);
+      self.reverse();
+      self.sort(function() { return Math.random()* 2 - 1; });
+      var cut = self.splice(0, 6);
+      Array.prototype.push.apply(self, cut);
+      self.reverse();
+      self.sort(function() { return Math.random()* 2 - 1; });
+      var cut = self.splice(0, 6);
+      Array.prototype.push.apply(self, cut);
+      self.reverse();
+      self.sort(function() { return Math.random()* 2 - 1; });
+    });
 
     notifier.notify({
       object: this,
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 5d4933a..4f629ff 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -336,6 +336,7 @@
         '../../src/heap-snapshot-generator.h',
         '../../src/heap.cc',
         '../../src/heap.h',
+        '../../src/hydrogen-alias-analysis.h',
         '../../src/hydrogen-bce.cc',
         '../../src/hydrogen-bce.h',
         '../../src/hydrogen-bch.cc',
diff --git a/tools/run-tests.py b/tools/run-tests.py
index 4f212d6..48682d4 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -293,7 +293,7 @@
   if timeout == -1:
     # Simulators are slow, therefore allow a longer default timeout.
     if arch in SLOW_ARCHS:
-      timeout = 3 * TIMEOUT_DEFAULT;
+      timeout = 2 * TIMEOUT_DEFAULT;
     else:
       timeout = TIMEOUT_DEFAULT;
 
diff --git a/tools/v8heapconst.py b/tools/v8heapconst.py
index a4335a0..1f72c37 100644
--- a/tools/v8heapconst.py
+++ b/tools/v8heapconst.py
@@ -250,6 +250,6 @@
   ("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
   ("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
   ("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
-  ("CODE_SPACE", 0x11ce1): "JsConstructEntryCode",
-  ("CODE_SPACE", 0x193e1): "JsEntryCode",
+  ("CODE_SPACE", 0x11141): "JsConstructEntryCode",
+  ("CODE_SPACE", 0x18da1): "JsEntryCode",
 }