Fixed bug in JSObject::GetPropertyAttributePostInterceptor where map transitions would count as properties.

Allowed aliased eval invocations by treating them as evals in the global context. This may change in the future.

Added support for accessing the last entered context through the API and renamed Context::Current to Context::GetCurrent and Context::GetSecurityContext to Context::GetCurrentSecurityContext.

Fixed bug in the debugger that would cause the debugger scripts to be recursively loaded and changed all disabling of interrupts to be block-structured.

Made snapshot data read-only to allow it to be more easily shared across multiple users of V8 when linked as a shared library.


git-svn-id: http://v8.googlecode.com/svn/trunk@6 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 884bed4..a4d4e4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2008-07-25: Version 0.1.3 (128832)
+
+        Fixed bug in JSObject::GetPropertyAttributePostInterceptor where
+        map transitions would count as properties.
+
+        Allowed aliased eval invocations by treating them as evals in the
+        global context. This may change in the future.
+
+        Added support for accessing the last entered context through the
+        API and renamed Context::Current to Context::GetCurrent and
+        Context::GetSecurityContext to Context::GetCurrentSecurityContext.
+
+        Fixed bug in the debugger that would cause the debugger scripts to
+        be recursively loaded and changed all disabling of interrupts to
+        be block-structured.
+
+        Made snapshot data read-only to allow it to be more easily shared
+        across multiple users of V8 when linked as a shared library.
+
+
 2008-07-16: Version 0.1.2 (127441)
 
         Fixed building on Mac OS X by recognizing i386 and friends as
diff --git a/public/v8.h b/public/v8.h
index 256d5ba..63d2e06 100644
--- a/public/v8.h
+++ b/public/v8.h
@@ -1779,11 +1779,14 @@
                                      Handle<ObjectTemplate>(),
                                  Handle<Value> global_object = Handle<Value>());
 
-  /** Returns the context that is on the top of the stack.*/
-  static Local<Context> Current();
+  /** Returns the last entered context. */
+  static Local<Context> GetEntered();
 
