Revision: 8453
Author:   [email protected]
Date:     Wed Jun 29 00:41:42 2011
Log: Explicitly pass the closure when allocating a catch or with context.

Before: allocation of a catch or with context fetched the closure to store
in the context from the previous context in the context chain.  Now: the
closure is passed explicitly.

[email protected]
BUG=
TEST=

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

Modified:
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/full-codegen.cc
 /branches/bleeding_edge/src/full-codegen.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue Jun 28 08:22:08 2011 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed Jun 29 00:41:42 2011
@@ -4260,6 +4260,26 @@
 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
   __ ldr(dst, ContextOperand(cp, context_index));
 }
+
+
+void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
+  if (scope()->is_global_scope()) {
+ // Contexts nested in the global context have a canonical empty function
+    // as their closure, not the anonymous closure containing the global
+    // code.  Pass a smi sentinel and let the runtime look up the empty
+    // function.
+    __ mov(ip, Operand(Smi::FromInt(0)));
+  } else if (scope()->is_eval_scope()) {
+    // Contexts created by a call to eval have the same closure as the
+    // context calling eval, not the anonymous closure containing the eval
+    // code.  Fetch it from the context.
+    __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX));
+  } else {
+    ASSERT(scope()->is_function_scope());
+    __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  }
+  __ push(ip);
+}


// ----------------------------------------------------------------------------
=======================================
--- /branches/bleeding_edge/src/factory.cc      Mon Jun 27 02:02:34 2011
+++ /branches/bleeding_edge/src/factory.cc      Wed Jun 29 00:41:42 2011
@@ -251,29 +251,34 @@


 Handle<Context> Factory::NewFunctionContext(int length,
-                                            Handle<JSFunction> closure) {
+                                            Handle<JSFunction> function) {
   CALL_HEAP_FUNCTION(
       isolate(),
-      isolate()->heap()->AllocateFunctionContext(length, *closure),
+      isolate()->heap()->AllocateFunctionContext(length, *function),
       Context);
 }


-Handle<Context> Factory::NewCatchContext(Handle<Context> previous,
+Handle<Context> Factory::NewCatchContext(Handle<JSFunction> function,
+                                         Handle<Context> previous,
                                          Handle<String> name,
                                          Handle<Object> thrown_object) {
   CALL_HEAP_FUNCTION(
       isolate(),
- isolate()->heap()->AllocateCatchContext(*previous, *name, *thrown_object),
+      isolate()->heap()->AllocateCatchContext(*function,
+                                              *previous,
+                                              *name,
+                                              *thrown_object),
       Context);
 }


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

=======================================
--- /branches/bleeding_edge/src/factory.h       Mon Jun 27 02:02:34 2011
+++ /branches/bleeding_edge/src/factory.h       Wed Jun 29 00:41:42 2011
@@ -152,15 +152,17 @@

   // Create a function context.
   Handle<Context> NewFunctionContext(int length,
-                                     Handle<JSFunction> closure);
+                                     Handle<JSFunction> function);

   // Create a catch context.
-  Handle<Context> NewCatchContext(Handle<Context> previous,
+  Handle<Context> NewCatchContext(Handle<JSFunction> function,
+                                  Handle<Context> previous,
                                   Handle<String> name,
                                   Handle<Object> thrown_object);

   // Create a 'with' context.
-  Handle<Context> NewWithContext(Handle<Context> previous,
+  Handle<Context> NewWithContext(Handle<JSFunction> function,
+                                 Handle<Context> previous,
                                  Handle<JSObject> extension);

   // Return the Symbol matching the passed in string.
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Fri Jun 24 07:30:10 2011
+++ /branches/bleeding_edge/src/full-codegen.cc Wed Jun 29 00:41:42 2011
@@ -956,7 +956,8 @@
   SetStatementPosition(stmt);

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

@@ -1107,7 +1108,8 @@
   { Comment cmnt(masm_, "[ Extend catch context");
     __ Push(stmt->name());
     __ push(result_register());
-    __ CallRuntime(Runtime::kPushCatchContext, 2);
+    PushFunctionArgumentForContextAllocation();
+    __ CallRuntime(Runtime::kPushCatchContext, 3);
     StoreToFrameField(StandardFrameConstants::kContextOffset,
                       context_register());
   }
=======================================
--- /branches/bleeding_edge/src/full-codegen.h  Fri Jun 24 07:30:10 2011
+++ /branches/bleeding_edge/src/full-codegen.h  Wed Jun 29 00:41:42 2011
@@ -556,6 +556,10 @@
   // in v8::internal::Context.
   void LoadContextField(Register dst, int context_index);

+  // Push the function argument for the runtime functions PushWithContext
+  // and PushCatchContext.
+  void PushFunctionArgumentForContextAllocation();
+
   // AST node visit functions.
 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
   AST_NODE_LIST(DECLARE_VISIT)
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Jun 28 08:22:08 2011
+++ /branches/bleeding_edge/src/heap.cc Wed Jun 29 00:41:42 2011
@@ -3939,7 +3939,8 @@
 }


-MaybeObject* Heap::AllocateCatchContext(Context* previous,
+MaybeObject* Heap::AllocateCatchContext(JSFunction* function,
+                                        Context* previous,
                                         String* name,
                                         Object* thrown_object) {
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == Context::THROWN_OBJECT_INDEX);
@@ -3950,7 +3951,7 @@
   }
   Context* context = reinterpret_cast<Context*>(result);
   context->set_map(catch_context_map());
-  context->set_closure(previous->closure());
+  context->set_closure(function);
   context->set_previous(previous);
   context->set_extension(name);
   context->set_global(previous->global());
@@ -3959,7 +3960,8 @@
 }


