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
parent c40aa827
......@@ -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)));
......
......@@ -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
......
......@@ -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();
}
}
......
......@@ -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:
......
......@@ -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;
......
......@@ -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.
......
......@@ -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
......
......@@ -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.
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment