Revision: 8231
Author:   [email protected]
Date:     Thu Jun  9 04:26:01 2011
Log:      A collection of context-related refactoring changes.

Introduce separate maps for function and with contexts.  Use the function
context map for testing whether a context is a function context (global
contexts are no longer function contexts).

Split the paths for allocating with and catch contexts.

Rename some functions.  Generally refactor code to make it simpler.

[email protected]
BUG=
TEST=

Review URL: http://codereview.chromium.org/7003058
http://code.google.com/p/v8/source/detail?r=8231

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/contexts.cc
 /branches/bleeding_edge/src/contexts.h
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/full-codegen.cc
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/mark-compact.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/prettyprinter.cc
 /branches/bleeding_edge/src/rewriter.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Mon Jun 6 00:47:21 2011 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Jun 9 04:26:01 2011
@@ -158,7 +158,7 @@
   __ ldr(r3, MemOperand(sp, 0));

   // Setup the object header.
-  __ LoadRoot(r2, Heap::kContextMapRootIndex);
+  __ LoadRoot(r2, Heap::kFunctionContextMapRootIndex);
   __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
   __ mov(r2, Operand(Smi::FromInt(length)));
   __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset));
@@ -187,7 +187,7 @@

   // Need to collect. Call into runtime system.
   __ bind(&gc);
-  __ TailCallRuntime(Runtime::kNewContext, 1, 1);
+  __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
 }


=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Jun 3 00:41:37 2011 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Jun 9 04:26:01 2011
@@ -182,7 +182,7 @@
       FastNewContextStub stub(heap_slots);
       __ CallStub(&stub);
     } else {
-      __ CallRuntime(Runtime::kNewContext, 1);
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
     }
     function_in_register = false;
     // Context is returned in both r0 and cp.  It replaces the context
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Jun 8 03:51:51 2011 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Jun 9 04:26:01 2011
@@ -189,7 +189,7 @@
       FastNewContextStub stub(heap_slots);
       __ CallStub(&stub);
     } else {
-      __ CallRuntime(Runtime::kNewContext, 1);
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
     }
     RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
     // Context is returned in both r0 and cp.  It replaces the context
=======================================
--- /branches/bleeding_edge/src/ast.cc  Wed Jun  8 06:55:33 2011
+++ /branches/bleeding_edge/src/ast.cc  Thu Jun  9 04:26:01 2011
@@ -362,12 +362,12 @@
 }


