Author: [EMAIL PROTECTED]
Date: Wed Nov 19 01:06:36 2008
New Revision: 788

Modified:
    branches/experimental/toiger/src/codegen-ia32.cc
    branches/experimental/toiger/src/jump-target-ia32.cc
    branches/experimental/toiger/src/virtual-frame-ia32.cc
    branches/experimental/toiger/src/virtual-frame-ia32.h

Log:
First step toward allowing constants to appear in the virtual frame
without being materialized on the actual frame.

Currently constants are materialized almost immediately: as soon as we
call the runtime; push any non-constant value on top of them; jump,
branch, or bind a jump target; or generate code for any AST node.
Review URL: http://codereview.chromium.org/11232

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Wed Nov 19 01:06:36  
2008
@@ -158,6 +158,7 @@
      frame_->AllocateStackSlots(scope_->num_stack_slots());

      if (scope_->num_heap_slots() > 0) {
+      frame_->SpillAll();
        Comment cmnt(masm_, "[ allocate local context");
        // Save the arguments object pointer, if any.
        if (arguments_object_allocated && !arguments_object_saved) {
@@ -200,17 +201,12 @@
          Variable* par = scope_->parameter(i);
          Slot* slot = par->slot();
          if (slot != NULL && slot->type() == Slot::CONTEXT) {
-          // Save the arguments object pointer, if any.
-          if (arguments_object_allocated && !arguments_object_saved) {
-            frame_->EmitPush(ecx);
-            arguments_object_saved = true;
-          }
            ASSERT(!scope_->is_global_scope());  // no parameters in global  
scope
            __ mov(eax, frame_->ParameterAt(i));
            // Loads ecx with context; used below in RecordWrite.
-          __ mov(SlotOperand(slot, ecx), eax);
+          __ mov(SlotOperand(slot, edx), eax);
            int offset = FixedArray::kHeaderSize + slot->index() *  
kPointerSize;
-          __ RecordWrite(ecx, offset, eax, ebx);
+          __ RecordWrite(edx, offset, eax, ebx);
          }
        }
      }
@@ -240,6 +236,7 @@
            // the stack, we rely on the property that loading a
            // zero-sized reference will not clobber the ecx register.
            if (!arguments_object_saved) {
+            frame_->SpillAll();
              frame_->EmitPush(ecx);
            }
            arguments_ref.SetValue(NOT_CONST_INIT);
@@ -524,10 +521,10 @@
    Comment cmnt(masm_, "[ UnloadReference");
    int size = ref->size();
    if (size == 1) {
-    frame_->Pop(eax);
+    frame_->EmitPop(eax);
      __ mov(frame_->Top(), eax);
    } else if (size > 1) {
-    frame_->Pop(eax);
+    frame_->EmitPop(eax);
      frame_->Drop(size);
      frame_->EmitPush(eax);
    }
@@ -553,7 +550,7 @@
    Comment cmnt(masm_, "[ ToBoolean");

    // The value to convert should be popped from the stack.
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);

    // Fast case checks.

@@ -711,7 +708,7 @@

    if (op == Token::COMMA) {
      // Simply discard left value.
-    frame_->Pop(eax);
+    frame_->EmitPop(eax);
      frame_->Drop();
      frame_->EmitPush(eax);
      return;
@@ -747,7 +744,7 @@
      DeferredInlineBinaryOperation* deferred =
          new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags);
      // Fetch the operands from the stack.
-    frame_->Pop(ebx);  // get y
+    frame_->EmitPop(ebx);  // get y
      __ mov(eax, frame_->Top());  // get x
      // Generate the inline part of the code.
      deferred->GenerateInlineCode();
@@ -938,7 +935,7 @@
          deferred = new DeferredInlinedSmiAddReversed(this, int_value,
                                                       overwrite_mode);
        }
-      frame_->Pop(eax);
+      frame_->EmitPop(eax);
        __ add(Operand(eax), Immediate(value));
        __ j(overflow, deferred->enter(), not_taken);
        __ test(eax, Immediate(kSmiTagMask));
