| Index: src/ia32/fast-codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/fast-codegen-ia32.cc (revision 3532)
|
| +++ src/ia32/fast-codegen-ia32.cc (working copy)
|
| @@ -261,30 +261,28 @@
|
| }
|
|
|
|
|
| -template <>
|
| -Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source,
|
| - Register scratch) {
|
| - switch (source->type()) {
|
| +MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
|
| + switch (slot->type()) {
|
| case Slot::PARAMETER:
|
| case Slot::LOCAL:
|
| - return Operand(ebp, SlotOffset(source));
|
| + return Operand(ebp, SlotOffset(slot));
|
| case Slot::CONTEXT: {
|
| int context_chain_length =
|
| - function_->scope()->ContextChainLength(source->var()->scope());
|
| + function_->scope()->ContextChainLength(slot->var()->scope());
|
| __ LoadContext(scratch, context_chain_length);
|
| - return CodeGenerator::ContextOperand(scratch, source->index());
|
| + return CodeGenerator::ContextOperand(scratch, slot->index());
|
| }
|
| case Slot::LOOKUP:
|
| - UNIMPLEMENTED();
|
| + UNREACHABLE();
|
| }
|
| UNREACHABLE();
|
| return Operand(eax, 0);
|
| }
|
|
|
|
|
| -void FastCodeGenerator::Move(Register dst, Slot* source) {
|
| - Operand location = CreateSlotOperand<Operand>(source, dst);
|
| - __ mov(dst, location);
|
| +void FastCodeGenerator::Move(Register destination, Slot* source) {
|
| + MemOperand location = EmitSlotSearch(source, destination);
|
| + __ mov(destination, location);
|
| }
|
|
|
|
|
| @@ -297,7 +295,7 @@
|
| case Expression::kEffect:
|
| break;
|
| case Expression::kValue: {
|
| - Operand location = CreateSlotOperand<Operand>(source, scratch);
|
| + MemOperand location = EmitSlotSearch(source, scratch);
|
| __ push(location);
|
| break;
|
| }
|
| @@ -334,25 +332,14 @@
|
| Register src,
|
| Register scratch1,
|
| Register scratch2) {
|
| - switch (dst->type()) {
|
| - case Slot::PARAMETER:
|
| - case Slot::LOCAL:
|
| - __ mov(Operand(ebp, SlotOffset(dst)), src);
|
| - break;
|
| - case Slot::CONTEXT: {
|
| - ASSERT(!src.is(scratch1));
|
| - ASSERT(!src.is(scratch2));
|
| - ASSERT(!scratch1.is(scratch2));
|
| - int context_chain_length =
|
| - function_->scope()->ContextChainLength(dst->var()->scope());
|
| - __ LoadContext(scratch1, context_chain_length);
|
| - __ mov(Operand(scratch1, Context::SlotOffset(dst->index())), src);
|
| - int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
|
| - __ RecordWrite(scratch1, offset, src, scratch2);
|
| - break;
|
| - }
|
| - case Slot::LOOKUP:
|
| - UNIMPLEMENTED();
|
| + ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
|
| + ASSERT(!scratch1.is(src) && !scratch2.is(src));
|
| + MemOperand location = EmitSlotSearch(dst, scratch1);
|
| + __ mov(location, src);
|
| + // Emit the write barrier code if the location is in the heap.
|
| + if (dst->type() == Slot::CONTEXT) {
|
| + int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
|
| + __ RecordWrite(scratch1, offset, src, scratch2);
|
| }
|
| }
|
|
|
| @@ -448,15 +435,18 @@
|
| case Slot::PARAMETER:
|
| case Slot::LOCAL:
|
| if (decl->mode() == Variable::CONST) {
|
| - __ mov(Operand(ebp, SlotOffset(var->slot())),
|
| + __ mov(Operand(ebp, SlotOffset(slot)),
|
| Immediate(Factory::the_hole_value()));
|
| } else if (decl->fun() != NULL) {
|
| Visit(decl->fun());
|
| - __ pop(Operand(ebp, SlotOffset(var->slot())));
|
| + __ pop(Operand(ebp, SlotOffset(slot)));
|
| }
|
| break;
|
|
|
| case Slot::CONTEXT:
|
| + // We bypass the general EmitSlotSearch because we know more about
|
| + // this specific context.
|
| +
|
| // The variable in the decl always resides in the current context.
|
| ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
|
| if (FLAG_debug_code) {
|
| @@ -904,7 +894,7 @@
|
| switch (slot->type()) {
|
| case Slot::LOCAL:
|
| case Slot::PARAMETER: {
|
| - Operand target = Operand(ebp, SlotOffset(var->slot()));
|
| + Operand target = Operand(ebp, SlotOffset(slot));
|
| switch (context) {
|
| case Expression::kUninitialized:
|
| UNREACHABLE();
|
| @@ -948,38 +938,18 @@
|
| }
|
|
|
| case Slot::CONTEXT: {
|
| - int chain_length =
|
| - function_->scope()->ContextChainLength(slot->var()->scope());
|
| - if (chain_length > 0) {
|
| - // Move up the context chain to the context containing the slot.
|
| - __ mov(eax,
|
| - Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX)));
|
| - // Load the function context (which is the incoming, outer context).
|
| - __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset));
|
| - for (int i = 1; i < chain_length; i++) {
|
| - __ mov(eax,
|
| - Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)));
|
| - __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset));
|
| - }
|
| - } else { // Slot is in the current context. Generate optimized code.
|
| - __ mov(eax, esi); // RecordWrite destroys the object register.
|
| - }
|
| - if (FLAG_debug_code) {
|
| - __ cmp(eax,
|
| - Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)));
|
| - __ Check(equal, "Context Slot chain length wrong.");
|
| - }
|
| - __ pop(ecx);
|
| - __ mov(Operand(eax, Context::SlotOffset(slot->index())), ecx);
|
| + MemOperand target = EmitSlotSearch(slot, ecx);
|
| + __ pop(eax);
|
| + __ mov(target, eax);
|
|
|
| // RecordWrite may destroy all its register arguments.
|
| if (context == Expression::kValue) {
|
| - __ push(ecx);
|
| + __ push(eax);
|
| } else if (context != Expression::kEffect) {
|
| - __ mov(edx, ecx);
|
| + __ mov(edx, eax);
|
| }
|
| int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
|
| - __ RecordWrite(eax, offset, ecx, ebx);
|
| + __ RecordWrite(ecx, offset, eax, ebx);
|
| if (context != Expression::kEffect &&
|
| context != Expression::kValue) {
|
| Move(context, edx);
|
| @@ -991,6 +961,10 @@
|
| UNREACHABLE();
|
| break;
|
| }
|
| + } else {
|
| + // Variables rewritten as properties are not treated as variables in
|
| + // assignments.
|
| + UNREACHABLE();
|
| }
|
| }
|
|
|
|
|