| Index: src/codegen-ia32.cc
 | 
| ===================================================================
 | 
| --- src/codegen-ia32.cc	(revision 469)
 | 
| +++ src/codegen-ia32.cc	(working copy)
 | 
| @@ -894,18 +894,8 @@
 | 
|    void Generate(MacroAssembler* masm);
 | 
|  
 | 
|   private:
 | 
| -
 | 
|    Major MajorKey() { return ToBoolean; }
 | 
| -
 | 
|    int MinorKey() { return 0; }
 | 
| -
 | 
| -  const char* GetName() { return "ToBooleanStub"; }
 | 
| -
 | 
| -#ifdef DEBUG
 | 
| -  void Print() {
 | 
| -    PrintF("ToBooleanStub\n");
 | 
| -  }
 | 
| -#endif
 | 
|  };
 | 
|  
 | 
|  
 | 
| @@ -1476,8 +1466,6 @@
 | 
|      return (static_cast<int>(cc_) << 1) | (strict_ ? 1 : 0);
 | 
|    }
 | 
|  
 | 
| -  const char* GetName() { return "CompareStub"; }
 | 
| -
 | 
|  #ifdef DEBUG
 | 
|    void Print() {
 | 
|      PrintF("CompareStub (cc %d), (strict %s)\n",
 | 
| @@ -1585,8 +1573,6 @@
 | 
|   private:
 | 
|    int argc_;
 | 
|  
 | 
| -  const char* GetName() { return "CallFunctionStub"; }
 | 
| -
 | 
|  #ifdef DEBUG
 | 
|    void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
 | 
|  #endif
 | 
| @@ -3521,8 +3507,6 @@
 | 
|    int MinorKey() { return is_increment_ ? 1 : 0; }
 | 
|    void Generate(MacroAssembler* masm);
 | 
|  
 | 
| -  const char* GetName() { return "RevertToNumberStub"; }
 | 
| -
 | 
|  #ifdef DEBUG
 | 
|    void Print() {
 | 
|      PrintF("RevertToNumberStub (is_increment %s)\n",
 | 
| @@ -3552,8 +3536,6 @@
 | 
|    }
 | 
|    void Generate(MacroAssembler* masm);
 | 
|  
 | 
| -  const char* GetName() { return "CounterOpStub"; }
 | 
| -
 | 
|  #ifdef DEBUG
 | 
|    void Print() {
 | 
|      PrintF("CounterOpStub (result_offset %d), (is_postfix %s),"
 | 
| @@ -3754,6 +3736,18 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +class InstanceofStub: public CodeStub {
 | 
| + public:
 | 
| +  InstanceofStub() { }
 | 
| +
 | 
| +  void Generate(MacroAssembler* masm);
 | 
| +
 | 
| + private:
 | 
| +  Major MajorKey() { return Instanceof; }
 | 
| +  int MinorKey() { return 0; }
 | 
| +};
 | 
| +
 | 
| +
 | 
|  void Ia32CodeGenerator::VisitCompareOperation(CompareOperation* node) {
 | 
|    Comment cmnt(masm_, "[ CompareOperation");
 | 
|  
 | 
| @@ -3934,8 +3928,10 @@
 | 
|      case Token::INSTANCEOF: {
 | 
|        Load(left);
 | 
|        Load(right);
 | 
| -      __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
 | 
| -      __ push(eax);  // push the result
 | 
| +      InstanceofStub stub;
 | 
| +      __ CallStub(&stub);
 | 
| +      __ test(eax, Operand(eax));
 | 
| +      cc_reg_ = zero;
 | 
|        return;
 | 
|      }
 | 
|      default:
 | 
| @@ -5289,6 +5285,53 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void InstanceofStub::Generate(MacroAssembler* masm) {
 | 
| +  // Get the object - go slow case if it's a smi.
 | 
| +  Label slow;
 | 
| +  __ mov(eax, Operand(esp, 2 * kPointerSize));  // 2 ~ return address, function
 | 
| +  __ test(eax, Immediate(kSmiTagMask));
 | 
| +  __ j(zero, &slow, not_taken);
 | 
| +
 | 
| +  // Check that the left hand is a JS object.
 | 
| +  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));  // ebx - object map
 | 
| +  __ movzx_b(ecx, FieldOperand(eax, Map::kInstanceTypeOffset));  // ecx - type
 | 
| +  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
 | 
| +  __ j(less, &slow, not_taken);
 | 
| +  __ cmp(ecx, LAST_JS_OBJECT_TYPE);
 | 
| +  __ j(greater, &slow, not_taken);
 | 
| +
 | 
| +  // Get the prototype of the function.
 | 
| +  __ mov(edx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address
 | 
| +  __ TryGetFunctionPrototype(edx, ebx, ecx, &slow);
 | 
| +
 | 
| +  // Register mapping: eax is object map and ebx is function prototype.
 | 
| +  __ mov(ecx, FieldOperand(eax, Map::kPrototypeOffset));
 | 
| +
 | 
| +  // Loop through the prototype chain looking for the function prototype.
 | 
| +  Label loop, is_instance, is_not_instance;
 | 
| +  __ bind(&loop);
 | 
| +  __ cmp(ecx, Operand(ebx));
 | 
| +  __ j(equal, &is_instance);
 | 
| +  __ cmp(Operand(ecx), Immediate(Factory::null_value()));
 | 
| +  __ j(equal, &is_not_instance);
 | 
| +  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
 | 
| +  __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset));
 | 
| +  __ jmp(&loop);
 | 
| +
 | 
| +  __ bind(&is_instance);
 | 
| +  __ Set(eax, Immediate(0));
 | 
| +  __ ret(2 * kPointerSize);
 | 
| +
 | 
| +  __ bind(&is_not_instance);
 | 
| +  __ Set(eax, Immediate(Smi::FromInt(1)));
 | 
| +  __ ret(2 * kPointerSize);
 | 
| +
 | 
| +  // Slow-case: Go through the JavaScript implementation.
 | 
| +  __ bind(&slow);
 | 
| +  __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  #undef __
 | 
|  
 | 
|  // -----------------------------------------------------------------------------
 | 
| 
 |