Link function contexts directly to the previous context.

Instead of NULL in the previous field of function contexts, put the previous
context.  This saves the indirection of fetching the previous through the
context's closure.

R=ager@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/7134042

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8238 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-06-09 12:45:26 +00:00
parent c40aa827bf
commit 4b96218589
10 changed files with 23 additions and 49 deletions

View File

@ -167,10 +167,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ mov(r1, Operand(Smi::FromInt(0)));
__ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX)));
__ str(r0, MemOperand(r0, Context::SlotOffset(Context::FCONTEXT_INDEX)));
__ str(r1, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX)));
__ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX)));
__ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX)));
// Copy the global object from the surrounding context.
// Copy the global object from the previous context.
__ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
__ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX)));

View File

@ -2538,12 +2538,9 @@ void MacroAssembler::Abort(const char* msg) {
void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
if (context_chain_length > 0) {
// Move up the chain of contexts to the context containing the slot.
ldr(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX)));
// Load the function context (which is the incoming, outer context).
ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
ldr(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
for (int i = 1; i < context_chain_length; i++) {
ldr(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
ldr(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
}
} else {
// Slot is in the current function context. Move it into the

View File

@ -187,11 +187,9 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
}
}
// proceed with enclosing context
// Proceed with the previous context.
if (context->IsGlobalContext()) {
follow_context_chain = false;
} else if (context->IsFunctionContext()) {
context = Handle<Context>(context->closure()->context(), isolate);
} else {
context = Handle<Context>(context->previous(), isolate);
}
@ -234,7 +232,7 @@ bool Context::GlobalIfNotShadowedByEval(Handle<String> name) {
// Check context only holding the function name variable.
index = scope_info->FunctionContextSlotIndex(*name);
if (index >= 0) return false;
context = Context::cast(context->closure()->context());
context = context->previous();
}
// No local or potential with statement found so the variable is
@ -245,8 +243,10 @@ bool Context::GlobalIfNotShadowedByEval(Handle<String> name) {
void Context::ComputeEvalScopeInfo(bool* outer_scope_calls_eval,
bool* outer_scope_calls_non_strict_eval) {
Context* context = this;
while (true) {
// Skip up the context chain checking all the function contexts to see
// whether they call eval.
Context* context = fcontext();
while (!context->IsGlobalContext()) {
Handle<SerializedScopeInfo> scope_info(
context->closure()->shared()->scope_info());
if (scope_info->CallsEval()) {
@ -258,8 +258,7 @@ void Context::ComputeEvalScopeInfo(bool* outer_scope_calls_eval,
return;
}
}
if (context->IsGlobalContext()) break;
context = Context::cast(context->closure()->context());
context = context->previous()->fcontext();
}
}

View File

@ -166,9 +166,6 @@ enum ContextLookupFlags {
// the moment we also use it in generated code for context slot accesses -
// and there we don't want a loop because of code bloat - but we may not
// need it there after all (see comment in codegen_*.cc).
//
// - If we cannot get rid of fcontext, consider making 'previous' never NULL
// except for the global context. This could simplify Context::Lookup.
class Context: public FixedArray {
public:

View File

@ -3928,7 +3928,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
context->set_map(function_context_map());
context->set_closure(function);
context->set_fcontext(context);
context->set_previous(NULL);
context->set_previous(function->context());
context->set_extension(NULL);
context->set_global(function->context()->global());
return context;

View File

@ -138,14 +138,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ Set(ebx, Immediate(0)); // Set to NULL.
__ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
__ mov(Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)), eax);
__ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), ebx);
__ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi);
__ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx);
// Copy the global object from the surrounding context. We go through the
// context in the function (ecx) to match the allocation behavior we have
// in the runtime system (see Heap::AllocateFunctionContext).
__ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset));
__ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX)));
// Copy the global object from the previous context.
__ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
__ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx);
// Initialize the rest of the slots to undefined.

View File

@ -1759,12 +1759,9 @@ void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
if (context_chain_length > 0) {
// Move up the chain of contexts to the context containing the slot.
mov(dst, Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX)));
// Load the function context (which is the incoming, outer context).
mov(dst, FieldOperand(dst, JSFunction::kContextOffset));
mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
for (int i = 1; i < context_chain_length; i++) {
mov(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
mov(dst, FieldOperand(dst, JSFunction::kContextOffset));
mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
}
} else {
// Slot is in the current function context. Move it into the

View File

@ -8607,11 +8607,7 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
// Stop search when eval is found or when the global context is
// reached.
if (attributes != ABSENT || context->IsGlobalContext()) break;
if (context->IsFunctionContext()) {
context = Handle<Context>(context->closure()->context(), isolate);
} else {
context = Handle<Context>(context->previous(), isolate);
}
context = Handle<Context>(context->previous(), isolate);
}
// If eval could not be resolved, it has been deleted and we need to
@ -10268,11 +10264,7 @@ class ScopeIterator {
}
// Move to the next context.
if (context_->IsFunctionContext()) {
context_ = Handle<Context>(context_->closure()->context());
} else {
context_ = Handle<Context>(context_->previous());
}
context_ = Handle<Context>(context_->previous(), isolate_);
// If passing the local scope indicate that the current scope is now the
// local scope.

View File

@ -133,10 +133,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ Set(rbx, 0); // Set to NULL.
__ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
__ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax);
__ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx);
__ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi);
__ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx);
// Copy the global object from the surrounding context.
// Copy the global object from the previous context.
__ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
__ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx);

View File

@ -3617,15 +3617,10 @@ void MacroAssembler::CopyBytes(Register destination,
void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
if (context_chain_length > 0) {
// Move up the chain of contexts to the context containing the slot.
movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
// Load the function context (which is the incoming, outer context).
movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
movq(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
for (int i = 1; i < context_chain_length; i++) {
movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
movq(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
}
// The context may be an intermediate context, not a function context.
movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
} else {
// Slot is in the current function context. Move it into the
// destination register in case we store into it (the write barrier