| Index: src/mips/full-codegen-mips.cc
 | 
| ===================================================================
 | 
| --- src/mips/full-codegen-mips.cc	(revision 9531)
 | 
| +++ src/mips/full-codegen-mips.cc	(working copy)
 | 
| @@ -62,9 +62,11 @@
 | 
|  // A patch site is a location in the code which it is possible to patch. This
 | 
|  // class has a number of methods to emit the code which is patchable and the
 | 
|  // method EmitPatchInfo to record a marker back to the patchable code. This
 | 
| -// marker is a andi at, rx, #yyy instruction, and x * 0x0000ffff + yyy (raw 16
 | 
| -// bit immediate value is used) is the delta from the pc to the first
 | 
| +// marker is a andi zero_reg, rx, #yyyy instruction, and rx * 0x0000ffff + yyyy
 | 
| +// (raw 16 bit immediate value is used) is the delta from the pc to the first
 | 
|  // instruction of the patchable code.
 | 
| +// The marker instruction is effectively a NOP (dest is zero_reg) and will
 | 
| +// never be emitted by normal code.
 | 
|  class JumpPatchSite BASE_EMBEDDED {
 | 
|   public:
 | 
|    explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
 | 
| @@ -103,7 +105,7 @@
 | 
|      if (patch_site_.is_bound()) {
 | 
|        int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
 | 
|        Register reg = Register::from_code(delta_to_patch_site / kImm16Mask);
 | 
| -      __ andi(at, reg, delta_to_patch_site % kImm16Mask);
 | 
| +      __ andi(zero_reg, reg, delta_to_patch_site % kImm16Mask);
 | 
|  #ifdef DEBUG
 | 
|        info_emitted_ = true;
 | 
|  #endif
 | 
| @@ -162,6 +164,11 @@
 | 
|      __ bind(&ok);
 | 
|    }
 | 
|  
 | 
| +  // Open a frame scope to indicate that there is a frame on the stack.  The
 | 
| +  // MANUAL indicates that the scope shouldn't actually generate code to set up
 | 
| +  // the frame (that is done below).
 | 
| +  FrameScope frame_scope(masm_, StackFrame::MANUAL);
 | 
| +
 | 
|    int locals_count = info->scope()->num_stack_slots();
 | 
|  
 | 
|    __ Push(ra, fp, cp, a1);
 | 
| @@ -310,17 +317,25 @@
 | 
|  
 | 
|  
 | 
|  void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
 | 
| +  // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need
 | 
| +  // to make sure it is constant. Branch may emit a skip-or-jump sequence
 | 
| +  // instead of the normal Branch. It seems that the "skip" part of that
 | 
| +  // sequence is about as long as this Branch would be so it is safe to ignore
 | 
| +  // that.
 | 
| +  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
 | 
|    Comment cmnt(masm_, "[ Stack check");
 | 
|    Label ok;
 | 
|    __ LoadRoot(t0, Heap::kStackLimitRootIndex);
 | 
| -  __ Branch(&ok, hs, sp, Operand(t0));
 | 
| +  __ sltu(at, sp, t0);
 | 
| +  __ beq(at, zero_reg, &ok);
 | 
| +  // CallStub will emit a li t9, ... first, so it is safe to use the delay slot.
 | 
|    StackCheckStub stub;
 | 
| +  __ CallStub(&stub);
 | 
|    // Record a mapping of this PC offset to the OSR id.  This is used to find
 | 
|    // the AST id from the unoptimized code in order to use it as a key into
 | 
|    // the deoptimization input data found in the optimized code.
 | 
|    RecordStackCheck(stmt->OsrEntryId());
 | 
|  
 | 
| -  __ CallStub(&stub);
 | 
|    __ bind(&ok);
 | 
|    PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
 | 
|    // Record a mapping of the OSR id to this PC.  This is used if the OSR
 | 
| @@ -3921,10 +3936,14 @@
 | 
|  }
 | 
|  
 | 
|  void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
 | 
| -                                                 Handle<String> check,
 | 
| -                                                 Label* if_true,
 | 
| -                                                 Label* if_false,
 | 
| -                                                 Label* fall_through) {
 | 
| +                                                 Handle<String> check) {
 | 
| +  Label materialize_true, materialize_false;
 | 
| +  Label* if_true = NULL;
 | 
| +  Label* if_false = NULL;
 | 
| +  Label* fall_through = NULL;
 | 
| +  context()->PrepareTest(&materialize_true, &materialize_false,
 | 
| +                         &if_true, &if_false, &fall_through);
 | 
| +
 | 
|    { AccumulatorValueContext context(this);
 | 
|      VisitForTypeofValue(expr);
 | 
|    }
 | 
| @@ -3986,28 +4005,20 @@
 | 
|    } else {
 | 
|      if (if_false != fall_through) __ jmp(if_false);
 | 
|    }
 | 