-bool WithEnterStatement::IsInlineable() const {
+bool EnterWithContextStatement::IsInlineable() const {
   return false;
 }


-bool WithExitStatement::IsInlineable() const {
+bool ExitContextStatement::IsInlineable() const {
   return false;
 }

=======================================
--- /branches/bleeding_edge/src/ast.h   Wed Jun  8 06:55:33 2011
+++ /branches/bleeding_edge/src/ast.h   Thu Jun  9 04:26:01 2011
@@ -60,8 +60,8 @@
   V(ContinueStatement)                          \
   V(BreakStatement)                             \
   V(ReturnStatement)                            \
-  V(WithEnterStatement)                         \
-  V(WithExitStatement)                          \
+  V(EnterWithContextStatement)                  \
+  V(ExitContextStatement)                       \
   V(SwitchStatement)                            \
   V(DoWhileStatement)                           \
   V(WhileStatement)                             \
@@ -611,12 +611,12 @@
 };


-class WithEnterStatement: public Statement {
+class EnterWithContextStatement: public Statement {
  public:
-  explicit WithEnterStatement(Expression* expression)
+  explicit EnterWithContextStatement(Expression* expression)
       : expression_(expression) { }

-  DECLARE_NODE_TYPE(WithEnterStatement)
+  DECLARE_NODE_TYPE(EnterWithContextStatement)

   Expression* expression() const { return expression_; }

@@ -627,13 +627,11 @@
 };


-class WithExitStatement: public Statement {
+class ExitContextStatement: public Statement {
  public:
-  WithExitStatement() { }
-
   virtual bool IsInlineable() const;

-  DECLARE_NODE_TYPE(WithExitStatement)
+  DECLARE_NODE_TYPE(ExitContextStatement)
 };


=======================================
--- /branches/bleeding_edge/src/contexts.cc     Tue May 24 01:38:42 2011
+++ /branches/bleeding_edge/src/contexts.cc     Thu Jun  9 04:26:01 2011
@@ -96,7 +96,7 @@
       PrintF("\n");
     }

-    // check extension/with object
+    // Check extension/with/global object.
     if (context->has_extension()) {
       Handle<JSObject> extension = Handle<JSObject>(context->extension(),
                                                     isolate);
@@ -119,7 +119,8 @@
       }
     }

-    if (context->is_function_context()) {
+    // Only functions can have locals, parameters, and a function name.
+    if (context->IsFunctionContext()) {
       // we have context-local slots

       // check non-parameter locals in context
@@ -189,9 +190,8 @@
     // proceed with enclosing context
     if (context->IsGlobalContext()) {
       follow_context_chain = false;
-    } else if (context->is_function_context()) {
- context = Handle<Context>(Context::cast(context->closure()->context()),
-                                isolate);
+    } else if (context->IsFunctionContext()) {
+      context = Handle<Context>(context->closure()->context(), isolate);
     } else {
       context = Handle<Context>(context->previous(), isolate);
     }
@@ -212,11 +212,12 @@
   // before the global context and check that there are no context
   // extension objects (conservative check for with statements).
   while (!context->IsGlobalContext()) {
-    // Check if the context is a potentially a with context.
+    // Check if the context is a catch or with context, or has called
+    // non-strict eval.
     if (context->has_extension()) return false;

     // Not a with context so it must be a function context.
-    ASSERT(context->is_function_context());
+    ASSERT(context->IsFunctionContext());

     // Check non-parameter locals.
     Handle<SerializedScopeInfo> scope_info(
=======================================
--- /branches/bleeding_edge/src/contexts.h      Tue May 31 09:38:40 2011
+++ /branches/bleeding_edge/src/contexts.h      Thu Jun  9 04:26:01 2011
@@ -289,8 +289,17 @@
   // Compute the global context by traversing the context chain.
   Context* global_context();

-  // Tells if this is a function context (as opposed to a 'with' context).
-  bool is_function_context() { return unchecked_previous() == NULL; }
+  // Predicates for context types.  IsGlobalContext is defined on Object
+  // because we frequently have to know if arbitrary objects are global
+  // contexts.
+  bool IsFunctionContext() {
+    Map* map = this->map();
+    return map == map->GetHeap()->function_context_map();
+  }
+  bool IsCatchContext() {
+    Map* map = this->map();
+    return map == map->GetHeap()->catch_context_map();
+  }

   // Tells whether the global context is marked with out of memory.
   inline bool has_out_of_memory();
=======================================
--- /branches/bleeding_edge/src/factory.cc      Thu Jun  9 03:03:35 2011
+++ /branches/bleeding_edge/src/factory.cc      Thu Jun  9 04:26:01 2011
@@ -247,16 +247,22 @@
       isolate()->heap()->AllocateFunctionContext(length, *closure),
       Context);
 }
+
+
+Handle<Context> Factory::NewCatchContext(Handle<Context> previous,
+                                         Handle<JSObject> extension) {
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateCatchContext(*previous, *extension),
+      Context);
+}


 Handle<Context> Factory::NewWithContext(Handle<Context> previous,
-                                        Handle<JSObject> extension,
-                                        bool is_catch_context) {
+                                        Handle<JSObject> extension) {
   CALL_HEAP_FUNCTION(
       isolate(),
-      isolate()->heap()->AllocateWithContext(*previous,
-                                             *extension,
-                                             is_catch_context),
+      isolate()->heap()->AllocateWithContext(*previous, *extension),
       Context);
 }

=======================================
--- /branches/bleeding_edge/src/factory.h       Thu Jun  9 03:03:35 2011
+++ /branches/bleeding_edge/src/factory.h       Thu Jun  9 04:26:01 2011
@@ -149,10 +149,13 @@
   Handle<Context> NewFunctionContext(int length,
                                      Handle<JSFunction> closure);

+  // Create a catch context.
+  Handle<Context> NewCatchContext(Handle<Context> previous,
+                                  Handle<JSObject> extension);
+
   // Create a 'with' context.
   Handle<Context> NewWithContext(Handle<Context> previous,
-                                 Handle<JSObject> extension,
-                                 bool is_catch_context);
+                                 Handle<JSObject> extension);

   // Return the Symbol matching the passed in string.
   Handle<String> SymbolFromString(Handle<String> value);
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Wed Jun  8 06:55:33 2011
+++ /branches/bleeding_edge/src/full-codegen.cc Thu Jun  9 04:26:01 2011
@@ -90,14 +90,14 @@
 }