@@ -950,7 +947,7 @@

      case Token::SUB: {
        DeferredCode* deferred = NULL;
-      frame_->Pop(eax);
+      frame_->EmitPop(eax);
        if (!reversed) {
          deferred = new DeferredInlinedSmiSub(this, int_value,  
overwrite_mode);
          __ sub(Operand(eax), Immediate(value));
@@ -970,7 +967,7 @@

      case Token::SAR: {
        if (reversed) {
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          frame_->EmitPush(Immediate(value));
          frame_->EmitPush(eax);
          GenericBinaryOperation(op, type, overwrite_mode);
@@ -979,7 +976,7 @@
          DeferredCode* deferred =
            new DeferredInlinedSmiOperation(this, Token::SAR, shift_value,
                                            overwrite_mode);
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          __ test(eax, Immediate(kSmiTagMask));
          __ j(not_zero, deferred->enter(), not_taken);
          __ sar(eax, shift_value);
@@ -992,7 +989,7 @@

      case Token::SHR: {
        if (reversed) {
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          frame_->EmitPush(Immediate(value));
          frame_->EmitPush(eax);
          GenericBinaryOperation(op, type, overwrite_mode);
@@ -1001,7 +998,7 @@
          DeferredCode* deferred =
          new DeferredInlinedSmiOperation(this, Token::SHR, shift_value,
                                          overwrite_mode);
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          __ test(eax, Immediate(kSmiTagMask));
          __ mov(ebx, Operand(eax));
          __ j(not_zero, deferred->enter(), not_taken);
@@ -1020,7 +1017,7 @@

      case Token::SHL: {
        if (reversed) {
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          frame_->EmitPush(Immediate(value));
          frame_->EmitPush(eax);
          GenericBinaryOperation(op, type, overwrite_mode);
@@ -1029,7 +1026,7 @@
          DeferredCode* deferred =
          new DeferredInlinedSmiOperation(this, Token::SHL, shift_value,
                                          overwrite_mode);
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          __ test(eax, Immediate(kSmiTagMask));
          __ mov(ebx, Operand(eax));
          __ j(not_zero, deferred->enter(), not_taken);
@@ -1058,7 +1055,7 @@
          deferred = new DeferredInlinedSmiOperationReversed(this, op,  
int_value,
                                                             overwrite_mode);
        }
-      frame_->Pop(eax);
+      frame_->EmitPop(eax);
        __ test(eax, Immediate(kSmiTagMask));
        __ j(not_zero, deferred->enter(), not_taken);
        if (op == Token::BIT_AND) {
@@ -1078,7 +1075,7 @@
        if (!reversed) {
          frame_->EmitPush(Immediate(value));
        } else {
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          frame_->EmitPush(Immediate(value));
          frame_->EmitPush(eax);
        }
@@ -1124,11 +1121,11 @@
    // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion  
order.
    if (cc == greater || cc == less_equal) {
      cc = ReverseCondition(cc);
-    frame_->Pop(edx);
-    frame_->Pop(eax);
+    frame_->EmitPop(edx);
+    frame_->EmitPop(eax);
    } else {
-    frame_->Pop(eax);
-    frame_->Pop(edx);
+    frame_->EmitPop(eax);
+    frame_->EmitPop(edx);
    }

    // Check for the smi case.
@@ -1200,7 +1197,7 @@

    SmiComparisonDeferred* deferred =
        new SmiComparisonDeferred(this, cc, strict, int_value);
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);
    __ test(eax, Immediate(kSmiTagMask));
    __ j(not_zero, deferred->enter(), not_taken);
    // Test smi equality by pointer comparison.
@@ -1281,6 +1278,7 @@


  void CodeGenerator::VisitBlock(Block* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Block");
    RecordStatementPosition(node);
    node->set_break_stack_height(break_stack_height_);
@@ -1293,6 +1291,7 @@


  void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
+  frame_->SpillAll();
    frame_->EmitPush(Immediate(pairs));
    frame_->EmitPush(esi);
    frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
@@ -1302,6 +1301,8 @@


  void CodeGenerator::VisitDeclaration(Declaration* node) {
+  frame_->SpillAll();
+
    Comment cmnt(masm_, "[ Declaration");
    Variable* var = node->proxy()->var();
    ASSERT(var != NULL);  // must have been resolved
@@ -1363,6 +1364,7 @@


  void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ ExpressionStatement");
    RecordStatementPosition(node);
    Expression* expression = node->expression();
@@ -1374,12 +1376,14 @@


  void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "// EmptyStatement");
    // nothing to do
  }


  void CodeGenerator::VisitIfStatement(IfStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ IfStatement");
    // Generate different code depending on which parts of the if statement
    // are present or not.
@@ -1477,6 +1481,7 @@


  void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ ContinueStatement");
    RecordStatementPosition(node);
    CleanStack(break_stack_height_ - node->target()->break_stack_height());
@@ -1485,6 +1490,7 @@


  void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ BreakStatement");
    RecordStatementPosition(node);
    CleanStack(break_stack_height_ - node->target()->break_stack_height());
@@ -1493,12 +1499,13 @@


  void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ ReturnStatement");
    RecordStatementPosition(node);
    Load(node->expression());

    // Move the function result into eax
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);

    // If we're inside a try statement or the return instruction
    // sequence has been generated, we just jump to that
@@ -1532,6 +1539,7 @@


  void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ WithEnterStatement");
    RecordStatementPosition(node);
    Load(node->expression());
@@ -1552,6 +1560,7 @@


  void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ WithExitStatement");
    // Pop context.
    __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
@@ -1586,7 +1595,7 @@
    // placeholders, and fill in the addresses after the labels have been
    // bound.

-  frame_->Pop(eax);  // supposed Smi
+  frame_->EmitPop(eax);  // supposed Smi
    // check range of value, if outside [0..length-1] jump to default/end  
label.
    ASSERT(kSmiTagSize == 1 && kSmiTag == 0);

@@ -1638,6 +1647,7 @@


  void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ SwitchStatement");
    RecordStatementPosition(node);
    node->set_break_stack_height(break_stack_height_);
@@ -1727,6 +1737,7 @@


  void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ LoopStatement");
    RecordStatementPosition(node);
    node->set_break_stack_height(break_stack_height_);
@@ -1905,6 +1916,7 @@


  void CodeGenerator::VisitForInStatement(ForInStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ ForInStatement");
    RecordStatementPosition(node);

@@ -1930,7 +1942,7 @@

    // Both SpiderMonkey and kjs ignore null and undefined in contrast
    // to the specification.  12.6.4 mandates a call to ToObject.
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);

    // eax: value to be iterated over
    __ cmp(eax, Factory::undefined_value());
@@ -2072,7 +2084,7 @@

    // Next.
    node->continue_target()->Bind();
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);
    __ add(Operand(eax), Immediate(Smi::FromInt(1)));
    frame_->EmitPush(eax);
    entry.Jump();
@@ -2090,6 +2102,7 @@


  void CodeGenerator::VisitTryCatch(TryCatch* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ TryCatch");

    JumpTarget try_block(this);
@@ -2169,7 +2182,7 @@

    // If we can fall off the end of the try block, unlink from try chain.
    if (frame_ != NULL) {
-    frame_->Pop(eax);
+    frame_->EmitPop(eax);
      __ mov(Operand::StaticVariable(handler_address), eax);  // TOS ==  
next_sp
      frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
      // next_sp popped.
@@ -2193,7 +2206,7 @@
        __ lea(esp, Operand(edx, kNextOffset));
        frame_->Forget(frame_->height() - handler_height);

-      frame_->Pop(Operand::StaticVariable(handler_address));
+      frame_->EmitPop(Operand::StaticVariable(handler_address));
        frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
        // next_sp popped.
        shadows[i]->original_target()->Jump();
@@ -2205,6 +2218,7 @@


  void CodeGenerator::VisitTryFinally(TryFinally* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ TryFinally");

    // State: Used to keep track of reason for entering the finally
@@ -2295,7 +2309,7 @@
    // Reload sp from the top handler, because some statements that we
    // break from (eg, for...in) may have left stuff on the stack.
    // Preserve the TOS in a register across stack manipulation.
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);
    ExternalReference handler_address(Top::k_handler_address);
    __ mov(edx, Operand::StaticVariable(handler_address));
    const int kNextOffset = StackHandlerConstants::kNextOffset +
@@ -2303,7 +2317,7 @@
    __ lea(esp, Operand(edx, kNextOffset));
    frame_->Forget(frame_->height() - handler_height);

-  frame_->Pop(Operand::StaticVariable(handler_address));
+  frame_->EmitPop(Operand::StaticVariable(handler_address));
    frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
    // Next_sp popped.
    frame_->EmitPush(eax);
@@ -2328,8 +2342,8 @@
    if (frame_ != NULL) {
      JumpTarget exit(this);
      // Restore state and return value or faked TOS.
-    frame_->Pop(ecx);
-    frame_->Pop(eax);
+    frame_->EmitPop(ecx);
+    frame_->EmitPop(eax);

      // Generate code to jump to the right destination for all used
      // (formerly) shadowing targets.
@@ -2355,6 +2369,7 @@


  void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ DebuggerStatement");
    RecordStatementPosition(node);
    frame_->CallRuntime(Runtime::kDebugBreak, 0);
@@ -2376,6 +2391,7 @@


  void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ FunctionLiteral");

    // Build the function boilerplate and instantiate it.
@@ -2388,12 +2404,14 @@

  void CodeGenerator::VisitFunctionBoilerplateLiteral(
      FunctionBoilerplateLiteral* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
    InstantiateBoilerplate(node->boilerplate());
  }


  void CodeGenerator::VisitConditional(Conditional* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Conditional");
    JumpTarget then(this);
    JumpTarget else_(this);
@@ -2454,12 +2472,14 @@


  void CodeGenerator::VisitSlot(Slot* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Slot");
    LoadFromSlot(node, typeof_state());
  }


  void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ VariableProxy");
    Variable* var = node->var();
    Expression* expr = var->rewrite();
@@ -2482,6 +2502,7 @@


  void CodeGenerator::VisitLiteral(Literal* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Literal");
    if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
      // To prevent long attacker-controlled byte sequences in code, larger
@@ -2526,6 +2547,7 @@


  void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ RegExp Literal");
    RegExpDeferred* deferred = new RegExpDeferred(this, node);

@@ -2586,6 +2608,7 @@


  void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ ObjectLiteral");
    ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);

@@ -2627,7 +2650,7 @@
            __ mov(eax, frame_->Top());
            frame_->EmitPush(eax);
            Load(property->value());
-          frame_->Pop(eax);
+          frame_->EmitPop(eax);
            __ Set(ecx, Immediate(key));
            frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
            frame_->Drop();
@@ -2676,6 +2699,7 @@


  void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ ArrayLiteral");

    // Call runtime to create the array literal.
@@ -2702,7 +2726,7 @@
        Load(value);

        // Get the value off the stack.
-      frame_->Pop(eax);
+      frame_->EmitPop(eax);
        // Fetch the object literal while leaving on the stack.
        __ mov(ecx, frame_->Top());
        // Get the elements array.
@@ -2727,6 +2751,7 @@


  void CodeGenerator::VisitAssignment(Assignment* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Assignment");

    RecordStatementPosition(node);
@@ -2776,6 +2801,7 @@


  void CodeGenerator::VisitThrow(Throw* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Throw");

    Load(node->exception());
@@ -2786,6 +2812,7 @@


  void CodeGenerator::VisitProperty(Property* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Property");
    Reference property(this, node);
    property.GetValue(typeof_state());
@@ -2793,6 +2820,7 @@


  void CodeGenerator::VisitCall(Call* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ Call");

    ZoneList<Expression*>* args = node->arguments();
@@ -2924,6 +2952,7 @@


  void CodeGenerator::VisitCallNew(CallNew* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ CallNew");

    // According to ECMA-262, section 11.2.2, page 44, the function
@@ -2967,7 +2996,7 @@
  void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
    ASSERT(args->length() == 1);
    Load(args->at(0));
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);
    __ test(eax, Immediate(kSmiTagMask));
    cc_reg_ = zero;
  }
@@ -2976,7 +3005,7 @@
  void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
    ASSERT(args->length() == 1);
    Load(args->at(0));
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);
    __ test(eax, Immediate(kSmiTagMask | 0x80000000));
    cc_reg_ = zero;
  }
@@ -3001,7 +3030,7 @@

    // Load the string into eax.
    Load(args->at(0));
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);
    // If the receiver is a smi return undefined.
    ASSERT(kSmiTag == 0);
    __ test(eax, Immediate(kSmiTagMask));
@@ -3009,7 +3038,7 @@

    // Load the index into ebx.
    Load(args->at(1));
-  frame_->Pop(ebx);
+  frame_->EmitPop(ebx);

    // Check for negative or non-smi index.
    ASSERT(kSmiTag == 0);
@@ -3109,7 +3138,7 @@
    // object is a smi.  This can't be done with the usual test opcode so
    // we copy the object to ecx and do some destructive ops on it that
    // result in the right CC bits.
-  frame_->Pop(eax);
+  frame_->EmitPop(eax);
    __ mov(ecx, Operand(eax));
    __ and_(ecx, kSmiTagMask);
    __ xor_(ecx, kSmiTagMask);
@@ -3208,14 +3237,15 @@
    // Load the two objects into registers and perform the comparison.
    Load(args->at(0));
    Load(args->at(1));
-  frame_->Pop(eax);
-  frame_->Pop(ecx);
+  frame_->EmitPop(eax);
+  frame_->EmitPop(ecx);
    __ cmp(eax, Operand(ecx));
    cc_reg_ = equal;
  }


  void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
+  frame_->SpillAll();
    if (CheckForInlineRuntimeCall(node)) {
      return;
    }
@@ -3254,6 +3284,7 @@


  void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
+  frame_->SpillAll();
    // Note that because of NOT and an optimization in comparison of a typeof
    // expression to a literal string, this function can fail to leave a  
value
    // on top of the frame or in the cc register.
@@ -3328,7 +3359,7 @@
        case Token::SUB: {
          UnarySubStub stub;
          // TODO(1222589): remove dependency of TOS being cached inside stub
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          frame_->CallStub(&stub, 0);
          frame_->EmitPush(eax);
          break;
@@ -3338,7 +3369,7 @@
          // Smi check.
          JumpTarget smi_label(this);
          JumpTarget continue_label(this);
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          __ test(eax, Immediate(kSmiTagMask));
          smi_label.Branch(zero, taken);

@@ -3361,7 +3392,7 @@
        case Token::ADD: {
          // Smi check.
          JumpTarget continue_label(this);
-        frame_->Pop(eax);
+        frame_->EmitPop(eax);
          __ test(eax, Immediate(kSmiTagMask));
          continue_label.Branch(zero);

@@ -3466,6 +3497,7 @@


  void CodeGenerator::VisitCountOperation(CountOperation* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ CountOperation");

    bool is_postfix = node->is_postfix();
@@ -3494,7 +3526,7 @@
          new CountOperationDeferred(this, is_postfix, is_increment,
                                     target.size() * kPointerSize);

-    frame_->Pop(eax);  // Load TOS into eax for calculations below
+    frame_->EmitPop(eax);  // Load TOS into eax for calculations below

      // Postfix: Store the old value as the result.
      if (is_postfix) {
@@ -3529,6 +3561,7 @@


  void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
+  frame_->SpillAll();
    // Note that due to an optimization in comparison operations (typeof
    // compared to a string literal), we can evaluate a binary expression  
such
    // as AND or OR and not leave a value on the frame or in the cc register.
@@ -3668,6 +3701,7 @@


  void CodeGenerator::VisitThisFunction(ThisFunction* node) {
+  frame_->SpillAll();
    frame_->EmitPush(frame_->Function());
  }

@@ -3685,6 +3719,7 @@


  void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
+  frame_->SpillAll();
    Comment cmnt(masm_, "[ CompareOperation");

    // Get the expressions from the node.
@@ -3704,7 +3739,7 @@
      // The 'null' value can only be equal to 'null' or 'undefined'.
      if (left_is_null || right_is_null) {
        Load(left_is_null ? right : left);
-      frame_->Pop(eax);
+      frame_->EmitPop(eax);
        __ cmp(eax, Factory::null_value());

        // The 'null' value is only equal to 'undefined' if using non-strict
@@ -3742,7 +3777,7 @@

      // Load the operand and move it to register edx.
      LoadTypeofExpression(operation->expression());
-    frame_->Pop(edx);
+    frame_->EmitPop(edx);

      if (check->Equals(Heap::number_symbol())) {
        __ test(edx, Immediate(kSmiTagMask));
@@ -4051,7 +4086,7 @@
          // Variable::CONST because of const declarations which will
          // initialize consts to 'the hole' value and by doing so, end up
          // calling this code.
-        frame->Pop(eax);
+        frame->EmitPop(eax);
          __ mov(cgen_->SlotOperand(slot, ecx), eax);
          frame->EmitPush(eax);  // RecordWrite may destroy the value in eax.
          if (slot->type() == Slot::CONTEXT) {
@@ -4075,7 +4110,7 @@
        Handle<String> name(GetName());
        Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
        // TODO(1222589): Make the IC grab the values from the stack.
-      frame->Pop(eax);
+      frame->EmitPop(eax);
        // Setup the name register.
        __ mov(ecx, name);
        frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
@@ -4091,7 +4126,7 @@
        // Call IC code.
        Handle<Code>  
ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
        // TODO(1222589): Make the IC grab the values from the stack.
-      frame->Pop(eax);
+      frame->EmitPop(eax);
        frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
        frame->EmitPush(eax);  // IC call leaves result in eax, push it out
        break;

Modified: branches/experimental/toiger/src/jump-target-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/jump-target-ia32.cc        (original)
+++ branches/experimental/toiger/src/jump-target-ia32.cc        Wed Nov 19  
01:06:36 2008
@@ -69,11 +69,12 @@

    if (expected_frame_ == NULL) {
      expected_frame_ = current_frame;
-    code_generator_->set_frame(NULL);
+    expected_frame_->EnsureMergable();
      // The frame at the actual function return will always have height  
zero.
      if (code_generator_->IsActualFunctionReturn(this)) {
        expected_frame_->Forget(expected_frame_->height());
      }
+    code_generator_->set_frame(NULL);
    } else {
      // No code needs to be emitted to merge to the expected frame at the
      // actual function return.
@@ -100,6 +101,7 @@

    if (expected_frame_ == NULL) {
      expected_frame_ = new VirtualFrame(current_frame);
+    expected_frame_->EnsureMergable();
      // The frame at the actual function return will always have height  
zero.
      if (code_generator_->IsActualFunctionReturn(this)) {
        expected_frame_->Forget(expected_frame_->height());
@@ -130,6 +132,7 @@
    ASSERT(expected_frame_ == NULL);

    expected_frame_ = new VirtualFrame(current_frame);
+  expected_frame_->EnsureMergable();
    // Adjust the expected frame's height to account for the return address
    // pushed by the call instruction.
    expected_frame_->Adjust(1);
@@ -153,6 +156,7 @@

    if (expected_frame_ == NULL) {
      expected_frame_ = new VirtualFrame(current_frame);
+    expected_frame_->EnsureMergable();
      // The frame at the actual function return will always have height  
zero.
      if (code_generator_->IsActualFunctionReturn(this)) {
        expected_frame_->Forget(expected_frame_->height());

Modified: branches/experimental/toiger/src/virtual-frame-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.cc      (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.cc      Wed Nov 19  
01:06:36 2008
@@ -33,77 +33,147 @@

  namespace v8 { namespace internal {

+#define __ masm_->
+
  //  
-------------------------------------------------------------------------
  // VirtualFrame implementation.

-#define __ masm_->
-
+// On entry to a function, the virtual frame already contains the receiver,
+// the parameters, and a return address.  All frame elements are in memory.
  VirtualFrame::VirtualFrame(CodeGenerator* cgen)
      : masm_(cgen->masm()),
        elements_(0),
        parameter_count_(cgen->scope()->num_parameters()),
        local_count_(0),
-      frame_pointer_(-1) {
-  // The virtual frame contains a receiver, the parameters, and a return
-  // address (all in memory) when it is created.
-  Adjust(parameter_count_ + 2);
+      stack_pointer_(parameter_count_ + 1),  // 0-based index of TOS.
+      frame_pointer_(kIllegalIndex) {
+  for (int i = 0; i < parameter_count_ + 2; i++) {
+    elements_.Add(FrameElement());
+  }
  }


+// When cloned, a frame is a deep copy of the original.
  VirtualFrame::VirtualFrame(VirtualFrame* original)
      : masm_(original->masm_),
        elements_(original->elements_.length()),
        parameter_count_(original->parameter_count_),
        local_count_(original->local_count_),
+      stack_pointer_(original->stack_pointer_),
        frame_pointer_(original->frame_pointer_) {
-  // Copy all the elements.
+  // Copy all the elements from the original.
    for (int i = 0; i < original->elements_.length(); i++) {
      elements_.Add(original->elements_[i]);
    }
  }


+// Modify the state of the virtual frame to match the actual frame by  
adding
+// extra in-memory elements to the top of the virtual frame.  The extra
+// elements will be externally materialized on the actual frame (eg, by
+// pushing an exception handler).  No code is emitted.
  void VirtualFrame::Adjust(int count) {
    ASSERT(count >= 0);
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+
    for (int i = 0; i < count; i++) {
-    elements_.Add(Element());
+    elements_.Add(FrameElement());
    }
+  stack_pointer_ += count;
  }


+// Modify the state of the virtual frame to match the actual frame by
+// removing elements from the top of the virtual frame.  The elements will
+// be externally popped from the actual frame (eg, by a runtime call).  No
+// code is emitted.
  void VirtualFrame::Forget(int count) {
    ASSERT(count >= 0);
+  ASSERT(stack_pointer_ == elements_.length() - 1);
    ASSERT(elements_.length() >= count);
+
+  stack_pointer_ -= count;
    for (int i = 0; i < count; i++) {
      elements_.RemoveLast();
    }
  }


+void VirtualFrame::SpillAll() {
+  int i = 0;
+
+  // Spill dirty constants below the stack pointer.
+  for (; i <= stack_pointer_; i++) {
+    if (elements_[i].type() == FrameElement::CONSTANT &&
+        elements_[i].is_dirty()) {
+      __ mov(Operand(ebp, fp_relative(i)),  
Immediate(elements_[i].handle()));
+      elements_[i] = FrameElement();  // The element is now in memory.
+    }
+  }
+
+  // Spill all constants above the stack pointer.
+  for (; i < elements_.length(); i++) {
+    ASSERT(elements_[i].type() == FrameElement::CONSTANT);
+    ASSERT(elements_[i].is_dirty());
+    stack_pointer_++;
+    __ push(Immediate(elements_[i].handle()));
+    elements_[i] = FrameElement();  // The element is now in memory.
+  }
+}
+
+
+void VirtualFrame::PrepareForCall(int frame_arg_count) {
+  ASSERT(height() >= frame_arg_count);
+
+  // The only non-memory elements of the frame are constants.  Push all of
+  // them above the stack pointer to allocate space for them and to ensure
+  // the arguments are flushed to memory.
+  for (int i = stack_pointer_ + 1; i < elements_.length(); i++) {
+    ASSERT(elements_[i].type() == FrameElement::CONSTANT);
+    ASSERT(elements_[i].is_dirty());
+    stack_pointer_++;
+    elements_[i].clear_dirty();
+    __ push(Immediate(elements_[i].handle()));
+  }
+
+  // Forget the ones that will be popped by the call.
+  Forget(frame_arg_count);
+}
+
+
+void VirtualFrame::EnsureMergable() {
+  // We cannot merge to a frame that has constants as elements, because an
+  // arbitrary frame may not have constants in those locations.
+  SpillAll();
+}
+
+
  void VirtualFrame::MergeTo(VirtualFrame* expected) {
    ASSERT(masm_ == expected->masm_);
    ASSERT(elements_.length() == expected->elements_.length());
    ASSERT(parameter_count_ == expected->parameter_count_);
    ASSERT(local_count_ == expected->local_count_);
    ASSERT(frame_pointer_ == expected->frame_pointer_);
-  for (int i = 0; i < elements_.length(); i++) {
-    ASSERT(elements_[i].matches(expected->elements_[i]));
-  }
+
+  // The expected frame is one we can merge to (ie, currently that means
+  // that all elements are in memory).  The only thing we need to do to
+  // merge is make this one mergable too.
+  SpillAll();
+
+  ASSERT(stack_pointer_ == expected->stack_pointer_);
  }


  void VirtualFrame::Enter() {
    Comment cmnt(masm_, "[ Enter JS frame");
-  Adjust(1);
-  __ push(ebp);
+  EmitPush(ebp);

-  frame_pointer_ = elements_.length() - 1;
+  frame_pointer_ = stack_pointer_;
    __ mov(ebp, Operand(esp));

    // Store the context and the function in the frame.
-  Adjust(2);
-  __ push(esi);
-  __ push(edi);
+  EmitPush(esi);
+  EmitPush(edi);

    // Clear the function slot when generating debug code.
    if (FLAG_debug_code) {
@@ -123,20 +193,21 @@
    // call instruction to support patching the exit code in the
    // debugger. See VisitReturnStatement for the full return sequence.
    __ mov(esp, Operand(ebp));
-  __ pop(ebp);
+  stack_pointer_ = frame_pointer_;
+  for (int i = elements_.length() - 1; i > stack_pointer_; i--) {
+    elements_.RemoveLast();
+  }
+
+  frame_pointer_ = kIllegalIndex;
+  EmitPop(ebp);
  }


  void VirtualFrame::AllocateStackSlots(int count) {
    ASSERT(height() == 0);
    local_count_ = count;
-  Adjust(count);
-  if (count > 0) {
-    Comment cmnt(masm_, "[ Allocate space for locals");
-    __ Set(eax, Immediate(Factory::undefined_value()));
-    for (int i = 0; i < count; i++) {
-      __ push(eax);
-    }
+  for (int i = 0; i < count; i++) {
+    elements_.Add(FrameElement(Factory::undefined_value()));
    }
  }

@@ -154,22 +225,19 @@


  void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) {
-  ASSERT(height() >= frame_arg_count);
-  Forget(frame_arg_count);
+  PrepareForCall(frame_arg_count);
    __ CallStub(stub);
  }


  void VirtualFrame::CallRuntime(Runtime::Function* f, int frame_arg_count) {
-  ASSERT(height() >= frame_arg_count);
-  Forget(frame_arg_count);
+  PrepareForCall(frame_arg_count);
    __ CallRuntime(f, frame_arg_count);
  }


  void VirtualFrame::CallRuntime(Runtime::FunctionId id, int  
frame_arg_count) {
-  ASSERT(height() >= frame_arg_count);
-  Forget(frame_arg_count);
+  PrepareForCall(frame_arg_count);
    __ CallRuntime(id, frame_arg_count);
  }

@@ -177,8 +245,7 @@
  void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
                                   InvokeFlag flag,
                                   int frame_arg_count) {
-  ASSERT(height() >= frame_arg_count);
-  Forget(frame_arg_count);
+  PrepareForCall(frame_arg_count);
    __ InvokeBuiltin(id, flag);
  }

@@ -186,14 +253,20 @@
  void VirtualFrame::CallCodeObject(Handle<Code> code,
                                    RelocInfo::Mode rmode,
                                    int frame_arg_count) {
-  ASSERT(height() >= frame_arg_count);
-  Forget(frame_arg_count);
+  PrepareForCall(frame_arg_count);
    __ call(code, rmode);
  }


  void VirtualFrame::Drop(int count) {
    ASSERT(height() >= count);
+
+  // Discard elements above the stack pointer.
+  while (count > 0 && stack_pointer_ < elements_.length() - 1) {
+    elements_.RemoveLast();
+  }
+
+  // Discard the rest of the elements and lower the stack pointer.
    Forget(count);
    if (count > 0) {
      __ add(Operand(esp), Immediate(count * kPointerSize));
@@ -204,34 +277,45 @@
  void VirtualFrame::Drop() { Drop(1); }


-void VirtualFrame::Pop(Register reg) {
-  Forget(1);
+void VirtualFrame::EmitPop(Register reg) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  stack_pointer_--;
+  elements_.RemoveLast();
    __ pop(reg);
  }


-void VirtualFrame::Pop(Operand operand) {
-  Forget(1);
+void VirtualFrame::EmitPop(Operand operand) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  stack_pointer_--;
+  elements_.RemoveLast();
    __ pop(operand);
  }


  void VirtualFrame::EmitPush(Register reg) {
-  Adjust(1);
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  elements_.Add(FrameElement());
+  stack_pointer_++;
    __ push(reg);
  }


  void VirtualFrame::EmitPush(Operand operand) {
-  Adjust(1);
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  elements_.Add(FrameElement());
+  stack_pointer_++;
    __ push(operand);
  }


  void VirtualFrame::EmitPush(Immediate immediate) {
-  Adjust(1);
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  elements_.Add(FrameElement());
+  stack_pointer_++;
    __ push(immediate);
  }
+

  #undef __


Modified: branches/experimental/toiger/src/virtual-frame-ia32.h
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.h       (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.h       Wed Nov 19  
01:06:36 2008
@@ -39,11 +39,50 @@
  // only one kind, in-memory.  Their actual location is given by their
  // position in the virtual frame.

-class Element BASE_EMBEDDED {
+class FrameElement BASE_EMBEDDED {
   public:
-  Element() {}
+  enum Type { MEMORY, CONSTANT, LAST_TYPE = CONSTANT };

-  bool matches(const Element& other) { return true; }
+  FrameElement() : type_(MEMORY) {}
+
+  explicit FrameElement(Handle<Object> value) : type_(CONSTANT |  
kDirtyBit) {
+    data_.handle_ = value.location();
+  }
+
+  Type type() const { return static_cast<Type>(type_ & kTypeMask); }
+
+  bool is_dirty() const {
+    STATIC_ASSERT(kDirtyBit > LAST_TYPE);
+    return (type_ & kDirtyBit) != 0;
+  }
+
+  void set_dirty() {
+    ASSERT(type() != MEMORY);
+    type_ = type_ | kDirtyBit;
+  }
+
+  void clear_dirty() {
+    ASSERT(type() != MEMORY);
+    type_ = type_ & ~kDirtyBit;
+  }
+
+  Handle<Object> handle() const {
+    ASSERT(type() == CONSTANT);
+    return Handle<Object>(data_.handle_);
+  }
+
+ private:
+  static const int kDirtyBit = 1 << 8;
+  static const int kTypeMask = kDirtyBit - 1;
+
+  // The element's type and a dirty bit.  The dirty bit can be cleared
+  // for non-memory elements to indicate that the element agrees with
+  // the value in memory in the actual frame.
+  int type_;
+
+  union {
+    Object** handle_;
+  } data_;
  };


@@ -58,12 +97,10 @@

  class VirtualFrame : public Malloced {
   public:
-  // Construct a virtual frame with the given code generator used to
-  // generate code.
+  // Construct an initial virtual frame on entry to a JS function.
    explicit VirtualFrame(CodeGenerator* cgen);

-  // Construct a virtual frame that is a clone of an existing one,  
initially
-  // with an identical state.
+  // Construct a virtual frame as a clone of an existing one.
    explicit VirtualFrame(VirtualFrame* original);

    // The height of the virtual expression stack.
@@ -71,13 +108,22 @@
      return elements_.length() - expression_base_index();
    }

-  // Add extra in-memory elements to the top of the frame without  
generating
-  // code.
+  // Add extra in-memory elements to the top of the frame to match an  
actual
+  // frame (eg, the frame after an exception handler is pushed).  No code  
is
+  // emitted.
    void Adjust(int count);

-  // Forget frame elements without generating code.
+  // Forget elements from the top of the frame to match an actual frame  
(eg,
+  // the frame after a runtime call).  No code is emitted.
    void Forget(int count);

+  // Spill all values from the frame to memory.
+  void SpillAll();
+
+  // Ensure that this frame is in a state where an arbitrary frame of the
+  // right size could be merged to it.  May emit code.
+  void EnsureMergable();
+
    // Make this virtual frame have a state identical to an expected virtual
    // frame.  As a side effect, code may be emitted to make this frame match
    // the expected one.
@@ -158,10 +204,10 @@
    // Drop one element.
    void Drop();

-  // Pop and save an element from the top of the expression stack.  May  
emit
-  // code.
-  void Pop(Register reg);
-  void Pop(Operand operand);
+  // Pop and save an element from the top of the expression stack and emit  
a
+  // corresponding pop instruction.
+  void EmitPop(Register reg);
+  void EmitPop(Operand operand);

    // Push an element on top of the expression stack and emit a  
corresponding
    // push instruction.
@@ -170,6 +216,9 @@
    void EmitPush(Immediate immediate);

   private:
+  // An illegal index into the virtual frame.
+  static const int kIllegalIndex = -1;
+
    static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
    static const int kFunctionOffset =  
JavaScriptFrameConstants::kFunctionOffset;
    static const int kContextOffset = StandardFrameConstants::kContextOffset;
@@ -178,11 +227,17 @@

    MacroAssembler* masm_;

-  List<Element> elements_;
+  List<FrameElement> elements_;

    int parameter_count_;
    int local_count_;

+  // The index of the element that is at the processor's stack pointer
+  // (the esp register).
+  int stack_pointer_;
+
+  // The index of the element that is at the processor's frame pointer
+  // (the ebp register).
    int frame_pointer_;

    // The index of the first parameter.  The receiver lies below the first
@@ -196,6 +251,16 @@

    // The index of the base of the expression stack.
    int expression_base_index() const { return local0_index() +  
local_count_; }
+
+  // Convert a frame index into a frame pointer relative offset into the
+  // actual stack.
+  int fp_relative(int index) const {
+    return (frame_pointer_ - index) * kPointerSize;
+  }
+
+  // Spill the topmost elements of the frame to memory (eg, they are the
+  // arguments to a call) and all registers.
+  void PrepareForCall(int count);
  };



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

Reply via email to