| +  context()->Plug(if_true, if_false);
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void FullCodeGenerator::EmitLiteralCompareUndefined(Expression* expr,
 | 
| -                                                    Label* if_true,
 | 
| -                                                    Label* if_false,
 | 
| -                                                    Label* fall_through) {
 | 
| -  VisitForAccumulatorValue(expr);
 | 
| -  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 | 
| -
 | 
| -  __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
 | 
| -  Split(eq, v0, Operand(at), if_true, if_false, fall_through);
 | 
| -}
 | 
| -
 | 
| -
 | 
|  void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
 | 
|    Comment cmnt(masm_, "[ CompareOperation");
 | 
|    SetSourcePosition(expr->position());
 | 
|  
 | 
| +  // First we try a fast inlined version of the compare when one of
 | 
| +  // the operands is a literal.
 | 
| +  if (TryLiteralCompare(expr)) return;
 | 
| +
 | 
|    // Always perform the comparison for its control flow.  Pack the result
 | 
|    // into the expression's context after the comparison is performed.
 | 
| -
 | 
|    Label materialize_true, materialize_false;
 | 
|    Label* if_true = NULL;
 | 
|    Label* if_false = NULL;
 | 
| @@ -4015,13 +4026,6 @@
 | 
|    context()->PrepareTest(&materialize_true, &materialize_false,
 | 
|                           &if_true, &if_false, &fall_through);
 | 
|  
 | 
| -  // First we try a fast inlined version of the compare when one of
 | 
| -  // the operands is a literal.
 | 
| -  if (TryLiteralCompare(expr, if_true, if_false, fall_through)) {
 | 
| -    context()->Plug(if_true, if_false);
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
|    Token::Value op = expr->op();
 | 
|    VisitForStackValue(expr->left());
 | 
|    switch (op) {
 | 
| @@ -4046,11 +4050,8 @@
 | 
|      default: {
 | 
|        VisitForAccumulatorValue(expr->right());
 | 
|        Condition cc = eq;
 | 
| -      bool strict = false;
 | 
|        switch (op) {
 | 
|          case Token::EQ_STRICT:
 | 
| -          strict = true;
 | 
| -          // Fall through.
 | 
|          case Token::EQ:
 | 
|            cc = eq;
 | 
|            __ mov(a0, result_register());
 | 
| @@ -4109,8 +4110,9 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
 | 
| -  Comment cmnt(masm_, "[ CompareToNull");
 | 
| +void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
 | 
| +                                              Expression* sub_expr,
 | 
| +                                              NilValue nil) {
 | 
|    Label materialize_true, materialize_false;
 | 
|    Label* if_true = NULL;
 | 
|    Label* if_false = NULL;
 | 
| @@ -4118,15 +4120,21 @@
 | 
|    context()->PrepareTest(&materialize_true, &materialize_false,
 | 
|                           &if_true, &if_false, &fall_through);
 | 
|  
 | 
| -  VisitForAccumulatorValue(expr->expression());
 | 
| +  VisitForAccumulatorValue(sub_expr);
 | 
|    PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 | 
| +  Heap::RootListIndex nil_value = nil == kNullValue ?
 | 
| +      Heap::kNullValueRootIndex :
 | 
| +      Heap::kUndefinedValueRootIndex;
 | 
|    __ mov(a0, result_register());
 | 
| -  __ LoadRoot(a1, Heap::kNullValueRootIndex);
 | 
| -  if (expr->is_strict()) {
 | 
| +  __ LoadRoot(a1, nil_value);
 | 
| +  if (expr->op() == Token::EQ_STRICT) {
 | 
|      Split(eq, a0, Operand(a1), if_true, if_false, fall_through);
 | 
|    } else {
 | 
| +    Heap::RootListIndex other_nil_value = nil == kNullValue ?
 | 
| +        Heap::kUndefinedValueRootIndex :
 | 
| +        Heap::kNullValueRootIndex;
 | 
|      __ Branch(if_true, eq, a0, Operand(a1));
 | 
| -    __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
 | 
| +    __ LoadRoot(a1, other_nil_value);
 | 
|      __ Branch(if_true, eq, a0, Operand(a1));
 | 
|      __ And(at, a0, Operand(kSmiTagMask));
 | 
|      __ Branch(if_false, eq, at, Operand(zero_reg));
 | 
| 
 |