| Index: src/arm/full-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/full-codegen-arm.cc (revision 5429)
|
| +++ src/arm/full-codegen-arm.cc (working copy)
|
| @@ -493,7 +493,7 @@
|
| int context_chain_length =
|
| scope()->ContextChainLength(slot->var()->scope());
|
| __ LoadContext(scratch, context_chain_length);
|
| - return CodeGenerator::ContextOperand(scratch, slot->index());
|
| + return ContextOperand(scratch, slot->index());
|
| }
|
| case Slot::LOOKUP:
|
| UNREACHABLE();
|
| @@ -557,19 +557,17 @@
|
| ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
|
| if (FLAG_debug_code) {
|
| // Check if we have the correct context pointer.
|
| - __ ldr(r1,
|
| - CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX));
|
| + __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX));
|
| __ cmp(r1, cp);
|
| __ Check(eq, "Unexpected declaration in current context.");
|
| }
|
| if (mode == Variable::CONST) {
|
| __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
| - __ str(ip, CodeGenerator::ContextOperand(cp, slot->index()));
|
| + __ str(ip, ContextOperand(cp, slot->index()));
|
| // No write barrier since the_hole_value is in old space.
|
| } else if (function != NULL) {
|
| VisitForValue(function, kAccumulator);
|
| - __ str(result_register(),
|
| - CodeGenerator::ContextOperand(cp, slot->index()));
|
| + __ str(result_register(), ContextOperand(cp, slot->index()));
|
| int offset = Context::SlotOffset(slot->index());
|
| // We know that we have written a function, which is not a smi.
|
| __ mov(r1, Operand(cp));
|
| @@ -881,6 +879,68 @@
|
| }
|
|
|
|
|
| +void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
|
| + Slot* slot,
|
| + TypeofState typeof_state,
|
| + Label* slow) {
|
| + Register current = cp;
|
| + Register next = r1;
|
| + Register temp = r2;
|
| +
|
| + Scope* s = scope();
|
| + while (s != NULL) {
|
| + if (s->num_heap_slots() > 0) {
|
| + if (s->calls_eval()) {
|
| + // Check that extension is NULL.
|
| + __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
|
| + __ tst(temp, temp);
|
| + __ b(ne, slow);
|
| + }
|
| + // Load next context in chain.
|
| + __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX));
|
| + __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
|
| + // Walk the rest of the chain using a single register without
|
| + // clobbering cp.
|
| + current = next;
|
| + }
|
| + // If no outer scope calls eval, we do not need to check more
|
| + // context extensions.
|
| + if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
|
| + s = s->outer_scope();
|
| + }
|
| +
|
| + if (s->is_eval_scope()) {
|
| + Label loop, fast;
|
| + if (!current.is(next)) {
|
| + __ Move(next, current);
|
| + }
|
| + __ bind(&loop);
|
| + // Terminate at global context.
|
| + __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
|
| + __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
|
| + __ cmp(temp, ip);
|
| + __ b(eq, &fast);
|
| + // Check that extension is NULL.
|
| + __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
|
| + __ tst(temp, temp);
|
| + __ b(ne, slow);
|
| + // Load next context in chain.
|
| + __ ldr(next, ContextOperand(next, Context::CLOSURE_INDEX));
|
| + __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
|
| + __ b(&loop);
|
| + __ bind(&fast);
|
| + }
|
| +
|
| + __ ldr(r0, CodeGenerator::GlobalObject());
|
| + __ mov(r2, Operand(slot->var()->name()));
|
| + RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
|
| + ? RelocInfo::CODE_TARGET
|
| + : RelocInfo::CODE_TARGET_CONTEXT;
|
| + Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
| + __ Call(ic, mode);
|
| +}
|
| +
|
| +
|
| void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
| Expression::Context context) {
|
| // Four cases: non-this global variables, lookup slots, all other
|
| @@ -900,11 +960,26 @@
|
| Apply(context, r0);
|
|
|
| } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
|
| + Label done, slow;
|
| +
|
| + // Generate fast-case code for variables that might be shadowed by
|
| + // eval-introduced variables. Eval is used a lot without
|
| + // introducing variables. In those cases, we do not want to
|
| + // perform a runtime call for all variables in the scope
|
| + // containing the eval.
|
| + if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
|
| + EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow);
|
| + Apply(context, r0);
|
| + __ jmp(&done);
|
| + }
|
| +
|
| + __ bind(&slow);
|
| Comment cmnt(masm_, "Lookup slot");
|
| __ mov(r1, Operand(var->name()));
|
| __ Push(cp, r1); // Context and name.
|
| __ CallRuntime(Runtime::kLoadContextSlot, 2);
|
| Apply(context, r0);
|
| + __ bind(&done);
|
|
|
| } else if (slot != NULL) {
|
| Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
|
| @@ -2464,12 +2539,10 @@
|
|
|
| Register key = r0;
|
| Register cache = r1;
|
| - __ ldr(cache, CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX));
|
| + __ ldr(cache, ContextOperand(cp, Context::GLOBAL_INDEX));
|
| __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset));
|
| + __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
|
| __ ldr(cache,
|
| - CodeGenerator::ContextOperand(
|
| - cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
|
| - __ ldr(cache,
|
| FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
|
|
|
|
|
| @@ -3187,7 +3260,7 @@
|
|
|
|
|
| void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
|
| - __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index));
|
| + __ ldr(dst, ContextOperand(cp, context_index));
|
| }
|
|
|
|
|
|
|