Fixed bug in JSObject::GetPropertyAttributePostInterceptor where map transitions...
authorkasper.lund <kasper.lund@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 25 Jul 2008 07:37:58 +0000 (07:37 +0000)
committerkasper.lund <kasper.lund@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 25 Jul 2008 07:37:58 +0000 (07:37 +0000)
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

18 files changed:
ChangeLog
public/v8.h
src/api.cc
src/api.h
src/ast.cc
src/compiler.cc
src/debug.cc
src/execution.cc
src/execution.h
src/mksnapshot.cc
src/objects.cc
src/runtime.cc
src/runtime.h
src/serialize.cc
src/serialize.h
src/snapshot-common.cc
src/snapshot-empty.cc
src/snapshot.h

index 884bed41853eb61ad8dcb63662bae1522c52b4b6..a4d4e4f8cdba79daae38ab85e9ddadf3b928dfa7 100644 (file)
--- 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
index 256d5ba18ca61aa33da6293e272e5aa18cfa0e54..63d2e065aa1165ed5c850aa3473f3fe21d2362b6 100644 (file)
@@ -1779,11 +1779,14 @@ class Context {
                                      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
index 5f1a94cbe14ff6142ccab3f6b4659b5737c536cc..f346cc197783953ff5a5c722ceee8346de173510 100644 (file)
@@ -403,11 +403,12 @@ void** v8::HandleScope::CreateHandle(void* value) {
 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::Enter() {
 
 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 @@ bool Context::InSecurityContext() {
 }
 
 
-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);
 }
index 6975e573b0e550af80ea6325e4767703c856b40b..45701dcc7577730032ed9c7b53a39e8f0abd80da 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -345,15 +345,17 @@ class HandleScopeImplementer {
 
   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 @@ class HandleScopeImplementer {
   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 @@ class HandleScopeImplementer {
   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 @@ class HandleScopeImplementer {
 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();
+bool HandleScopeImplementer::HasSavedContexts() {
+  return !saved_contexts_.is_empty();
 }
 
-void HandleScopeImplementer::AddSecurityContext(Handle<Object> context) {
-  security_contexts.Add(context);
+
+void HandleScopeImplementer::SaveSecurityContext(Handle<Object> context) {
+  saved_security_contexts_.Add(context);
+}
+
+
+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);
 }
 
 
-Handle<Object> HandleScopeImplementer::RemoveLastSecurityContext() {
-  return security_contexts.RemoveLast();
+bool HandleScopeImplementer::LeaveLastContext() {
+  if (entered_contexts_.is_empty()) return false;
+  entered_contexts_.RemoveLast();
+  return true;
 }
 
 
-bool HandleScopeImplementer::HasSecurityContexts() {
-  return !security_contexts.is_empty();
+Handle<Object> HandleScopeImplementer::LastEnteredContext() {
+  if (entered_contexts_.is_empty()) return Handle<Object>::null();
+  return entered_contexts_.last();
 }
 
 
index 232bfad8a11d4460c599d722e2cb27be7ce3549c..6296f950892e5a084e7f126c9861636398e63435 100644 (file)
@@ -83,7 +83,6 @@ void VariableProxy::BindTo(Variable* var) {
   // 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_);
index 48502cad148184e55ee975d416a998e9de75beb8..fb11bf82fb4612703367cce3edf9ff9b70b77ce7 100644 (file)
@@ -112,7 +112,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
 
   // Make sure we have an initial stack limit.
   StackGuard guard;
-  StackGuard::DisableInterrupts();
+  PostponeInterruptsScope postpone;
 
   // Notify debugger
   Debugger::OnBeforeCompile(script);
@@ -126,7 +126,6 @@ static Handle<JSFunction> MakeFunction(bool is_global,
   // Check for parse errors.
   if (lit == NULL) {
     ASSERT(Top::has_pending_exception());
-    StackGuard::EnableInterrupts();
     return Handle<JSFunction>::null();
   }
 
@@ -144,7 +143,6 @@ static Handle<JSFunction> MakeFunction(bool is_global,
   // Check for stack-overflow exceptions.
   if (code.is_null()) {
     Top::StackOverflow();
-    StackGuard::EnableInterrupts();
     return Handle<JSFunction>::null();
   }
 
@@ -172,8 +170,6 @@ static Handle<JSFunction> MakeFunction(bool is_global,
   // the instances of the function.
   SetExpectedNofPropertiesFromEstimate(fun, lit->expected_property_count());
 
-  StackGuard::EnableInterrupts();
-
   // Notify debugger
   Debugger::OnAfterCompile(script, fun);
 
@@ -242,7 +238,7 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
 
   // 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 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
   // Check for parse errors.
   if (lit == NULL) {
     ASSERT(Top::has_pending_exception());
-    StackGuard::EnableInterrupts();
     return false;
   }
 
@@ -278,7 +273,6 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
   // Check for stack-overflow exception.
   if (code.is_null()) {
     Top::StackOverflow();
-    StackGuard::EnableInterrupts();
     return false;
   }
 
@@ -293,7 +287,6 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
 
   // Check the function has compiled code.
   ASSERT(shared->is_compiled());
-  StackGuard::EnableInterrupts();
   return true;
 }
 
index e7f5ee29f1a41399b7571edf6c5288106a66450b..a5401ed945380ddc95de9d04b3aba1d2fbacd3db 100644 (file)
@@ -530,10 +530,12 @@ void Debug::Setup(bool create_heap_objects) {
 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 @@ bool Debug::CompileDebuggerScript(int index) {
     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 @@ bool Debug::Load() {
   // 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);
-
-  // Enter the debugger context.
+  Handle<Context> context =
+      Bootstrapper::CreateEnvironment(Handle<Object>::null(),
+                                      v8::Handle<ObjectTemplate>(),
+                                      NULL);
+
+  // 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 @@ Object* Debug::Break(Arguments args) {
   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 @@ Object* Debug::Break(Arguments args) {
     PrepareStep(step_action, step_count);
   }
 
-  // Reactivate interrupt.
-  StackGuard::EnableInterrupts();
-
   // Install jump to the call address which was overwritten.
   SetAfterBreakTarget(frame);
 
@@ -1344,8 +1347,8 @@ void Debugger::DebugRequest(const uint16_t* json_request, int length) {
     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 @@ Handle<String> Debugger::ProcessRequest(Handle<Object> exec_state,
 
 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 Debugger::IsPlainBreakRequest(Handle<Object> request) {
   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 @@ void DebugMessageThread::Run() {
 }
 
 
-// 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) {
index 6e97c3506c980e021090a52017195e51c255d1e1..e1d46e5fedfe90fb03d22aaaccfea80f15354ebf 100644 (file)
@@ -75,7 +75,8 @@ static Handle<Object> Invoke(bool construct,
     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 @@ bool StackGuard::IsDebugBreak() {
   return thread_local_.interrupt_flags_ & DEBUGBREAK;
 }
 
+
 void StackGuard::DebugBreak() {
   ExecutionAccess access;
   if (!Top::is_break_no_lock()) {
index 4bd07fb750ad79adc43b3e3f960e9aff3539b9d9..27a4c9cea9dc570edfca0e6ab54a83313ee63076 100644 (file)
@@ -147,8 +147,6 @@ class StackGuard BASE_EMBEDDED {
   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 @@ class StackGuard BASE_EMBEDDED {
     }
   }
 
+  // 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 @@ class StackGuard BASE_EMBEDDED {
        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 @@ class StackLimitCheck BASE_EMBEDDED {
 };
 
 
+// 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) { }
index 0e3d750b27d5fbc288d02bdcb48fe7ec1392c930..234430505e0ed289d7aa7685af64352d6fd189be 100644 (file)
@@ -132,7 +132,7 @@ static int WriteInternalSnapshotToFile(const char* filename,
   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) {
index ab40bb6621bee7af8822b033d25dbd638d2fbb84..59bbfa18a1172323f18523af20b2b0166badbfd5 100644 (file)
@@ -348,7 +348,7 @@ Object* Object::GetProperty(Object* receiver,
     if (current == last) break;
   }
 
-  if (!result->IsValid()) {
+  if (!result->IsProperty()) {
     *attributes = ABSENT;
     return Heap::undefined_value();
   }
@@ -378,17 +378,14 @@ Object* Object::GetProperty(Object* receiver,
                                      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 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
   // 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.
index 2d9e4986413587a5463a07ef41fd1b0e7c17c409..2e3025b979c19a32538ccf81296720509036e347 100644 (file)
@@ -2988,8 +2988,8 @@ static Object* RuntimePreempt(Arguments args) {
 
 
 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 @@ static Object* Runtime_DebugBreak(Arguments args) {
   // 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 @@ static Object* EvalContext() {
   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 @@ static Object* Runtime_Abort(Arguments args) {
 }
 
 
+#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 @@ static Object* Runtime_ListNatives(Arguments args) {
 #undef ADD_ENTRY
   return *result;
 }
+#endif
 
 
 static Object* Runtime_IS_VAR(Arguments args) {
index 8ea552af21525d97d8a03f31ae04fd53265b6ecc..e46ff470a4efb3fd21016d412f7cf741d96350be 100644 (file)
@@ -33,11 +33,11 @@ namespace v8 { namespace internal {
 // 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 @@ namespace v8 { namespace internal {
   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.
 
index 4f402322bec92f25768b68d1675df241d9c4c748..0d5f129bd9bf358881d8edcac7f25740cfe51feb 100644 (file)
@@ -921,17 +921,18 @@ void Serializer::PutGlobalHandleStack(const List<Handle<Object> >& stack) {
 
 
 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 @@ RelativeAddress Serializer::Allocate(HeapObject* obj) {
 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 @@ void Deserializer::GetContextStack() {
   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]);
   }
 }
 
index 5997d37763db0378b2f6e4bd574edf375c6950e5..5085b7e4f6ae5bb1388432ec4d7664100d666b8a 100644 (file)
@@ -202,7 +202,7 @@ class Serializer: public ObjectVisitor {
 
 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 @@ class SnapshotReader {
   }
 
   int GetInt() {
-    int result = *reinterpret_cast<int*>(str_);
+    int result = *reinterpret_cast<const int*>(str_);
     str_ += sizeof(result);
     return result;
   }
@@ -238,8 +238,8 @@ class SnapshotReader {
   }
 
  private:
-  char* str_;
-  char* end_;
+  const char* str_;
+  const char* end_;
 };
 
 
@@ -249,7 +249,7 @@ class Deserializer: public ObjectVisitor {
  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();
 
index ba15fd5bb6e996d7ba2c25e8f6de27f621947477..314a5f0b69ec90cb51f90302784e735602aef6ce 100644 (file)
@@ -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);
index c015d86f4a41bd1bb28ba99d98f7bf65aa22fa79..909a223907e159a25b107b4557335232668e3f06 100644 (file)
@@ -33,7 +33,7 @@
 
 namespace v8 { namespace internal {
 
-char Snapshot::data_[] = { 0 };
+const char Snapshot::data_[] = { 0 };
 int Snapshot::size_ = 0;
 
 } }  // namespace v8::internal
index ebc578fa55c15de383f87a2fdca6cc99f1fca3ba..bb40c2efbff2b0a50d31422dd2fb6fd57632c23f 100644 (file)
@@ -45,10 +45,10 @@ class Snapshot {
   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);
 };