-MaybeObject* Heap::AllocateWithContext(Context* previous,
+MaybeObject* Heap::AllocateWithContext(JSFunction* function,
+                                       Context* previous,
                                        JSObject* extension) {
   Object* result;
{ MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
@@ -3967,7 +3969,7 @@
   }
   Context* context = reinterpret_cast<Context*>(result);
   context->set_map(with_context_map());
-  context->set_closure(previous->closure());
+  context->set_closure(function);
   context->set_previous(previous);
   context->set_extension(extension);
   context->set_global(previous->global());
=======================================
--- /branches/bleeding_edge/src/heap.h  Wed Jun 22 13:23:48 2011
+++ /branches/bleeding_edge/src/heap.h  Wed Jun 29 00:41:42 2011
@@ -647,14 +647,16 @@

   // Allocate a function context.
   MUST_USE_RESULT MaybeObject* AllocateFunctionContext(int length,
- JSFunction* closure); + JSFunction* function);

   // Allocate a catch context.
-  MUST_USE_RESULT MaybeObject* AllocateCatchContext(Context* previous,
+  MUST_USE_RESULT MaybeObject* AllocateCatchContext(JSFunction* function,
+                                                    Context* previous,
                                                     String* name,
                                                     Object* thrown_object);
   // Allocate a 'with' context.
-  MUST_USE_RESULT MaybeObject* AllocateWithContext(Context* previous,
+  MUST_USE_RESULT MaybeObject* AllocateWithContext(JSFunction* function,
+                                                   Context* previous,
                                                    JSObject* extension);

   // Allocates a new utility object in the old generation.
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue Jun 28 08:22:08 2011 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Jun 29 00:41:42 2011
@@ -4209,6 +4209,25 @@
 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
   __ mov(dst, ContextOperand(esi, context_index));
 }
+
+
+void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
+  if (scope()->is_global_scope()) {
+ // Contexts nested in the global context have a canonical empty function
+    // as their closure, not the anonymous closure containing the global
+    // code.  Pass a smi sentinel and let the runtime look up the empty
+    // function.
+    __ push(Immediate(Smi::FromInt(0)));
+  } else if (scope()->is_eval_scope()) {
+    // Contexts created by a call to eval have the same closure as the
+    // context calling eval, not the anonymous closure containing the eval
+    // code.  Fetch it from the context.
+    __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
+  } else {
+    ASSERT(scope()->is_function_scope());
+    __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+  }
+}


// ----------------------------------------------------------------------------
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Jun 28 08:22:08 2011
+++ /branches/bleeding_edge/src/runtime.cc      Wed Jun 29 00:41:42 2011
@@ -8049,7 +8049,7 @@

 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
   NoHandleAllocation ha;
-  ASSERT(args.length() == 1);
+  ASSERT(args.length() == 2);
   JSObject* extension_object;
   if (args[0]->IsJSObject()) {
     extension_object = JSObject::cast(args[0]);
@@ -8069,10 +8069,21 @@
       }
     }
   }
+
+  JSFunction* function;
+  if (args[1]->IsSmi()) {
+    // A smi sentinel indicates a context nested inside global code rather
+    // than some function.  There is a canonical empty function that can be
+    // gotten from the global context.
+    function = isolate->context()->global_context()->closure();
+  } else {
+    function = JSFunction::cast(args[1]);
+  }

   Context* context;
   MaybeObject* maybe_context =
