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