-  /** Returns the security context used to start JS execution.*/
-  static Local<Context> GetSecurityContext();
+  /** Returns the context that is on the top of the stack. */
+  static Local<Context> GetCurrent();
+
+  /** Returns the security context that is currently used. */
+  static Local<Context> GetCurrentSecurityContext();
 
   /**
    * Sets the security token for the context.  To access an object in
diff --git a/src/api.cc b/src/api.cc
index 5f1a94c..f346cc1 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -403,11 +403,12 @@
 void Context::Enter() {
   if (IsDeadCheck("v8::Context::Enter()")) return;
   i::Handle<i::Context> env = Utils::OpenHandle(this);
+  thread_local.EnterContext(env);
 
-  thread_local.AddEnteredContext(i::GlobalHandles::Create(i::Top::context()));
+  thread_local.SaveContext(i::GlobalHandles::Create(i::Top::context()));
   i::Top::set_context(*env);
 
-  thread_local.AddSecurityContext(
+  thread_local.SaveSecurityContext(
       i::GlobalHandles::Create(i::Top::security_context()));
   i::Top::set_security_context(*env);
 }
@@ -415,14 +416,19 @@
 
 void Context::Exit() {
   if (has_shut_down) return;
+  if (!ApiCheck(thread_local.LeaveLastContext(),
+                "v8::Context::Exit()",
+                "Cannot exit non-entered context")) {
+    return;
+  }
 
   // Content of 'last_context' and 'last_security_context' could be NULL.
-  i::Handle<i::Object> last_context = thread_local.RemoveLastEnteredContext();
+  i::Handle<i::Object> last_context = thread_local.RestoreContext();
   i::Top::set_context(static_cast<i::Context*>(*last_context));
   i::GlobalHandles::Destroy(last_context.location());
 
   i::Handle<i::Object> last_security_context =
-      thread_local.RemoveLastSecurityContext();
+      thread_local.RestoreSecurityContext();
   i::Top::set_security_context(
       static_cast<i::Context*>(*last_security_context));
   i::GlobalHandles::Destroy(last_security_context.location());
@@ -2145,16 +2151,26 @@
 }
 
 
-v8::Local<v8::Context> Context::Current() {
-  if (IsDeadCheck("v8::Context::Current()")) return Local<Context>();
+v8::Local<v8::Context> Context::GetEntered() {
+  if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
+  i::Handle<i::Object> last = thread_local.LastEnteredContext();
+  if (last.is_null()) return Local<Context>();
+  i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
+  return Utils::ToLocal(context);
+}
+
+
+v8::Local<v8::Context> Context::GetCurrent() {
+  if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
   i::Handle<i::Context> context(i::Top::global_context());
   return Utils::ToLocal(context);
 }
 
 
-v8::Local<v8::Context> Context::GetSecurityContext() {
-  if (IsDeadCheck("v8::Context::GetSecurityContext()")) return Local<Context>();
-  ASSERT(i::Top::security_context() != NULL);
+v8::Local<v8::Context> Context::GetCurrentSecurityContext() {
+  if (IsDeadCheck("v8::Context::GetCurrentSecurityContext()")) {
+    return Local<Context>();
+  }
   i::Handle<i::Context> context(i::Top::security_context());
   return Utils::ToLocal(context);
 }
diff --git a/src/api.h b/src/api.h
index 6975e57..45701dc 100644
--- a/src/api.h
+++ b/src/api.h
@@ -345,15 +345,17 @@
 
   HandleScopeImplementer()
       : blocks(0),
-        entered_contexts(0),
-        security_contexts(0) {
+        entered_contexts_(0),
+        saved_contexts_(0),
+        saved_security_contexts_(0) {
     Initialize();
   }
 
   void Initialize() {
     blocks.Initialize(0);
-    entered_contexts.Initialize(0);
-    security_contexts.Initialize(0);
+    entered_contexts_.Initialize(0);
+    saved_contexts_.Initialize(0);
+    saved_security_contexts_.Initialize(0);
     spare = NULL;
     ignore_out_of_memory = false;
     call_depth = 0;
@@ -378,12 +380,20 @@
   inline void DecrementCallDepth() {call_depth--;}
   inline bool CallDepthIsZero() { return call_depth == 0; }
 
-  inline void AddEnteredContext(Handle<Object>);
-  inline Handle<Object> RemoveLastEnteredContext();
-  inline bool HasEnteredContexts();
-  inline void AddSecurityContext(Handle<Object>);
-  inline Handle<Object> RemoveLastSecurityContext();
-  inline bool HasSecurityContexts();
+  inline void EnterContext(Handle<Object> context);
+  inline bool LeaveLastContext();
+
+  // Returns the last entered context or an empty handle if no
+  // contexts have been entered.
+  inline Handle<Object> LastEnteredContext();
+
+  inline void SaveContext(Handle<Object> context);
+  inline Handle<Object> RestoreContext();
+  inline bool HasSavedContexts();
+
+  inline void SaveSecurityContext(Handle<Object> context);
+  inline Handle<Object> RestoreSecurityContext();
+  inline bool HasSavedSecurityContexts();
 
   inline List<void**>* Blocks() { return &blocks; }
 
@@ -394,10 +404,12 @@
   List<void**> blocks;
   Object** spare;
   int call_depth;
-  // Used as a stack to keep track of contexts entered.
-  List<Handle<Object> > entered_contexts;
-  // Used as a stack to keep track of security contexts entered.
-  List<Handle<Object> > security_contexts;
+  // Used as a stack to keep track of entered contexts.
+  List<Handle<Object> > entered_contexts_;
+  // Used as a stack to keep track of saved contexts.
+  List<Handle<Object> > saved_contexts_;
+  // Used as a stack to keep track of saved security contexts.
+  List<Handle<Object> > saved_security_contexts_;
   bool ignore_out_of_memory;
   // This is only used for threading support.
   ImplementationUtilities::HandleScopeData handle_scope_data_;
@@ -415,32 +427,51 @@
 static const int kHandleBlockSize = v8::internal::KB - 2;  // fit in one page
 
 
-void HandleScopeImplementer::AddEnteredContext(Handle<Object> context) {
-  entered_contexts.Add(context);
+void HandleScopeImplementer::SaveContext(Handle<Object> context) {
+  saved_contexts_.Add(context);
 }
 
 
-Handle<Object> HandleScopeImplementer::RemoveLastEnteredContext() {
-  return entered_contexts.RemoveLast();
+Handle<Object> HandleScopeImplementer::RestoreContext() {
+  return saved_contexts_.RemoveLast();
 }
 
 
-bool HandleScopeImplementer::HasEnteredContexts() {
-  return !entered_contexts.is_empty();
-}
-
-void HandleScopeImplementer::AddSecurityContext(Handle<Object> context) {
-  security_contexts.Add(context);
+bool HandleScopeImplementer::HasSavedContexts() {
+  return !saved_contexts_.is_empty();
 }
 
 
-Handle<Object> HandleScopeImplementer::RemoveLastSecurityContext() {
-  return security_contexts.RemoveLast();
+void HandleScopeImplementer::SaveSecurityContext(Handle<Object> context) {
+  saved_security_contexts_.Add(context);
 }
 
 
-bool HandleScopeImplementer::HasSecurityContexts() {
-  return !security_contexts.is_empty();
+Handle<Object> HandleScopeImplementer::RestoreSecurityContext() {
+  return saved_security_contexts_.RemoveLast();
+}
+
+
+bool HandleScopeImplementer::HasSavedSecurityContexts() {
+  return !saved_security_contexts_.is_empty();
+}
+
+
+void HandleScopeImplementer::EnterContext(Handle<Object> context) {
+  entered_contexts_.Add(context);
+}
+
+
+bool HandleScopeImplementer::LeaveLastContext() {
+  if (entered_contexts_.is_empty()) return false;
+  entered_contexts_.RemoveLast();
+  return true;
+}
+
+
+Handle<Object> HandleScopeImplementer::LastEnteredContext() {
+  if (entered_contexts_.is_empty()) return Handle<Object>::null();
+  return entered_contexts_.last();
 }
 
 
diff --git a/src/ast.cc b/src/ast.cc
index 232bfad..6296f95 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -83,7 +83,6 @@
   // non-const) multiple variable declarations, const vars introduced via
   // eval() etc.  Const-ness and variable declarations are a complete mess
   // in JS. Sigh...
-  // ASSERT(var->mode() == Variable::CONST || !is_const());
   var_ = var;
   var->var_uses()->RecordUses(&var_uses_);
   var->obj_uses()->RecordUses(&obj_uses_);
diff --git a/src/compiler.cc b/src/compiler.cc
index 48502ca..fb11bf8 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -112,7 +112,7 @@
 
   // Make sure we have an initial stack limit.
   StackGuard guard;
-  StackGuard::DisableInterrupts();
+  PostponeInterruptsScope postpone;
 
   // Notify debugger
   Debugger::OnBeforeCompile(script);
@@ -126,7 +126,6 @@
   // Check for parse errors.
   if (lit == NULL) {
     ASSERT(Top::has_pending_exception());
-    StackGuard::EnableInterrupts();
     return Handle<JSFunction>::null();
   }
 
@@ -144,7 +143,6 @@
   // Check for stack-overflow exceptions.
   if (code.is_null()) {
     Top::StackOverflow();
-    StackGuard::EnableInterrupts();
     return Handle<JSFunction>::null();
   }
 
@@ -172,8 +170,6 @@
   // the instances of the function.
   SetExpectedNofPropertiesFromEstimate(fun, lit->expected_property_count());
 
-  StackGuard::EnableInterrupts();
-
   // Notify debugger
   Debugger::OnAfterCompile(script, fun);
 
@@ -242,7 +238,7 @@
 
   // Make sure we have an initial stack limit.
   StackGuard guard;
-  StackGuard::DisableInterrupts();
+  PostponeInterruptsScope postpone;
 
   // Compute name, source code and script data.
   Handle<String> name(String::cast(shared->name()));
@@ -263,7 +259,6 @@
   // Check for parse errors.
   if (lit == NULL) {
     ASSERT(Top::has_pending_exception());
-    StackGuard::EnableInterrupts();
     return false;
   }
 
@@ -278,7 +273,6 @@
   // Check for stack-overflow exception.
   if (code.is_null()) {
     Top::StackOverflow();
-    StackGuard::EnableInterrupts();
     return false;
   }
 
@@ -293,7 +287,6 @@
 
   // Check the function has compiled code.
   ASSERT(shared->is_compiled());
-  StackGuard::EnableInterrupts();
   return true;
 }
 
diff --git a/src/debug.cc b/src/debug.cc
index e7f5ee2..a5401ed 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -530,10 +530,12 @@
 bool Debug::CompileDebuggerScript(int index) {
   HandleScope scope;
 
-  // Find source and name for the requested script.
+  // Bail out if the index is invalid.
   if (index == -1) {
     return false;
   }
+
+  // Find source and name for the requested script.
   Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
   Vector<const char> name = Natives::GetScriptName(index);
   Handle<String> script_name = Factory::NewStringFromAscii(name);
@@ -552,26 +554,25 @@
     return false;
   }
 
-  // Execute the boilerplate function in the global object for the supplied
-  // context.
-  bool caught_exception = false;
+  // Execute the boilerplate function in the debugger context.
   Handle<Context> context = Top::global_context();
-  Handle<JSFunction> debug_fun(Factory::NewFunctionFromBoilerplate(boilerplate,
-                                                                   context));
-  Handle<GlobalObject> debug_global(context->global());
-  Handle<Object> result = Execution::TryCall(debug_fun, debug_global,
-                                             0, NULL, &caught_exception);
+  bool caught_exception = false;
+  Handle<JSFunction> function =
+      Factory::NewFunctionFromBoilerplate(boilerplate, context);
+  Handle<Object> result =
+      Execution::TryCall(function, Handle<Object>(context->global()),
+                         0, NULL, &caught_exception);
+
+  // Check for caught exceptions.
   if (caught_exception) {
-    MessageHandler::ReportMessage("error_loading_debugger",
-                                  NULL,
+    MessageHandler::ReportMessage("error_loading_debugger", NULL,
                                   HandleVector<Object>(&result, 1));
     return false;
   }
 
-  // Mark this script as native.
-  Handle<Script> script(Script::cast(debug_fun->shared()->script()));
+  // Mark this script as native and return successfully.
+  Handle<Script> script(Script::cast(function->shared()->script()));
   script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
-
   return true;
 }
 
@@ -580,39 +581,44 @@
   // Return if debugger is already loaded.
   if (IsLoaded()) return true;
 
+  // Bail out if we're already in the process of compiling the native
+  // JavaScript source code for the debugger.
+  if (Debugger::compiling_natives()) return false;
+
+  // Disable breakpoints and interrupts while compiling and running the
+  // debugger scripts including the context creation code.
+  DisableBreak disable(true);
+  PostponeInterruptsScope postpone;
+
   // Create the debugger context.
   HandleScope scope;
-  Handle<Object> empty_global_object;
-  Handle<Context> debug_context;
-  v8::Handle<v8::ObjectTemplate> global_template =
-      v8::Handle<v8::ObjectTemplate>();
-  debug_context = Bootstrapper::CreateEnvironment(empty_global_object,
-                                                  global_template,
-                                                  NULL);
+  Handle<Context> context =
+      Bootstrapper::CreateEnvironment(Handle<Object>::null(),
+                                      v8::Handle<ObjectTemplate>(),
+                                      NULL);
 
-  // Enter the debugger context.
+  // Use the debugger context.
   SaveContext save;
-  Top::set_context(*debug_context);
-  Top::set_security_context(*debug_context);
+  Top::set_context(*context);
+  Top::set_security_context(*context);
+
+  // Expose the builtins object in the debugger context.
+  Handle<String> key = Factory::LookupAsciiSymbol("builtins");
+  Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
+  SetProperty(global, key, Handle<Object>(global->builtins()), NONE);
 
   // Compile the JavaScript for the debugger in the debugger context.
   Debugger::set_compiling_natives(true);
-  if (!CompileDebuggerScript(Natives::GetIndex("mirror"))) {
-    return false;
-  };
-  if (!CompileDebuggerScript(Natives::GetIndex("debug"))) {
-    return false;
-  };
+  bool caught_exception =
+      !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
+      !CompileDebuggerScript(Natives::GetIndex("debug"));
   Debugger::set_compiling_natives(false);
 
-  // Expose the builtins object in the debugger context.
-  Handle<String> builtins_string = Factory::LookupAsciiSymbol("builtins");
-  Handle<JSGlobalObject> global(JSGlobalObject::cast(debug_context->global()));
-  SetProperty(global, builtins_string,
-              Handle<JSObject>(global->builtins()), NONE);
+  // Check for caught exceptions.
+  if (caught_exception) return false;
 
   // Debugger loaded.
-  debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*debug_context));
+  debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
   return true;
 }
 
@@ -654,8 +660,8 @@
   SaveBreakFrame save;
   EnterDebuggerContext enter;
 
-  // Deactivate interrupt during breakpoint processing.
-  StackGuard::DisableInterrupts();
+  // Postpone interrupt during breakpoint processing.
+  PostponeInterruptsScope postpone;
 
   // Get the debug info (create it if it does not exist).
   Handle<SharedFunctionInfo> shared =
@@ -707,9 +713,6 @@
     PrepareStep(step_action, step_count);
   }
 
-  // Reactivate interrupt.
-  StackGuard::EnableInterrupts();
-
   // Install jump to the call address which was overwritten.
   SetAfterBreakTarget(frame);
 
@@ -1344,8 +1347,8 @@
     pending_requests_tail_ = pending_request;
   }
 
-  // Use the stack guard to signal the debug request.
-  StackGuard::DebugBreak();
+  // Set the pending request flag to force the VM to stop soon.
+  v8::Debug::DebugBreak();
 }
 
 
@@ -1517,7 +1520,7 @@
 
 bool Debugger::IsPlainBreakRequest(Handle<Object> request) {
   // Get the function IsPlainBreakRequest (defined in debug.js).
-  Handle<JSFunction> process_denbug_request =
+  Handle<JSFunction> process_debug_request =
     Handle<JSFunction>(JSFunction::cast(
     Debug::debug_context()->global()->GetProperty(
         *Factory::LookupAsciiSymbol("IsPlainBreakRequest"))));
@@ -1526,7 +1529,7 @@
   bool caught_exception;
   const int argc = 1;
   Object** argv[argc] = { request.location() };
-  Handle<Object> result = Execution::TryCall(process_denbug_request,
+  Handle<Object> result = Execution::TryCall(process_debug_request,
                                              Factory::undefined_value(),
                                              argc, argv,
                                              &caught_exception);
@@ -1962,8 +1965,8 @@
 }
 
 
-// This method is called by the V8 thread whenever a debug event occours in the
-// vm.
+// This method is called by the V8 thread whenever a debug event occurs in
+// the VM.
 void DebugMessageThread::DebugEvent(v8::DebugEvent event,
                                     Handle<Object> exec_state,
                                     Handle<Object> event_data) {
diff --git a/src/execution.cc b/src/execution.cc
index 6e97c35..e1d46e5 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -75,7 +75,8 @@
     code = stub.GetCode();
   }
 
-  {  // Save and restore context around invocation and block the
+  {
+    // Save and restore context around invocation and block the
     // allocation of handles without explicit handle scopes.
     SaveContext save;
     NoHandleAllocation na;
@@ -296,6 +297,7 @@
   return thread_local_.interrupt_flags_ & DEBUGBREAK;
 }
 
+
 void StackGuard::DebugBreak() {
   ExecutionAccess access;
   if (!Top::is_break_no_lock()) {
diff --git a/src/execution.h b/src/execution.h
index 4bd07fb..27a4c9c 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -147,8 +147,6 @@
   static int ArchiveSpacePerThread();
 
   static bool IsStackOverflow();
-  static void EnableInterrupts();
-  static void DisableInterrupts();
   static bool IsPreempted();
   static void Preempt();
   static bool IsInterrupted();
@@ -186,6 +184,10 @@
     }
   }
 
+  // Enable or disable interrupts.
+  static void EnableInterrupts();
+  static void DisableInterrupts();
+
   static const int kLimitSize = 512 * KB;
   static const uintptr_t kInterruptLimit = 0xfffffffe;
   static const uintptr_t kIllegalLimit = 0xffffffff;
@@ -198,16 +200,21 @@
        initial_climit_(kIllegalLimit),
        climit_(kIllegalLimit),
        nesting_(0),
+       postpone_interrupts_nesting_(0),
        interrupt_flags_(0) {}
     uintptr_t initial_jslimit_;
     uintptr_t jslimit_;
     uintptr_t initial_climit_;
     uintptr_t climit_;
     int nesting_;
+    int postpone_interrupts_nesting_;
     int interrupt_flags_;
   };
+
   static ThreadLocal thread_local_;
+
   friend class StackLimitCheck;
+  friend class PostponeInterruptsScope;
 };
 
 
@@ -220,6 +227,25 @@
 };
 
 
+// Support for temporarily postponing interrupts. When the outermost
+// postpone scope is left the interrupts will be re-enabled and any
+// interrupts that occured while in the scope will be taken into
+// account.
+class PostponeInterruptsScope BASE_EMBEDDED {
+ public:
+  PostponeInterruptsScope() {
+    StackGuard::thread_local_.postpone_interrupts_nesting_++;
+    StackGuard::DisableInterrupts();
+  }
+
+  ~PostponeInterruptsScope() {
+    if (--StackGuard::thread_local_.postpone_interrupts_nesting_ == 0) {
+      StackGuard::EnableInterrupts();
+    }
+  }
+};
+
+
 class PrintExtension : public v8::Extension {
  public:
   PrintExtension() : v8::Extension("v8/print", kSource) { }
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 0e3d750..2344305 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -132,7 +132,7 @@
   fprintf(f, "#include \"platform.h\"\n\n");
   fprintf(f, "#include \"snapshot.h\"\n\n");
   fprintf(f, "namespace v8 {\nnamespace internal {\n\n");
-  fprintf(f, "char Snapshot::data_[] = {");
+  fprintf(f, "const char Snapshot::data_[] = {");
   int written = 0;
   written += fprintf(f, "%i", str[0]);
   for (int i = 1; i < size; ++i) {
diff --git a/src/objects.cc b/src/objects.cc
index ab40bb6..59bbfa1 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -348,7 +348,7 @@
     if (current == last) break;
   }
 
-  if (!result->IsValid()) {
+  if (!result->IsProperty()) {
     *attributes = ABSENT;
     return Heap::undefined_value();
   }
@@ -378,17 +378,14 @@
                                      result->GetCallbackObject(),
                                      name,
                                      holder);
-    case MAP_TRANSITION:
-    case CONSTANT_TRANSITION:
-      *attributes = ABSENT;
-      return Heap::undefined_value();
     case INTERCEPTOR: {
       JSObject* recvr = JSObject::cast(receiver);
       return holder->GetPropertyWithInterceptor(recvr, name, attributes);
     }
+    default:
+      UNREACHABLE();
+      return NULL;
   }
-  UNREACHABLE();
-  return NULL;
 }
 
 
@@ -1571,7 +1568,7 @@
   // Check local property, ignore interceptor.
   LookupResult result;
   LocalLookupRealNamedProperty(name, &result);
-  if (result.IsValid()) return result.GetAttributes();
+  if (result.IsProperty()) return result.GetAttributes();
 
   if (continue_search) {
     // Continue searching via the prototype chain.
diff --git a/src/runtime.cc b/src/runtime.cc
index 2d9e498..2e3025b 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2988,8 +2988,8 @@
 
 
 static Object* Runtime_DebugBreak(Arguments args) {
-  // Just continue if breaks are disabled.
-  if (Debug::disable_break()) {
+  // Just continue if breaks are disabled or if we fail to load the debugger.
+  if (Debug::disable_break() || !Debug::Load()) {
     return args[0];
   }
 
@@ -3009,11 +3009,6 @@
   // Clear the debug request flag.
   StackGuard::Continue(DEBUGBREAK);
 
-  // Make sure debugger is loaded.
-  if (!Debug::Load()) {
-    return args[0];
-  }
-
   HandleScope scope;
   SaveBreakFrame save;
   EnterDebuggerContext enter;
@@ -3309,13 +3304,15 @@
   StackFrameLocator locator;
   JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
 
-  // Check if the caller of eval() supports eval. If not, eval is
-  // called through an alias in which case we throw an EvalError.
+  // TODO(900055): Right now we check if the caller of eval() supports
+  // eval to determine if it's an aliased eval or not. This may not be
+  // entirely correct in the unlikely case where a function uses both
+  // aliased and direct eval calls.
   HandleScope scope;
   if (!ScopeInfo<>::SupportsEval(frame->FindCode())) {
-    Handle<Object> error =
-        Factory::NewEvalError("illegal_eval", HandleVector<Object>(NULL, 0));
-    return Top::Throw(*error);
+    // Aliased eval: Evaluate in the global context of the eval
+    // function to support aliased, cross environment evals.
+    return *Top::global_context();
   }
 
   // Fetch the caller context from the frame.
@@ -4885,6 +4882,9 @@
 }
 
 
+#ifdef DEBUG
+// ListNatives is ONLY used by the fuzz-natives.js in debug mode
+// Exclude the code in release mode.
 static Object* Runtime_ListNatives(Arguments args) {
   ASSERT(args.length() == 1);
   HandleScope scope;
@@ -4904,6 +4904,7 @@
 #undef ADD_ENTRY
   return *result;
 }
+#endif
 
 
 static Object* Runtime_IS_VAR(Arguments args) {
diff --git a/src/runtime.h b/src/runtime.h
index 8ea552a..e46ff47 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -33,11 +33,11 @@
 // The interface to C++ runtime functions.
 
 // ----------------------------------------------------------------------------
-// RUNTIME_FUNCTION_LIST defines all runtime functions accessed
-// either directly by id (via the code generator), or indirectly
-// via a native call by name (from within JS code).
+// RUNTIME_FUNCTION_LIST_ALWAYS defines runtime calls available in both
+// release and debug mode.
+// This macro should only be used by the macro RUNTIME_FUNCTION_LIST.
 
-#define RUNTIME_FUNCTION_LIST(F) \
+#define RUNTIME_FUNCTION_LIST_ALWAYS(F) \
   /* Property access */ \
   F(AddProperty, 4) \
   F(GetProperty, 2) \
