Revision: 3534
Author: [email protected]
Date: Tue Jan  5 03:29:27 2010
Log: More cleanup of slot handling in the nonoptimizing code generator.
Rename CreateSlotOperand so that it's clear it can emit code.  Use it
where possible.

Review URL: http://codereview.chromium.org/523052
http://code.google.com/p/v8/source/detail?r=3534

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/fast-codegen.h
  /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
  /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
  /branches/bleeding_edge/src/x64/fast-codegen-x64.cc
  /branches/bleeding_edge/src/x64/macro-assembler-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Jan  5 01:11:10  
2010
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Jan  5 03:29:27  
2010
@@ -281,32 +281,29 @@
  }


-template <>
-MemOperand FastCodeGenerator::CreateSlotOperand<MemOperand>(
-    Slot* source,
-    Register scratch) {
-  switch (source->type()) {
+MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch)  
{
+  switch (slot->type()) {
      case Slot::PARAMETER:
      case Slot::LOCAL:
-      return MemOperand(fp, SlotOffset(source));
+      return MemOperand(fp, 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 MemOperand(r0, 0);
  }


-void FastCodeGenerator::Move(Register dst, Slot* source) {
-  // Use dst as scratch.
-  MemOperand location = CreateSlotOperand<MemOperand>(source, dst);
-  __ ldr(dst, location);
+void FastCodeGenerator::Move(Register destination, Slot* source) {
+  // Use destination as scratch.
+  MemOperand location = EmitSlotSearch(source, destination);
+  __ ldr(destination, location);
  }


@@ -351,23 +348,14 @@
                               Register src,
                               Register scratch1,
                               Register scratch2) {
-  switch (dst->type()) {
-    case Slot::PARAMETER:
-    case Slot::LOCAL:
-      __ str(src, MemOperand(fp, SlotOffset(dst)));
-      break;
-    case Slot::CONTEXT: {
-      int context_chain_length =
-          function_->scope()->ContextChainLength(dst->var()->scope());
-      __ LoadContext(scratch1, context_chain_length);
-      int index = Context::SlotOffset(dst->index());
-      __ mov(scratch2, Operand(index));
-      __ str(src, MemOperand(scratch1, index));
-      __ RecordWrite(scratch1, scratch2, src);
-      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);
+  __ str(src, location);
+  // Emit the write barrier code if the location is in the heap.
+  if (dst->type() == Slot::CONTEXT) {
+    __ mov(scratch2, Operand(Context::SlotOffset(dst->index())));
+    __ RecordWrite(scratch1, scratch2, src);
    }
  }

@@ -451,15 +439,18 @@
        case Slot::LOCAL:
          if (decl->mode() == Variable::CONST) {
            __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
-          __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
+          __ str(ip, MemOperand(fp, SlotOffset(slot)));
          } else if (decl->fun() != NULL) {
            Visit(decl->fun());
            __ pop(ip);
-          __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
+          __ str(ip, MemOperand(fp, 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) {
@@ -912,35 +903,35 @@
      // Overwrite the global object on the stack with the result if needed.
      DropAndMove(context, r0);

-  } else if (var->slot()) {
+  } else if (var->slot() != NULL) {
      Slot* slot = var->slot();
-    ASSERT_NOT_NULL(slot);  // Variables rewritten as properties not  
handled.
      switch (slot->type()) {
        case Slot::LOCAL:
        case Slot::PARAMETER: {
+        MemOperand target = MemOperand(fp, SlotOffset(slot));
          switch (context) {
            case Expression::kUninitialized:
              UNREACHABLE();
            case Expression::kEffect:
              // Perform assignment and discard value.
              __ pop(r0);
-            __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+            __ str(r0, target);
              break;
            case Expression::kValue:
              // Perform assignment and preserve value.
              __ ldr(r0, MemOperand(sp));
-            __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+            __ str(r0, target);
              break;
            case Expression::kTest:
              // Perform assignment and test (and discard) value.
              __ pop(r0);
-            __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+            __ str(r0, target);
              TestAndBranch(r0, true_label_, false_label_);
              break;
            case Expression::kValueTest: {
              Label discard;
              __ ldr(r0, MemOperand(sp));
-            __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+            __ str(r0, target);
              TestAndBranch(r0, true_label_, &discard);
              __ bind(&discard);
              __ pop();
@@ -950,7 +941,7 @@
            case Expression::kTestValue: {
              Label discard;
              __ ldr(r0, MemOperand(sp));
-            __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+            __ str(r0, target);
              TestAndBranch(r0, &discard, false_label_);
              __ bind(&discard);
              __ pop();
@@ -962,31 +953,15 @@
        }

        case Slot::CONTEXT: {
-        int chain_length =
-            function_->scope()->ContextChainLength(slot->var()->scope());
-        if (chain_length > 0) {
-          // Move up the chain of contexts to the context containing the  
slot.
-          __ ldr(r0, CodeGenerator::ContextOperand(cp,  
Context::CLOSURE_INDEX));
-          // Load the function context (which is the incoming, outer  
context).
-          __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset));
-          for (int i = 1; i < chain_length; i++) {
-            __ ldr(r0,
-                   CodeGenerator::ContextOperand(r0,  
Context::CLOSURE_INDEX));
-            __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset));
-          }
-        } else {  // Slot is in the current context.  Generate optimized  
code.
-          __ mov(r0, cp);
-        }
-        // The context may be an intermediate context, not a function  
context.
-        __ ldr(r0, CodeGenerator::ContextOperand(r0,  
Context::FCONTEXT_INDEX));
-        __ pop(r1);
-        __ str(r1, CodeGenerator::ContextOperand(r0, slot->index()));
+        MemOperand target = EmitSlotSearch(slot, r1);
+        __ pop(r0);
+        __ str(r0, target);

          // RecordWrite may destroy all its register arguments.
          if (context == Expression::kValue) {
-          __ push(r1);
+          __ push(r0);
          } else if (context != Expression::kEffect) {
-          __ mov(r3, r1);
+          __ mov(r3, r0);
          }
          int offset = FixedArray::kHeaderSize + slot->index() *  
kPointerSize;

@@ -994,14 +969,13 @@
          // register.  Skip the write barrier if the value written (r1) is  
a smi.
          // The smi test is part of RecordWrite on other platforms, not on  
arm.
          Label exit;
-        __ tst(r1, Operand(kSmiTagMask));
+        __ tst(r0, Operand(kSmiTagMask));
          __ b(eq, &exit);

          __ mov(r2, Operand(offset));
-        __ RecordWrite(r0, r2, r1);
+        __ RecordWrite(r1, r2, r0);
          __ bind(&exit);
-        if (context != Expression::kEffect &&
-            context != Expression::kValue) {
+        if (context != Expression::kEffect && context !=  
Expression::kValue) {
            Move(context, r3);
          }
          break;
@@ -1011,6 +985,10 @@
          UNREACHABLE();
          break;
      }
+  } else {
+    // Variables rewritten as properties are not treated as variables in
+    // assignments.
+    UNREACHABLE();
    }
  }

=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Mon Jan  4 05:56:31 2010
+++ /branches/bleeding_edge/src/fast-codegen.h  Tue Jan  5 03:29:27 2010
@@ -219,9 +219,10 @@
    void Move(Slot* dst, Register source, Register scratch1, Register  
scratch2);
    void Move(Register dst, Slot* source);

-  // Templated to allow for Operand on intel and MemOperand on ARM.
-  template <typename MemoryLocation>
-  MemoryLocation CreateSlotOperand(Slot* slot, Register scratch);
+  // Return an operand used to read/write to a known (ie, non-LOOKUP) slot.
+  // May emit code to traverse the context chain, destroying the scratch
+  // register.
+  MemOperand EmitSlotSearch(Slot* slot, Register scratch);

    // Drop the TOS, and store source to destination.
    // If destination is TOS, just overwrite TOS with source.
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Tue Jan  5  
01:11:10 2010
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Tue Jan  5  
03:29:27 2010
@@ -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();
    }
  }

=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h     Sun Dec 20  
00:40:13 2009
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h     Tue Jan  5  
03:29:27 2010
@@ -33,10 +33,13 @@
  namespace v8 {
  namespace internal {

+// Convenience for platform-independent signatures.  We do not normally
+// distinguish memory operands from other operands on ia32.
+typedef Operand MemOperand;
+
  // Forward declaration.
  class JumpTarget;

-
  // MacroAssembler implements a collection of frequently used macros.
  class MacroAssembler: public Assembler {
   public:
=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Jan  5 01:11:10  
2010
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Jan  5 03:29:27  
2010
@@ -270,30 +270,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(rbp, SlotOffset(source));
+      return Operand(rbp, 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(rax, 0);
  }


-void FastCodeGenerator::Move(Register dst, Slot* source) {
-  Operand location = CreateSlotOperand<Operand>(source, dst);
-  __ movq(dst, location);
+void FastCodeGenerator::Move(Register destination, Slot* source) {
+  MemOperand location = EmitSlotSearch(source, destination);
+  __ movq(destination, location);
  }


@@ -306,7 +304,7 @@
      case Expression::kEffect:
        break;
      case Expression::kValue: {
-      Operand location = CreateSlotOperand<Operand>(source, scratch);
+      MemOperand location = EmitSlotSearch(source, scratch);
        __ push(location);
        break;
      }
@@ -343,25 +341,14 @@
                               Register src,
                               Register scratch1,
                               Register scratch2) {
-  switch (dst->type()) {
-    case Slot::PARAMETER:
-    case Slot::LOCAL:
-      __ movq(Operand(rbp, 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);
-      __ movq(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);
+  __ movq(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);
    }
  }

@@ -457,14 +444,17 @@
        case Slot::LOCAL:
          if (decl->mode() == Variable::CONST) {
            __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
-          __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
+          __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
          } else if (decl->fun() != NULL) {
            Visit(decl->fun());
-          __ pop(Operand(rbp, SlotOffset(var->slot())));
+          __ pop(Operand(rbp, 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) {
@@ -908,34 +898,34 @@
      // Overwrite the global object on the stack with the result if needed.
      DropAndMove(context, rax);

-  } else if (var->slot()) {
+  } else if (var->slot() != NULL) {
      Slot* slot = var->slot();
-    ASSERT_NOT_NULL(slot);  // Variables rewritten as properties not  
handled.
      switch (slot->type()) {
        case Slot::LOCAL:
        case Slot::PARAMETER: {
+        Operand target = Operand(rbp, SlotOffset(slot));
          switch (context) {
            case Expression::kUninitialized:
              UNREACHABLE();
            case Expression::kEffect:
              // Perform assignment and discard value.
-            __ pop(Operand(rbp, SlotOffset(var->slot())));
+            __ pop(target);
              break;
            case Expression::kValue:
              // Perform assignment and preserve value.
              __ movq(rax, Operand(rsp, 0));
-            __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+            __ movq(target, rax);
              break;
            case Expression::kTest:
              // Perform assignment and test (and discard) value.
              __ pop(rax);
-            __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+            __ movq(target, rax);
              TestAndBranch(rax, true_label_, false_label_);
              break;
            case Expression::kValueTest: {
              Label discard;
              __ movq(rax, Operand(rsp, 0));
-            __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+            __ movq(target, rax);
              TestAndBranch(rax, true_label_, &discard);
              __ bind(&discard);
              __ addq(rsp, Immediate(kPointerSize));
@@ -945,7 +935,7 @@
            case Expression::kTestValue: {
              Label discard;
              __ movq(rax, Operand(rsp, 0));
-            __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+            __ movq(target, rax);
              TestAndBranch(rax, &discard, false_label_);
              __ bind(&discard);
              __ addq(rsp, Immediate(kPointerSize));
@@ -957,38 +947,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.
-          __ movq(rax,
-                  Operand(rsi,  
Context::SlotOffset(Context::CLOSURE_INDEX)));
-          // Load the function context (which is the incoming, outer  
context).
-          __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
-          for (int i = 1; i < chain_length; i++) {
-            __ movq(rax,
-                    Operand(rax,  
Context::SlotOffset(Context::CLOSURE_INDEX)));
-            __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
-          }
-        } else {  // Slot is in the current context.  Generate optimized  
code.
-          __ movq(rax, rsi);  // RecordWrite destroys the object register.
-        }
-        if (FLAG_debug_code) {
-          __ cmpq(rax,
-                  Operand(rax,  
Context::SlotOffset(Context::FCONTEXT_INDEX)));
-          __ Check(equal, "Context Slot chain length wrong.");
-        }
-        __ pop(rcx);
-        __ movq(Operand(rax, Context::SlotOffset(slot->index())), rcx);
+        MemOperand target = EmitSlotSearch(slot, rcx);
+        __ pop(rax);
+        __ movq(target, rax);

          // RecordWrite may destroy all its register arguments.
          if (context == Expression::kValue) {
-          __ push(rcx);
+          __ push(rax);
          } else if (context != Expression::kEffect) {
-          __ movq(rdx, rcx);
+          __ movq(rdx, rax);
          }
          int offset = FixedArray::kHeaderSize + slot->index() *  
kPointerSize;
-        __ RecordWrite(rax, offset, rcx, rbx);
+        __ RecordWrite(rcx, offset, rax, rbx);
          if (context != Expression::kEffect &&
              context != Expression::kValue) {
            Move(context, rdx);
@@ -1000,6 +970,10 @@
          UNREACHABLE();
          break;
      }
+  } else {
+    // Variables rewritten as properties are not treated as variables in
+    // assignments.
+    UNREACHABLE();
    }
  }

=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h       Thu Dec 10  
06:06:08 2009
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h       Tue Jan  5  
03:29:27 2010
@@ -38,6 +38,9 @@
  // function calling convention.
  static const Register kScratchRegister = r10;

+// Convenience for platform-independent signatures.
+typedef Operand MemOperand;
+
  // Forward declaration.
  class JumpTarget;

-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to