-void BreakableStatementChecker::VisitWithEnterStatement(
-    WithEnterStatement* stmt) {
+void BreakableStatementChecker::VisitEnterWithContextStatement(
+    EnterWithContextStatement* stmt) {
   Visit(stmt->expression());
 }


-void BreakableStatementChecker::VisitWithExitStatement(
-    WithExitStatement* stmt) {
+void BreakableStatementChecker::VisitExitContextStatement(
+    ExitContextStatement* stmt) {
 }


@@ -952,18 +952,19 @@
 }


-void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
-  Comment cmnt(masm_, "[ WithEnterStatement");
+void FullCodeGenerator::VisitEnterWithContextStatement(
+    EnterWithContextStatement* stmt) {
+  Comment cmnt(masm_, "[ EnterWithContextStatement");
   SetStatementPosition(stmt);

   VisitForStackValue(stmt->expression());
-  __ CallRuntime(Runtime::kPushContext, 1);
+  __ CallRuntime(Runtime::kPushWithContext, 1);
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
 }


-void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
-  Comment cmnt(masm_, "[ WithExitStatement");
+void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) {
+  Comment cmnt(masm_, "[ ExitContextStatement");
   SetStatementPosition(stmt);

   // Pop context.
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Jun  9 03:03:35 2011
+++ /branches/bleeding_edge/src/heap.cc Thu Jun  9 04:26:01 2011
@@ -1894,7 +1894,7 @@
         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
-  set_context_map(Map::cast(obj));
+  set_function_context_map(Map::cast(obj));

   { MaybeObject* maybe_obj =
         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
@@ -1902,6 +1902,12 @@
   }
   set_catch_context_map(Map::cast(obj));

+  { MaybeObject* maybe_obj =
+        AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_with_context_map(Map::cast(obj));
+
   { MaybeObject* maybe_obj =
         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
     if (!maybe_obj->ToObject(&obj)) return false;
@@ -3919,38 +3925,47 @@
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   Context* context = reinterpret_cast<Context*>(result);
-  context->set_map(context_map());
+  context->set_map(function_context_map());
   context->set_closure(function);
   context->set_fcontext(context);
   context->set_previous(NULL);
   context->set_extension(NULL);
   context->set_global(function->context()->global());
-  ASSERT(!context->IsGlobalContext());
-  ASSERT(context->is_function_context());
-  ASSERT(result->IsContext());
-  return result;
+  return context;
+}
+
+
+MaybeObject* Heap::AllocateCatchContext(Context* previous,
+                                        JSObject* extension) {
+  Object* result;
+ { MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
+  Context* context = reinterpret_cast<Context*>(result);
+  context->set_map(catch_context_map());
+  context->set_closure(previous->closure());
+  context->set_fcontext(previous->fcontext());
+  context->set_previous(previous);
+  context->set_extension(extension);
+  context->set_global(previous->global());
+  return context;
 }


 MaybeObject* Heap::AllocateWithContext(Context* previous,
-                                       JSObject* extension,
-                                       bool is_catch_context) {
+                                       JSObject* extension) {
   Object* result;
{ MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   Context* context = reinterpret_cast<Context*>(result);
-  context->set_map(is_catch_context ? catch_context_map() :
-      context_map());
+  context->set_map(with_context_map());
   context->set_closure(previous->closure());
   context->set_fcontext(previous->fcontext());
   context->set_previous(previous);
   context->set_extension(extension);
   context->set_global(previous->global());
-  ASSERT(!context->IsGlobalContext());
-  ASSERT(!context->is_function_context());
-  ASSERT(result->IsContext());
-  return result;
+  return context;
 }


=======================================
--- /branches/bleeding_edge/src/heap.h  Thu Jun  9 03:03:35 2011
+++ /branches/bleeding_edge/src/heap.h  Thu Jun  9 04:26:01 2011
@@ -107,8 +107,9 @@
V(Map, external_unsigned_int_array_map, ExternalUnsignedIntArrayMap) \ V(Map, external_float_array_map, ExternalFloatArrayMap) \ V(Map, external_double_array_map, ExternalDoubleArrayMap) \ - V(Map, context_map, ContextMap) \ + V(Map, function_context_map, FunctionContextMap) \ V(Map, catch_context_map, CatchContextMap) \ + V(Map, with_context_map, WithContextMap) \ V(Map, code_map, CodeMap) \ V(Map, oddball_map, OddballMap) \ V(Map, global_property_cell_map, GlobalPropertyCellMap) \
@@ -645,10 +646,12 @@
   MUST_USE_RESULT MaybeObject* AllocateFunctionContext(int length,
JSFunction* closure);

+  // Allocate a catch context.
+  MUST_USE_RESULT MaybeObject* AllocateCatchContext(Context* previous,
+                                                    JSObject* extension);
   // Allocate a 'with' context.
   MUST_USE_RESULT MaybeObject* AllocateWithContext(Context* previous,
-                                                   JSObject* extension,
-                                                   bool is_catch_context);
+                                                   JSObject* extension);

   // Allocates a new utility object in the old generation.
   MUST_USE_RESULT MaybeObject* AllocateStruct(InstanceType type);
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Thu Jun  9 04:15:03 2011
+++ /branches/bleeding_edge/src/hydrogen.cc     Thu Jun  9 04:26:01 2011
@@ -2551,19 +2551,20 @@
 }


-void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
+void HGraphBuilder::VisitEnterWithContextStatement(
+    EnterWithContextStatement* stmt) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("WithEnterStatement");
+  return Bailout("EnterWithContextStatement");
 }


-void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
+void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("WithExitStatement");
+  return Bailout("ExitContextStatement");
 }