@@ -279,13 +279,28 @@
   F(FunctionGetAssemblerCode, 1) \
   F(Abort, 2) \
   \
-  /* Testing */ \
-  F(ListNatives, 1) \
-  \
   /* Pseudo functions - handled as macros by parser */ \
   F(IS_VAR, 1)
 
 
+#ifdef DEBUG
+#define RUNTIME_FUNCTION_LIST_DEBUG(F) \
+  /* Testing */ \
+  F(ListNatives, 1)
+#else
+#define RUNTIME_FUNCTION_LIST_DEBUG(F)
+#endif
+
+
+// ----------------------------------------------------------------------------
+// RUNTIME_FUNCTION_LIST defines all runtime functions accessed
+// either directly by id (via the code generator), or indirectly
+// via a native call by name (from within JS code).
+
+#define RUNTIME_FUNCTION_LIST(F) \
+  RUNTIME_FUNCTION_LIST_ALWAYS(F) \
+  RUNTIME_FUNCTION_LIST_DEBUG(F)
+
 // ----------------------------------------------------------------------------
 // Runtime provides access to all C++ runtime functions.
 
diff --git a/src/serialize.cc b/src/serialize.cc
index 4f40232..0d5f129 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -921,17 +921,18 @@
 
 
 void Serializer::PutContextStack() {
-  List<Handle<Object> > entered_contexts(2);
-  while (HandleScopeImplementer::instance()->HasEnteredContexts()) {
+  List<Handle<Object> > contexts(2);
+  while (HandleScopeImplementer::instance()->HasSavedContexts()) {
     Handle<Object> context =
-      HandleScopeImplementer::instance()->RemoveLastEnteredContext();
-    entered_contexts.Add(context);
+      HandleScopeImplementer::instance()->RestoreContext();
+    contexts.Add(context);
   }
-  PutGlobalHandleStack(entered_contexts);
+  PutGlobalHandleStack(contexts);
+
   List<Handle<Object> > security_contexts(2);
-  while (HandleScopeImplementer::instance()->HasSecurityContexts()) {
+  while (HandleScopeImplementer::instance()->HasSavedSecurityContexts()) {
     Handle<Object> context =
-      HandleScopeImplementer::instance()->RemoveLastSecurityContext();
+      HandleScopeImplementer::instance()->RestoreSecurityContext();
     security_contexts.Add(context);
   }
   PutGlobalHandleStack(security_contexts);
@@ -1049,7 +1050,7 @@
 static const int kInitArraySize = 32;
 
 
-Deserializer::Deserializer(char* str, int len)
+Deserializer::Deserializer(const char* str, int len)
   : reader_(str, len),
     map_pages_(kInitArraySize), old_pages_(kInitArraySize),
     code_pages_(kInitArraySize), large_objects_(kInitArraySize),
@@ -1254,13 +1255,13 @@
   List<Handle<Object> > entered_contexts(2);
   GetGlobalHandleStack(&entered_contexts);
   for (int i = 0; i < entered_contexts.length(); i++) {
-    HandleScopeImplementer::instance()->AddEnteredContext(entered_contexts[i]);
+    HandleScopeImplementer::instance()->SaveContext(entered_contexts[i]);
   }
   List<Handle<Object> > security_contexts(2);
   GetGlobalHandleStack(&security_contexts);
   for (int i = 0; i < security_contexts.length(); i++) {
     HandleScopeImplementer::instance()->
-      AddSecurityContext(security_contexts[i]);
+      SaveSecurityContext(security_contexts[i]);
   }
 }
 
diff --git a/src/serialize.h b/src/serialize.h
index 5997d37..5085b7e 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -202,7 +202,7 @@
 
 class SnapshotReader {
  public:
-  SnapshotReader(char* str, int len): str_(str), end_(str + len) {}
+  SnapshotReader(const char* str, int len): str_(str), end_(str + len) {}
 
   void ExpectC(char expected) {
     int c = GetC();
@@ -216,7 +216,7 @@
   }
 
   int GetInt() {
-    int result = *reinterpret_cast<int*>(str_);
+    int result = *reinterpret_cast<const int*>(str_);
     str_ += sizeof(result);
     return result;
   }
@@ -238,8 +238,8 @@
   }
 
  private:
-  char* str_;
-  char* end_;
+  const char* str_;
+  const char* end_;
 };
 
 
@@ -249,7 +249,7 @@
  public:
   // Create a deserializer. The snapshot is held in str and has size len.
   // Ownership of str is not assumed by the Deserializer.
-  Deserializer(char* str, int len);
+  Deserializer(const char* str, int len);
 
   virtual ~Deserializer();
 
diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc
index ba15fd5..314a5f0 100644
--- a/src/snapshot-common.cc
+++ b/src/snapshot-common.cc
@@ -35,7 +35,7 @@
 
 namespace v8 { namespace internal {
 
-bool Snapshot::Deserialize(char* content, int len) {
+bool Snapshot::Deserialize(const char* content, int len) {
   Deserializer des(content, len);
   des.GetFlags();
   return V8::Initialize(&des);
diff --git a/src/snapshot-empty.cc b/src/snapshot-empty.cc
index c015d86..909a223 100644
--- a/src/snapshot-empty.cc
+++ b/src/snapshot-empty.cc
@@ -33,7 +33,7 @@
 
 namespace v8 { namespace internal {
 
-char Snapshot::data_[] = { 0 };
+const char Snapshot::data_[] = { 0 };
 int Snapshot::size_ = 0;
 
 } }  // namespace v8::internal
diff --git a/src/snapshot.h b/src/snapshot.h
index ebc578f..bb40c2e 100644
--- a/src/snapshot.h
+++ b/src/snapshot.h
@@ -45,10 +45,10 @@
   static bool WriteToFile(const char* snapshot_file);
 
  private:
-  static char data_[];
+  static const char data_[];
   static int size_;
 
-  static bool Deserialize(char* content, int len);
+  static bool Deserialize(const char* content, int len);
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
 };