-      isolate->heap()->AllocateWithContext(isolate->context(),
+      isolate->heap()->AllocateWithContext(function,
+                                           isolate->context(),
                                            extension_object);
   if (!maybe_context->To(&context)) return maybe_context;
   isolate->set_context(context);
@@ -8082,12 +8093,22 @@

 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
   NoHandleAllocation ha;
-  ASSERT(args.length() == 2);
+  ASSERT(args.length() == 3);
   String* name = String::cast(args[0]);
   Object* thrown_object = args[1];
+  JSFunction* function;
+  if (args[2]->IsSmi()) {
+    // A smi sentinel indicates a context nested inside global code rather
+    // than some function.  There is a canonical empty function that can be
+    // gotten from the global context.
+    function = isolate->context()->global_context()->closure();
+  } else {
+    function = JSFunction::cast(args[2]);
+  }
   Context* context;
   MaybeObject* maybe_context =
-      isolate->heap()->AllocateCatchContext(isolate->context(),
+      isolate->heap()->AllocateCatchContext(function,
+                                            isolate->context(),
                                             name,
                                             thrown_object);
   if (!maybe_context->To(&context)) return maybe_context;
@@ -10967,6 +10988,7 @@
// 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(Isolate* isolate,
+                                            Handle<JSFunction> function,
                                             Handle<Context> current,
                                             Handle<Context> base) {
   // At the end of the chain. Return the base context to link to.
@@ -10977,17 +10999,21 @@
   // Recursively copy the with and catch contexts.
   HandleScope scope(isolate);
   Handle<Context> previous(current->previous());
- Handle<Context> new_previous = CopyWithContextChain(isolate, previous, base);
+  Handle<Context> new_previous =
+      CopyWithContextChain(isolate, function, previous, base);
   Handle<Context> new_current;
   if (current->IsCatchContext()) {
     Handle<String> name(String::cast(current->extension()));
Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX));
     new_current =
- isolate->factory()->NewCatchContext(new_previous, name, thrown_object);
+        isolate->factory()->NewCatchContext(function,
+                                            new_previous,
+                                            name,
+                                            thrown_object);
   } else {
     Handle<JSObject> extension(JSObject::cast(current->extension()));
     new_current =
-        isolate->factory()->NewWithContext(new_previous, extension);
+ isolate->factory()->NewWithContext(function, new_previous, extension);
   }
   return scope.CloseAndEscape(new_current);
 }
@@ -11118,11 +11144,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->declaration_context());
-  context = CopyWithContextChain(isolate, frame_context, context);
+ context = CopyWithContextChain(isolate, go_between, frame_context, context);

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

   // Wrap the evaluation statement in a new function compiled in the newly
=======================================
--- /branches/bleeding_edge/src/runtime.h       Thu Jun 16 07:12:58 2011
+++ /branches/bleeding_edge/src/runtime.h       Wed Jun 29 00:41:42 2011
@@ -298,8 +298,8 @@
   \
   /* Contexts */ \
   F(NewFunctionContext, 1, 1) \
-  F(PushWithContext, 1, 1) \
-  F(PushCatchContext, 2, 1) \
+  F(PushWithContext, 2, 1) \
+  F(PushCatchContext, 3, 1) \
   F(DeleteContextSlot, 2, 1) \
   F(LoadContextSlot, 2, 2) \
   F(LoadContextSlotNoReferenceError, 2, 2) \
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Tue Jun 28 08:22:08 2011 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed Jun 29 00:41:42 2011
@@ -4188,6 +4188,25 @@
 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
   __ movq(dst, ContextOperand(rsi, context_index));
 }
+
+
+void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
+  if (scope()->is_global_scope()) {
+ // Contexts nested in the global context have a canonical empty function
+    // as their closure, not the anonymous closure containing the global
+    // code.  Pass a smi sentinel and let the runtime look up the empty
+    // function.
+    __ Push(Smi::FromInt(0));
+  } else if (scope()->is_eval_scope()) {
+    // Contexts created by a call to eval have the same closure as the
+    // context calling eval, not the anonymous closure containing the eval
+    // code.  Fetch it from the context.
+    __ push(ContextOperand(rsi, Context::CLOSURE_INDEX));
+  } else {
+    ASSERT(scope()->is_function_scope());
+    __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+  }
+}


// ----------------------------------------------------------------------------

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

Reply via email to