=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Tue Jun 7 00:17:46 2011 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Jun 9 04:26:01 2011
@@ -129,7 +129,8 @@

   // Setup the object header.
   Factory* factory = masm->isolate()->factory();
- __ mov(FieldOperand(eax, HeapObject::kMapOffset), factory->context_map());
+  __ mov(FieldOperand(eax, HeapObject::kMapOffset),
+         factory->function_context_map());
   __ mov(FieldOperand(eax, Context::kLengthOffset),
          Immediate(Smi::FromInt(length)));

@@ -159,7 +160,7 @@

   // Need to collect. Call into runtime system.
   __ bind(&gc);
-  __ TailCallRuntime(Runtime::kNewContext, 1, 1);
+  __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
 }


=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Jun 3 00:41:37 2011 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Jun 9 04:26:01 2011
@@ -175,7 +175,7 @@
       FastNewContextStub stub(heap_slots);
       __ CallStub(&stub);
     } else {
-      __ CallRuntime(Runtime::kNewContext, 1);
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
     }
     function_in_register = false;
     // Context is returned in both eax and esi.  It replaces the context
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Jun 8 03:51:51 2011 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Jun 9 04:26:01 2011
@@ -184,7 +184,7 @@
       FastNewContextStub stub(heap_slots);
       __ CallStub(&stub);
     } else {
-      __ CallRuntime(Runtime::kNewContext, 1);
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
     }
     RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
     // Context is returned in both eax and esi.  It replaces the context
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Thu Jun  9 03:03:35 2011
+++ /branches/bleeding_edge/src/mark-compact.cc Thu Jun  9 04:26:01 2011
@@ -672,8 +672,9 @@

     Map* map = SafeMap(ctx);
     Heap* heap = map->heap();
