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:
parent
c40aa827bf
commit
4b96218589
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user