-    if (!(map == heap->raw_unchecked_context_map() ||
+    if (!(map == heap->raw_unchecked_function_context_map() ||
           map == heap->raw_unchecked_catch_context_map() ||
+          map == heap->raw_unchecked_with_context_map() ||
           map == heap->raw_unchecked_global_context_map())) {
       return false;
     }
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Jun  9 03:03:35 2011
+++ /branches/bleeding_edge/src/objects-inl.h   Thu Jun  9 04:26:01 2011
@@ -534,20 +534,15 @@

 bool Object::IsContext() {
   if (Object::IsHeapObject()) {
-    Heap* heap = HeapObject::cast(this)->GetHeap();
-    return (HeapObject::cast(this)->map() == heap->context_map() ||
-            HeapObject::cast(this)->map() == heap->catch_context_map() ||
-            HeapObject::cast(this)->map() == heap->global_context_map());
+    Map* map = HeapObject::cast(this)->map();
+    Heap* heap = map->GetHeap();
+    return (map == heap->function_context_map() ||
+            map == heap->catch_context_map() ||
+            map == heap->with_context_map() ||
+            map == heap->global_context_map());
   }
   return false;
 }
-
-
-bool Object::IsCatchContext() {
-  return Object::IsHeapObject() &&
-      HeapObject::cast(this)->map() ==
-      HeapObject::cast(this)->GetHeap()->catch_context_map();
-}


 bool Object::IsGlobalContext() {
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Jun  9 03:03:35 2011
+++ /branches/bleeding_edge/src/objects.h       Thu Jun  9 04:26:01 2011
@@ -735,7 +735,6 @@
   V(FixedArray)                                \
   V(FixedDoubleArray)                          \
   V(Context)                                   \
-  V(CatchContext)                              \
   V(GlobalContext)                             \
   V(JSFunction)                                \
   V(Code)                                      \
=======================================
--- /branches/bleeding_edge/src/parser.cc       Thu Jun  9 02:05:15 2011
+++ /branches/bleeding_edge/src/parser.cc       Thu Jun  9 04:26:01 2011
@@ -1922,7 +1922,7 @@
   Block* result = new(zone()) Block(NULL, 2, false);

   if (result != NULL) {
-    result->AddStatement(new(zone()) WithEnterStatement(obj));
+    result->AddStatement(new(zone()) EnterWithContextStatement(obj));

     // Create body block.
     Block* body = new(zone()) Block(NULL, 1, false);
@@ -1930,7 +1930,7 @@

     // Create exit block.
     Block* exit = new(zone()) Block(NULL, 1, false);
-    exit->AddStatement(new(zone()) WithExitStatement());
+    exit->AddStatement(new(zone()) ExitContextStatement());

     // Return a try-finally statement.
TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit);
@@ -2089,8 +2089,8 @@
     Expect(Token::RPAREN, CHECK_OK);

     if (peek() == Token::LBRACE) {
-        // Rewrite the catch body B to a single statement block
-        // { try B finally { PopContext }}.
+      // Rewrite the catch body B to a single statement block
+      // { try B finally { PopContext }}.
       Block* inner_body;
       // We need to collect escapes from the body for both the inner
       // try/finally used to pop the catch context and any possible outer
@@ -2107,7 +2107,7 @@

       // Create exit block.
       Block* inner_finally = new(zone()) Block(NULL, 1, false);
-      inner_finally->AddStatement(new(zone()) WithExitStatement());
+      inner_finally->AddStatement(new(zone()) ExitContextStatement());

       // Create a try/finally statement.
       TryFinallyStatement* inner_try_finally =
=======================================
--- /branches/bleeding_edge/src/prettyprinter.cc        Wed Jun  8 06:55:33 2011
+++ /branches/bleeding_edge/src/prettyprinter.cc        Thu Jun  9 04:26:01 2011
@@ -123,15 +123,16 @@
 }


-void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
-  Print("<enter with> (");
+void PrettyPrinter::VisitEnterWithContextStatement(
+    EnterWithContextStatement* node) {
+  Print("<enter with context> (");
   Visit(node->expression());
   Print(") ");
 }


-void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) {
-  Print("<exit with>");
+void PrettyPrinter::VisitExitContextStatement(ExitContextStatement* node) {
+  Print("<exit context>");
 }


@@ -797,13 +798,14 @@
 }


-void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
-  PrintIndentedVisit("WITH ENTER", node->expression());
+void AstPrinter::VisitEnterWithContextStatement(
+    EnterWithContextStatement* node) {
+  PrintIndentedVisit("ENTER WITH CONTEXT", node->expression());
 }


-void AstPrinter::VisitWithExitStatement(WithExitStatement* node) {
-  PrintIndented("WITH EXIT\n");
+void AstPrinter::VisitExitContextStatement(ExitContextStatement* node) {
+  PrintIndented("EXIT CONTEXT\n");
 }


@@ -1191,14 +1193,15 @@
 }


-void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
-  TagScope tag(this, "WithEnterStatement");
+void JsonAstBuilder::VisitEnterWithContextStatement(
+    EnterWithContextStatement* stmt) {
+  TagScope tag(this, "EnterWithContextStatement");
   Visit(stmt->expression());
 }


-void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
-  TagScope tag(this, "WithExitStatement");
+void JsonAstBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
+  TagScope tag(this, "ExitContextStatement");
 }


=======================================
--- /branches/bleeding_edge/src/rewriter.cc     Wed Jun  8 06:55:33 2011
+++ /branches/bleeding_edge/src/rewriter.cc     Thu Jun  9 04:26:01 2011
@@ -197,131 +197,18 @@
 void Processor::VisitDeclaration(Declaration* node) {}
 void Processor::VisitEmptyStatement(EmptyStatement* node) {}
 void Processor::VisitReturnStatement(ReturnStatement* node) {}
-void Processor::VisitWithEnterStatement(WithEnterStatement* node) {}
-void Processor::VisitWithExitStatement(WithExitStatement* node) {}
+void Processor::VisitEnterWithContextStatement(
+    EnterWithContextStatement* node) {
+}
+void Processor::VisitExitContextStatement(ExitContextStatement* node) {}
 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}


 // Expressions are never visited yet.
-void Processor::VisitFunctionLiteral(FunctionLiteral* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitSharedFunctionInfoLiteral(
-    SharedFunctionInfoLiteral* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitConditional(Conditional* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitVariableProxy(VariableProxy* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitLiteral(Literal* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitRegExpLiteral(RegExpLiteral* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitArrayLiteral(ArrayLiteral* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitObjectLiteral(ObjectLiteral* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitAssignment(Assignment* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitThrow(Throw* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitProperty(Property* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitCall(Call* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitCallNew(CallNew* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitCallRuntime(CallRuntime* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitUnaryOperation(UnaryOperation* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitCountOperation(CountOperation* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitBinaryOperation(BinaryOperation* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitCompareOperation(CompareOperation* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitCompareToNull(CompareToNull* node) {
-  USE(node);
-  UNREACHABLE();
-}
-
-
-void Processor::VisitThisFunction(ThisFunction* node) {
-  USE(node);
-  UNREACHABLE();
-}
+#define DEF_VISIT(type)                                         \
+  void Processor::Visit##type(type* expr) { UNREACHABLE(); }
+EXPRESSION_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT


 // Assumes code has been parsed and scopes have been analyzed.  Mutates the
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Wed Jun  8 01:13:31 2011
+++ /branches/bleeding_edge/src/runtime.cc      Thu Jun  9 04:26:01 2011
@@ -7883,7 +7883,7 @@
 }


-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewContext) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);

@@ -7901,50 +7901,50 @@
 }


-MUST_USE_RESULT static MaybeObject* PushContextHelper(Isolate* isolate,
-                                                      Object* object,
- bool is_catch_context) {
-  // Convert the object to a proper JavaScript object.
-  Object* js_object = object;
-  if (!js_object->IsJSObject()) {
-    MaybeObject* maybe_js_object = js_object->ToObject();
-    if (!maybe_js_object->ToObject(&js_object)) {
-      if (!Failure::cast(maybe_js_object)->IsInternalError()) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  JSObject* extension_object;
+  if (args[0]->IsJSObject()) {
+    extension_object = JSObject::cast(args[0]);
+  } else {
+    // Convert the object to a proper JavaScript object.
+    MaybeObject* maybe_js_object = args[0]->ToObject();
+    if (!maybe_js_object->To(&extension_object)) {
+      if (Failure::cast(maybe_js_object)->IsInternalError()) {
+        HandleScope scope(isolate);
+        Handle<Object> handle = args.at<Object>(0);
+        Handle<Object> result =
+            isolate->factory()->NewTypeError("with_expression",
+                                             HandleVector(&handle, 1));
+        return isolate->Throw(*result);
+      } else {
         return maybe_js_object;
       }
-      HandleScope scope(isolate);
-      Handle<Object> handle(object, isolate);
-      Handle<Object> result =
-          isolate->factory()->NewTypeError("with_expression",
-                                           HandleVector(&handle, 1));
-      return isolate->Throw(*result);
     }
   }

-  Object* result;
-  { MaybeObject* maybe_result = isolate->heap()->AllocateWithContext(
-      isolate->context(), JSObject::cast(js_object), is_catch_context);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
-
-  Context* context = Context::cast(result);
+  Context* context;
+  MaybeObject* maybe_context =
+      isolate->heap()->AllocateWithContext(isolate->context(),
+                                           extension_object);
+  if (!maybe_context->To(&context)) return maybe_context;
   isolate->set_context(context);
-
-  return result;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PushContext) {
-  NoHandleAllocation ha;
-  ASSERT(args.length() == 1);
-  return PushContextHelper(isolate, args[0], false);
+  return context;
 }


 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  return PushContextHelper(isolate, args[0], true);
+  JSObject* extension_object = JSObject::cast(args[0]);
+  Context* context;
+  MaybeObject* maybe_context =
+      isolate->heap()->AllocateCatchContext(isolate->context(),
+                                            extension_object);
+  if (!maybe_context->To(&context)) return maybe_context;
+  isolate->set_context(context);
+  return context;
 }


@@ -8607,9 +8607,8 @@
     // Stop search when eval is found or when the global context is
     // reached.
     if (attributes != ABSENT || context->IsGlobalContext()) break;
-    if (context->is_function_context()) {
- context = Handle<Context>(Context::cast(context->closure()->context()),
-                                isolate);
+    if (context->IsFunctionContext()) {
+      context = Handle<Context>(context->closure()->context(), isolate);
     } else {
       context = Handle<Context>(context->previous(), isolate);
     }
@@ -9842,8 +9841,8 @@
   Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
   ScopeInfo<> info(*scope_info);

-  // Get the context.
-  Handle<Context> context(Context::cast(it.frame()->context()));
+  // Get the nearest enclosing function context.
+ Handle<Context> context(Context::cast(it.frame()->context())->fcontext());

   // Get the locals names and values into a temporary array.
   //
@@ -9859,25 +9858,22 @@
   }

   // Fill in the values of the locals.
-  for (int i = 0; i < info.NumberOfLocals(); i++) {
-    if (is_optimized_frame) {
-      // If we are inspecting an optimized frame use undefined as the
-      // value for all locals.
-      //
-      // TODO(1140): We should be able to get the correct values
-      // for locals in optimized frames.
+  if (is_optimized_frame) {
+    // If we are inspecting an optimized frame use undefined as the
+    // value for all locals.
+    //
+    // TODO(1140): We should be able to get the correct values
+    // for locals in optimized frames.
+    for (int i = 0; i < info.NumberOfLocals(); i++) {
       locals->set(i * 2 + 1, isolate->heap()->undefined_value());
-    } else if (i < info.number_of_stack_slots()) {
+    }
+  } else {
+    for (int i = 0; i < info.number_of_stack_slots(); i++) {
       // Get the value from the stack.
       locals->set(i * 2 + 1, it.frame()->GetExpression(i));
-    } else {
-      // Traverse the context chain to the function context as all local
-      // variables stored in the context will be on the function context.
+    }
+ for (int i = info.number_of_stack_slots(); i < info.NumberOfLocals(); i++) {
       Handle<String> name = info.LocalName(i);
-      while (!context->is_function_context()) {
-        context = Handle<Context>(context->previous());
-      }
-      ASSERT(context->is_function_context());
       locals->set(i * 2 + 1,
                   context->get(scope_info->ContextSlotIndex(*name, NULL)));
     }
@@ -10139,7 +10135,7 @@
 // context.
 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
                                            Handle<Context> context) {
-  ASSERT(context->is_function_context());
+  ASSERT(context->IsFunctionContext());

   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
@@ -10238,7 +10234,7 @@
       int index = function_->shared()->scope_info()->
           StackSlotIndex(isolate_->heap()->result_symbol());
       at_local_ = index < 0;
-    } else if (context_->is_function_context()) {
+    } else if (context_->IsFunctionContext()) {
       at_local_ = true;
     } else if (context_->closure() != *function_) {
       // The context_ is a with block from the outer function.
@@ -10272,8 +10268,8 @@
     }

     // Move to the next context.
-    if (context_->is_function_context()) {
- context_ = Handle<Context>(Context::cast(context_->closure()->context()));
+    if (context_->IsFunctionContext()) {
+      context_ = Handle<Context>(context_->closure()->context());
     } else {
       context_ = Handle<Context>(context_->previous());
     }
@@ -10281,7 +10277,7 @@
// If passing the local scope indicate that the current scope is now the
     // local scope.
     if (!local_done_ &&
- (context_->IsGlobalContext() || (context_->is_function_context()))) {
+        (context_->IsGlobalContext() || context_->IsFunctionContext())) {
       at_local_ = true;
     }
   }
@@ -10295,7 +10291,7 @@
       ASSERT(context_->global()->IsGlobalObject());
       return ScopeTypeGlobal;
     }
-    if (context_->is_function_context()) {
+    if (context_->IsFunctionContext()) {
       return ScopeTypeClosure;
     }
     ASSERT(context_->has_extension());
@@ -10863,19 +10859,23 @@

// Creates a copy of the with context chain. The copy of the context chain is
 // is linked to the function context supplied.
-static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
- Handle<Context> function_context) {
-  // At the bottom of the chain. Return the function context to link to.
-  if (context_chain->is_function_context()) {
-    return function_context;
+static Handle<Context> CopyWithContextChain(Isolate* isolate,
+                                            Handle<Context> current,
+                                            Handle<Context> base) {
+  // At the end of the chain. Return the base context to link to.
+  if (current->IsFunctionContext() || current->IsGlobalContext()) {
+    return base;
   }

-  // Recursively copy the with contexts.
-  Handle<Context> previous(context_chain->previous());
-  Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
- Handle<Context> context = CopyWithContextChain(previous, function_context);
-  return context->GetIsolate()->factory()->NewWithContext(
-      context, extension, context_chain->IsCatchContext());
+  // Recursively copy the with and catch contexts.
+  HandleScope scope(isolate);
+  Handle<Context> previous(current->previous());
+ Handle<Context> new_previous = CopyWithContextChain(isolate, previous, base);
+  Handle<JSObject> extension(JSObject::cast(current->extension()));
+  Handle<Context> new_current = current->IsCatchContext()
+      ? isolate->factory()->NewCatchContext(new_previous, extension)
+      : isolate->factory()->NewWithContext(new_previous, extension);
+  return scope.CloseAndEscape(new_current);
 }


@@ -11004,11 +11004,11 @@
// Copy any with contexts present and chain them in front of this context.
   Handle<Context> frame_context(Context::cast(frame->context()));
   Handle<Context> function_context(frame_context->fcontext());
-  context = CopyWithContextChain(frame_context, context);
+  context = CopyWithContextChain(isolate, frame_context, context);

   if (additional_context->IsJSObject()) {
-    context = isolate->factory()->NewWithContext(context,
-        Handle<JSObject>::cast(additional_context), false);
+ Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
+    context = isolate->factory()->NewWithContext(context, extension);
   }

   // Wrap the evaluation statement in a new function compiled in the newly
=======================================
--- /branches/bleeding_edge/src/runtime.h       Tue Jun  7 00:17:46 2011
+++ /branches/bleeding_edge/src/runtime.h       Thu Jun  9 04:26:01 2011
@@ -297,8 +297,8 @@
   F(PromoteScheduledException, 0, 1) \
   \
   /* Contexts */ \
-  F(NewContext, 1, 1) \
-  F(PushContext, 1, 1) \
+  F(NewFunctionContext, 1, 1) \
+  F(PushWithContext, 1, 1) \
   F(PushCatchContext, 1, 1) \
   F(DeleteContextSlot, 2, 1) \
   F(LoadContextSlot, 2, 2) \
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue May 31 09:38:40 2011 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Thu Jun 9 04:26:01 2011
@@ -125,7 +125,7 @@
   __ movq(rcx, Operand(rsp, 1 * kPointerSize));

   // Setup the object header.
-  __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex);
+  __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex);
   __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
__ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));

@@ -152,7 +152,7 @@

   // Need to collect. Call into runtime system.
   __ bind(&gc);
-  __ TailCallRuntime(Runtime::kNewContext, 1, 1);
+  __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
 }


=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Jun 3 00:41:37 2011 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Jun 9 04:26:01 2011
@@ -175,7 +175,7 @@
       FastNewContextStub stub(heap_slots);
       __ CallStub(&stub);
     } else {
-      __ CallRuntime(Runtime::kNewContext, 1);
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
     }
     function_in_register = false;
     // Context is returned in both rax and rsi.  It replaces the context
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Jun 8 03:51:51 2011 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Jun 9 04:26:01 2011
@@ -197,7 +197,7 @@
       FastNewContextStub stub(heap_slots);
       __ CallStub(&stub);
     } else {
-      __ CallRuntime(Runtime::kNewContext, 1);
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
     }
     RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
     // Context is returned in both rax and rsi.  It replaces the context

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to