Desugar bitwise negation into XOR and kill all UnaryOp stuff.
authorsvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 6 Aug 2013 13:34:51 +0000 (13:34 +0000)
committersvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 6 Aug 2013 13:34:51 +0000 (13:34 +0000)
R=mstarzinger@chromium.org, verwaest@chromium.org

Review URL: https://codereview.chromium.org/22184004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16073 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

50 files changed:
src/arm/code-stubs-arm.cc
src/arm/full-codegen-arm.cc
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/arm/lithium-codegen-arm.h
src/ast.cc
src/ast.h
src/builtins.h
src/code-stubs-hydrogen.cc
src/code-stubs.cc
src/code-stubs.h
src/debug.cc
src/full-codegen.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen-uint32-analysis.cc
src/hydrogen.cc
src/hydrogen.h
src/ia32/code-stubs-ia32.cc
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.h
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/ic.cc
src/ic.h
src/log.cc
src/mips/assembler-mips.h
src/mips/code-stubs-mips.cc
src/mips/full-codegen-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-codegen-mips.h
src/mips/lithium-mips.cc
src/mips/lithium-mips.h
src/objects-inl.h
src/objects.h
src/parser.cc
src/runtime.cc
src/runtime.h
src/runtime.js
src/type-info.cc
src/type-info.h
src/typing.cc
src/x64/code-stubs-x64.cc
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-codegen-x64.h
src/x64/lithium-x64.cc
src/x64/lithium-x64.h

index 288e18f32795c698ace766e6dfda05e89dea29d5..98a835fd1a5adb0b3b461a92edd452a49566020a 100644 (file)
@@ -246,17 +246,6 @@ void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
 }
 
 
-void UnaryOpStub::InitializeInterfaceDescriptor(
-    Isolate* isolate,
-    CodeStubInterfaceDescriptor* descriptor) {
-  static Register registers[] = { r0 };
-  descriptor->register_param_count_ = 1;
-  descriptor->register_params_ = registers;
-  descriptor->deoptimization_handler_ =
-      FUNCTION_ADDR(UnaryOpIC_Miss);
-}
-
-
 void StoreGlobalStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
index dd347928d7416b6296afcba1a6198b40d7ae15da..b73006a17d99136d69d5b8a782ae3134fdd20675 100644 (file)
@@ -4349,32 +4349,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       break;
     }
 
-    case Token::BIT_NOT:
-      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
-      break;
-
     default:
       UNREACHABLE();
   }
 }
 
 
-void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
-                                           const char* comment) {
-  ASSERT_EQ(Token::BIT_NOT, expr->op());
-  // TODO(svenpanne): Allowing format strings in Comment would be nice here...
-  Comment cmt(masm_, comment);
-  UnaryOpStub stub(expr->op());
-  // UnaryOpStub expects the argument to be in the
-  // accumulator register r0.
-  VisitForAccumulatorValue(expr->expression());
-  SetSourcePosition(expr->position());
-  CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
-         expr->UnaryOperationFeedbackId());
-  context()->Plug(r0);
-}
-
-
 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
index 048840f10b2945bc63ea26e6facaf9d879484aea..43f0fd32931fd9660a681e70ca8ee54babc3e345 100644 (file)
@@ -1325,15 +1325,6 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
-  ASSERT(instr->value()->representation().IsInteger32());
-  ASSERT(instr->representation().IsInteger32());
-  if (instr->HasNoUses()) return NULL;
-  LOperand* value = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new(zone()) LBitNotI(value));
-}
-
-
 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
index db2d898a8593b794ac2890f49e4bce7494566241..7ce907a7abf77dea9cbbb3383561ff32a1a0de29 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -1377,18 +1376,6 @@ class LThrow: public LTemplateInstruction<0, 1, 0> {
 };
 
 
-class LBitNotI: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LBitNotI(LOperand* value) {
-    inputs_[0] = value;
-  }
-
-  LOperand* value() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
-};
-
-
 class LAddI: public LTemplateInstruction<1, 2, 0> {
  public:
   LAddI(LOperand* left, LOperand* right) {
index 6ca8851337cc5350ff0ed64e4a0c87c0530b0c8f..0b704d07ef5749cf056d2584e84815f7e3b03a59 100644 (file)
@@ -1669,7 +1669,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
       __ orr(result, left, right);
       break;
     case Token::BIT_XOR:
-      __ eor(result, left, right);
+      if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
+        __ mvn(result, Operand(left));
+      } else {
+        __ eor(result, left, right);
+      }
       break;
     default:
       UNREACHABLE();
@@ -1953,13 +1957,6 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
 }
 
 
-void LCodeGen::DoBitNotI(LBitNotI* instr) {
-  Register input = ToRegister(instr->value());
-  Register result = ToRegister(instr->result());
-  __ mvn(result, Operand(input));
-}
-
-
 void LCodeGen::DoThrow(LThrow* instr) {
   Register input_reg = EmitLoadRegister(instr->value(), ip);
   __ push(input_reg);
index 6125e27e2832b48c4558a8d33d9a81bd292737d3..143109c92da2f0d2b5c114a994645102e5a61746 100644 (file)
@@ -115,7 +115,7 @@ class LCodeGen BASE_EMBEDDED {
   DwVfpRegister EmitLoadDoubleRegister(LOperand* op,
                                        SwVfpRegister flt_scratch,
                                        DwVfpRegister dbl_scratch);
-  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
index f99eaef40f048974d1fbf9246ac8b04aef757333..2077f87d74153ba31e6fc94250a89508c3aeddda 100644 (file)
@@ -304,16 +304,6 @@ void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
 }
 
 
-bool UnaryOperation::ResultOverwriteAllowed() {
-  switch (op_) {
-    case Token::BIT_NOT:
-      return true;
-    default:
-      return false;
-  }
-}
-
-
 void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
   // TODO(olivf) If this Operation is used in a test context, then the right
   // hand side has a ToBoolean stub and we want to collect the type information.
index db8cb2e3676d053f9ac1243d2de596a140c04162..a8b74213adb663dce6c0fb3bad9ae8c45ea8a648 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1847,8 +1847,6 @@ class UnaryOperation: public Expression {
  public:
   DECLARE_NODE_TYPE(UnaryOperation)
 
-  virtual bool ResultOverwriteAllowed();
-
   Token::Value op() const { return op_; }
   Expression* expression() const { return expression_; }
   virtual int position() const { return pos_; }
@@ -1856,8 +1854,6 @@ class UnaryOperation: public Expression {
   BailoutId MaterializeTrueId() { return materialize_true_id_; }
   BailoutId MaterializeFalseId() { return materialize_false_id_; }
 
-  TypeFeedbackId UnaryOperationFeedbackId() const { return reuse(id()); }
-
   virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
 
  protected:
index 6a6ce9c294468b2d677a1f7c0f581a147ec42ff7..bb36c0251d972b247c9010a588c22fcf5225195b 100644 (file)
@@ -259,7 +259,6 @@ enum BuiltinExtraArguments {
   V(BIT_OR, 1)                           \
   V(BIT_AND, 1)                          \
   V(BIT_XOR, 1)                          \
-  V(BIT_NOT, 0)                          \
   V(SHL, 1)                              \
   V(SAR, 1)                              \
   V(SHR, 1)                              \
index 33681ed0999db60e764645b4a5fb03703e062e0e..852f7b569727b08939d1c952146699d6ff4999f7 100644 (file)
@@ -801,45 +801,6 @@ Handle<Code> CompareNilICStub::GenerateCode() {
 }
 
 
-template <>
-HValue* CodeStubGraphBuilder<UnaryOpStub>::BuildCodeInitializedStub() {
-  UnaryOpStub* stub = casted_stub();
-  ASSERT_EQ(Token::BIT_NOT, stub->operation());
-  Handle<Type> type = stub->GetType(graph()->isolate());
-  HValue* input = GetParameter(0);
-
-  // Prevent unwanted HChange being inserted to ensure that the stub
-  // deopts on newly encountered types.
-  if (!type->Maybe(Type::Double())) {
-    input = Add<HForceRepresentation>(input, Representation::Smi());
-  }
-
-  if (!type->Is(Type::Number())) {
-    // If we expect to see other things than Numbers, we will create a generic
-    // stub, which handles all numbers and calls into the runtime for the rest.
-    IfBuilder if_number(this);
-    if_number.If<HIsNumberAndBranch>(input);
-    if_number.Then();
-    HInstruction* res = BuildUnaryMathOp(input, type, stub->operation());
-    if_number.Return(AddInstruction(res));
-    if_number.Else();
-    HValue* function = AddLoadJSBuiltin(stub->ToJSBuiltin());
-    Add<HPushArgument>(GetParameter(0));
-    HValue* result = Add<HInvokeFunction>(function, 1);
-    if_number.Return(result);
-    if_number.End();
-    return graph()->GetConstantUndefined();
-  }
-
-  return AddInstruction(BuildUnaryMathOp(input, type, stub->operation()));
-}
-
-
-Handle<Code> UnaryOpStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
 template <>
 HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
   ToBooleanStub* stub = casted_stub();
index 4def2b572f940f9861ffc7a402ab649af849b5b5..d472fa287f0c03c0a40180267b6da29828c16325 100644 (file)
@@ -204,65 +204,6 @@ void CodeStub::PrintName(StringStream* stream) {
 }
 
 
-Builtins::JavaScript UnaryOpStub::ToJSBuiltin() {
-  switch (operation_) {
-    default:
-      UNREACHABLE();
-    case Token::BIT_NOT:
-      return Builtins::BIT_NOT;
-  }
-}
-
-
-Handle<JSFunction> UnaryOpStub::ToJSFunction(Isolate* isolate) {
-  Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
-  Object* builtin = builtins->javascript_builtin(ToJSBuiltin());
-  return Handle<JSFunction>(JSFunction::cast(builtin), isolate);
-}
-
-
-MaybeObject* UnaryOpStub::Result(Handle<Object> object, Isolate* isolate) {
-  Handle<JSFunction> builtin_function = ToJSFunction(isolate);
-  bool caught_exception;
-  Handle<Object> result = Execution::Call(builtin_function, object,
-                                          0, NULL, &caught_exception);
-  if (caught_exception) {
-    return Failure::Exception();
-  }
-  return *result;
-}
-
-
-void UnaryOpStub::UpdateStatus(Handle<Object> object) {
-  State old_state(state_);
-  if (object->IsSmi()) {
-    state_.Add(SMI);
-  } else if (object->IsHeapNumber()) {
-    state_.Add(HEAP_NUMBER);
-  } else {
-    state_.Add(GENERIC);
-  }
-  TraceTransition(old_state, state_);
-}
-
-
-Handle<Type> UnaryOpStub::GetType(Isolate* isolate) {
-  if (state_.Contains(GENERIC)) {
-    return handle(Type::Any(), isolate);
-  }
-  Handle<Type> type = handle(Type::None(), isolate);
-  if (state_.Contains(SMI)) {
-    type = handle(
-        Type::Union(type, handle(Type::Smi(), isolate)), isolate);
-  }
-  if (state_.Contains(HEAP_NUMBER)) {
-    type = handle(
-        Type::Union(type, handle(Type::Double(), isolate)), isolate);
-  }
-  return type;
-}
-
-
 void BinaryOpStub::Generate(MacroAssembler* masm) {
   // Explicitly allow generation of nested stubs. It is safe here because
   // generation code does not use any raw pointers.
@@ -348,28 +289,6 @@ void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
 #undef __
 
 
-void UnaryOpStub::PrintBaseName(StringStream* stream) {
-  CodeStub::PrintBaseName(stream);
-  if (operation_ == Token::BIT_NOT) stream->Add("Not");
-}
-
-
-void UnaryOpStub::PrintState(StringStream* stream) {
-  state_.Print(stream);
-}
-
-
-void UnaryOpStub::State::Print(StringStream* stream) const {
-  stream->Add("(");
-  SimpleListPrinter printer(stream);
-  if (IsEmpty()) printer.Add("None");
-  if (Contains(GENERIC)) printer.Add("Generic");
-  if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
-  if (Contains(SMI)) printer.Add("Smi");
-  stream->Add(")");
-}
-
-
 void BinaryOpStub::PrintName(StringStream* stream) {
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
index 84d9b023b3a237b36aee866c75b1ed5119e20d76..c58acd6b16d4674a2b4da3f7a49d6ceca0c62cfe 100644 (file)
@@ -40,7 +40,6 @@ namespace internal {
 #define CODE_STUB_LIST_ALL_PLATFORMS(V)  \
   V(CallFunction)                        \
   V(CallConstruct)                       \
-  V(UnaryOp)                             \
   V(BinaryOp)                            \
   V(StringAdd)                           \
   V(SubString)                           \
@@ -593,73 +592,6 @@ class StoreGlobalStub : public HydrogenCodeStub {
 };
 
 
-class UnaryOpStub : public HydrogenCodeStub {
- public:
-  // Stub without type info available -> construct uninitialized
-  explicit UnaryOpStub(Token::Value operation)
-      : HydrogenCodeStub(UNINITIALIZED), operation_(operation) { }
-  explicit UnaryOpStub(Code::ExtraICState ic_state) :
-      state_(StateBits::decode(ic_state)),
-      operation_(OperatorBits::decode(ic_state)) { }
-
-  virtual void InitializeInterfaceDescriptor(
-      Isolate* isolate,
-      CodeStubInterfaceDescriptor* descriptor);
-
-  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
-  virtual InlineCacheState GetICState() {
-    if (state_.Contains(GENERIC)) {
-      return MEGAMORPHIC;
-    } else if (state_.IsEmpty()) {
-      return PREMONOMORPHIC;
-    } else {
-      return MONOMORPHIC;
-    }
-  }
-  virtual Code::ExtraICState GetExtraICState() {
-    return OperatorBits::encode(operation_) |
-           StateBits::encode(state_.ToIntegral());
-  }
-
-  Token::Value operation() { return operation_; }
-  Handle<JSFunction> ToJSFunction(Isolate* isolate);
-  Builtins::JavaScript ToJSBuiltin();
-
-  void UpdateStatus(Handle<Object> object);
-  MaybeObject* Result(Handle<Object> object, Isolate* isolate);
-  Handle<Code> GenerateCode();
-  Handle<Type> GetType(Isolate* isolate);
-
- protected:
-  void PrintState(StringStream* stream);
-  void PrintBaseName(StringStream* stream);
-
- private:
-  enum UnaryOpType {
-    SMI,
-    HEAP_NUMBER,
-    GENERIC,
-    NUMBER_OF_TYPES
-  };
-
-  class State : public EnumSet<UnaryOpType, byte> {
-   public:
-    State() : EnumSet<UnaryOpType, byte>() { }
-    explicit State(byte bits) : EnumSet<UnaryOpType, byte>(bits) { }
-    void Print(StringStream* stream) const;
-  };
-
-  class StateBits : public BitField<int, 0, NUMBER_OF_TYPES> { };
-  class OperatorBits : public BitField<Token::Value, NUMBER_OF_TYPES, 8> { };
-
-  State state_;
-  Token::Value operation_;
-
-  virtual CodeStub::Major MajorKey() { return UnaryOp; }
-  virtual int NotMissMinorKey() { return GetExtraICState(); }
-};
-
-
 class FastCloneShallowArrayStub : public HydrogenCodeStub {
  public:
   // Maximum length of copied elements array.
index a0b9884410f289302d7d74be6e65bfb62ef1a413..a349502343ef532fb3cb40b4976a14e8c0c05a53 100644 (file)
@@ -159,7 +159,6 @@ void BreakLocationIterator::Next() {
       Code* code = Code::GetCodeFromTargetAddress(target);
       if ((code->is_inline_cache_stub() &&
            !code->is_binary_op_stub() &&
-           !code->is_unary_op_stub() &&
            !code->is_compare_ic_stub() &&
            !code->is_to_boolean_ic_stub()) ||
           RelocInfo::IsConstructCall(rmode())) {
index a9db54e32c18284b17f510d3384c55abebeab0f3..5b9698a7cc918eac8bb5bf66cfc2eeda76e55089 100644 (file)
@@ -625,8 +625,6 @@ class FullCodeGenerator: public AstVisitor {
   AST_NODE_LIST(DECLARE_VISIT)
 #undef DECLARE_VISIT
 
-  void EmitUnaryOperation(UnaryOperation* expr, const char* comment);
-
   void VisitComma(BinaryOperation* expr);
   void VisitLogicalExpression(BinaryOperation* expr);
   void VisitArithmeticExpression(BinaryOperation* expr);
index 28511f714208f6fcc9eb84a4d1812723f09ba01b..997b7c2fda9b29455d03faac59c5a49a60d18d5c 100644 (file)
@@ -1155,6 +1155,29 @@ void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
 }
 
 
+static bool MatchLeftIsOnes(HValue* l, HValue* r, HValue** negated) {
+  if (!l->EqualsInteger32Constant(~0)) return false;
+  *negated = r;
+  return true;
+}
+
+
+static bool MatchNegationViaXor(HValue* instr, HValue** negated) {
+  if (!instr->IsBitwise()) return false;
+  HBitwise* b = HBitwise::cast(instr);
+  return (b->op() == Token::BIT_XOR) &&
+      (MatchLeftIsOnes(b->left(), b->right(), negated) ||
+       MatchLeftIsOnes(b->right(), b->left(), negated));
+}
+
+
+static bool MatchDoubleNegation(HValue* instr, HValue** arg) {
+  HValue* negated;
+  return MatchNegationViaXor(instr, &negated) &&
+      MatchNegationViaXor(negated, arg);
+}
+
+
 HValue* HBitwise::Canonicalize() {
   if (!representation().IsSmiOrInteger32()) return this;
   // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
@@ -1167,18 +1190,10 @@ HValue* HBitwise::Canonicalize() {
       !left()->CheckFlag(kUint32)) {
     return left();
   }
-  return this;
-}
-
-
-HValue* HBitNot::Canonicalize() {
-  // Optimize ~~x, a common pattern used for ToInt32(x).
-  if (value()->IsBitNot()) {
-    HValue* result = HBitNot::cast(value())->value();
-    ASSERT(result->representation().IsInteger32());
-    if (!result->CheckFlag(kUint32)) {
-      return result;
-    }
+  // Optimize double negation, a common pattern used for ToInt32(x).
+  HValue* arg;
+  if (MatchDoubleNegation(this, &arg) && !arg->CheckFlag(kUint32)) {
+    return arg;
   }
   return this;
 }
index 17222d40419575db3188bbc0aa37db7cb8ebb494..1dbedbd52af497a34e84ef2974c437973ffbfcd1 100644 (file)
@@ -72,7 +72,6 @@ class LChunkBuilder;
   V(ArgumentsLength)                           \
   V(ArgumentsObject)                           \
   V(Bitwise)                                   \
-  V(BitNot)                                    \
   V(BlockEntry)                                \
   V(BoundsCheck)                               \
   V(BoundsCheckBaseIndexInformation)           \
@@ -2392,37 +2391,6 @@ class HElementsKind: public HUnaryOperation {
 };
 
 
-class HBitNot: public HUnaryOperation {
- public:
-  DECLARE_INSTRUCTION_FACTORY_P1(HBitNot, HValue*);
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Integer32();
-  }
-  virtual Representation observed_input_representation(int index) {
-    return Representation::Integer32();
-  }
-
-  virtual HValue* Canonicalize();
-
-  DECLARE_CONCRETE_INSTRUCTION(BitNot)
-
- protected:
-  virtual bool DataEquals(HValue* other) { return true; }
-
- private:
-  explicit HBitNot(HValue* value)
-      : HUnaryOperation(value, HType::TaggedNumber()) {
-    set_representation(Representation::Integer32());
-    SetFlag(kUseGVN);
-    SetFlag(kTruncatingToInt32);
-    SetFlag(kAllowUndefinedAsNaN);
-  }
-
-  virtual bool IsDeletable() const { return true; }
-};
-
-
 class HUnaryMathOperation: public HTemplateInstruction<2> {
  public:
   static HInstruction* New(Zone* zone,
index 67219f55dff778f78e9c4a02205cf6064ebdfe64..835a198d4d8b53f42d06542806f3381116ea1869 100644 (file)
@@ -33,11 +33,7 @@ namespace internal {
 
 bool HUint32AnalysisPhase::IsSafeUint32Use(HValue* val, HValue* use) {
   // Operations that operate on bits are safe.
-  if (use->IsBitwise() ||
-      use->IsShl() ||
-      use->IsSar() ||
-      use->IsShr() ||
-      use->IsBitNot()) {
+  if (use->IsBitwise() || use->IsShl() || use->IsSar() || use->IsShr()) {
     return true;
   } else if (use->IsChange() || use->IsSimulate()) {
     // Conversions and deoptimization have special support for unt32.
index 6043caa0f47f84ed16c18535eed3f278204b17b3..837c9780c50abe3753ddfd8c86d60a45626405f8 100644 (file)
@@ -1719,19 +1719,6 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
 }
 
 
-HInstruction* HGraphBuilder::BuildUnaryMathOp(
-    HValue* input, Handle<Type> type, Token::Value operation) {
-  ASSERT_EQ(Token::BIT_NOT, operation);
-  // We only handle the numeric cases here
-  type = handle(
-      Type::Intersect(type, handle(Type::Number(), isolate())), isolate());
-  if (type->Is(Type::None())) {
-    Add<HDeoptimize>(Deoptimizer::SOFT);
-  }
-  return New<HBitNot>(input);
-}
-
-
 void HGraphBuilder::BuildCompareNil(
     HValue* value,
     Handle<Type> type,
@@ -7229,7 +7216,6 @@ void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
     case Token::DELETE: return VisitDelete(expr);
     case Token::VOID: return VisitVoid(expr);
     case Token::TYPEOF: return VisitTypeof(expr);
-    case Token::BIT_NOT: return VisitBitNot(expr);
     case Token::NOT: return VisitNot(expr);
     default: UNREACHABLE();
   }
@@ -7291,15 +7277,6 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
 }
 
 
-void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
-  CHECK_ALIVE(VisitForValue(expr->expression()));
-  Handle<Type> operand_type = expr->expression()->bounds().lower;
-  HValue* value = TruncateToNumber(Pop(), &operand_type);
-  HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
-  return ast_context()->ReturnInstruction(instr, expr->id());
-}
-
-
 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
   if (ast_context()->IsTest()) {
     TestContext* context = TestContext::cast(ast_context());
index 47b4caa6e3c3a2bbdb346e1a7e466e23299836f9..6312a52376f50713ac584460634dbf4a63161d28 100644 (file)
@@ -1550,9 +1550,6 @@ class HGraphBuilder {
                                  ElementsKind kind,
                                  int length);
 
-  HInstruction* BuildUnaryMathOp(
-      HValue* value, Handle<Type> type, Token::Value token);
-
   void BuildCompareNil(
       HValue* value,
       Handle<Type> type,
@@ -1811,7 +1808,6 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
   void VisitDelete(UnaryOperation* expr);
   void VisitVoid(UnaryOperation* expr);
   void VisitTypeof(UnaryOperation* expr);
-  void VisitBitNot(UnaryOperation* expr);
   void VisitNot(UnaryOperation* expr);
 
   void VisitComma(BinaryOperation* expr);
index 02517351b149f7531d58a10c6b99c6b930cbb419..8721656634c87575142e2f446fbfbd05ba80caf4 100644 (file)
@@ -250,17 +250,6 @@ void ToBooleanStub::InitializeInterfaceDescriptor(
 }
 
 
-void UnaryOpStub::InitializeInterfaceDescriptor(
-    Isolate* isolate,
-    CodeStubInterfaceDescriptor* descriptor) {
-  static Register registers[] = { eax };
-  descriptor->register_param_count_ = 1;
-  descriptor->register_params_ = registers;
-  descriptor->deoptimization_handler_ =
-      FUNCTION_ADDR(UnaryOpIC_Miss);
-}
-
-
 void StoreGlobalStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
index a3e17a68bdacc00ac8a6832568b51bf6e9bff8dd..f08a269e85b576e46b7036fdbd6febc94732687b 100644 (file)
@@ -4347,31 +4347,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       break;
     }
 
-    case Token::BIT_NOT:
-      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
-      break;
-
     default:
       UNREACHABLE();
   }
 }
 
 
-void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
-                                           const char* comment) {
-  ASSERT_EQ(Token::BIT_NOT, expr->op());
-  Comment cmt(masm_, comment);
-  UnaryOpStub stub(expr->op());
-  // UnaryOpStub expects the argument to be in the
-  // accumulator register eax.
-  VisitForAccumulatorValue(expr->expression());
-  SetSourcePosition(expr->position());
-  CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
-         expr->UnaryOperationFeedbackId());
-  context()->Plug(eax);
-}
-
-
 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
index ab73406a13ec52ba365f343abee71a8abf0d2a9e..061ec9b6d3542b93c029da74ba1d105becb0d769 100644 (file)
@@ -1679,8 +1679,9 @@ void LCodeGen::DoBitI(LBitI* instr) {
   ASSERT(left->IsRegister());
 
   if (right->IsConstantOperand()) {
-    int right_operand = ToRepresentation(LConstantOperand::cast(right),
-                                         instr->hydrogen()->representation());
+    int32_t right_operand =
+        ToRepresentation(LConstantOperand::cast(right),
+                         instr->hydrogen()->representation());
     switch (instr->op()) {
       case Token::BIT_AND:
         __ and_(ToRegister(left), right_operand);
@@ -1689,7 +1690,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
         __ or_(ToRegister(left), right_operand);
         break;
       case Token::BIT_XOR:
-        __ xor_(ToRegister(left), right_operand);
+        if (right_operand == int32_t(~0)) {
+          __ not_(ToRegister(left));
+        } else {
+          __ xor_(ToRegister(left), right_operand);
+        }
         break;
       default:
         UNREACHABLE();
@@ -1990,13 +1995,6 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
 }
 
 
-void LCodeGen::DoBitNotI(LBitNotI* instr) {
-  LOperand* input = instr->value();
-  ASSERT(input->Equals(instr->result()));
-  __ not_(ToRegister(input));
-}
-
-
 void LCodeGen::DoThrow(LThrow* instr) {
   __ push(ToOperand(instr->value()));
   ASSERT(ToRegister(instr->context()).is(esi));
index 42c523478df1480f8c9f4bed9b90c568af9aec98..c9a78997f147e95465a7e5f63e1c1d80c07692b5 100644 (file)
@@ -294,7 +294,7 @@ class LCodeGen BASE_EMBEDDED {
   Register ToRegister(int index) const;
   XMMRegister ToDoubleRegister(int index) const;
   X87Register ToX87Register(int index) const;
-  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
   ExternalReference ToExternalReference(LConstantOperand* op) const;
 
index e3b64b79692e836c295cbef9f8489215626df112..52f39d4244debd6619a39a3a5f7d3b042bcd8874 100644 (file)
@@ -1414,16 +1414,6 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
-  ASSERT(instr->value()->representation().IsInteger32());
-  ASSERT(instr->representation().IsInteger32());
-  if (instr->HasNoUses()) return NULL;
-  LOperand* input = UseRegisterAtStart(instr->value());
-  LBitNotI* result = new(zone()) LBitNotI(input);
-  return DefineSameAsFirst(result);
-}
-
-
 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
index 9ed9a58ead9e85b4a1fc49019c43b52c265b155a..effecb73e365e5fec5f65749237f402651abcd5d 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -1357,18 +1356,6 @@ class LThrow: public LTemplateInstruction<0, 2, 0> {
 };
 
 
-class LBitNotI: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LBitNotI(LOperand* value) {
-    inputs_[0] = value;
-  }
-
-  LOperand* value() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
-};
-
-
 class LAddI: public LTemplateInstruction<1, 2, 0> {
  public:
   LAddI(LOperand* left, LOperand* right) {
index a55160a394e7f362842e70fb95cd30e65646a7fd..3c22580c2c7e2b36d851444304435e6f433d4a17 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -390,7 +390,6 @@ void IC::Clear(Address address) {
     case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
     case Code::COMPARE_IC: return CompareIC::Clear(address, target);
     case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target);
-    case Code::UNARY_OP_IC:
     case Code::BINARY_OP_IC:
     case Code::TO_BOOLEAN_IC:
       // Clearing these is tricky and does not
@@ -2589,27 +2588,6 @@ void BinaryOpIC::StubInfoToType(int minor_key,
 }
 
 
-MaybeObject* UnaryOpIC::Transition(Handle<Object> object) {
-  Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
-  UnaryOpStub stub(extra_ic_state);
-
-  stub.UpdateStatus(object);
-
-  Handle<Code> code = stub.GetCode(isolate());
-  set_target(*code);
-
-  return stub.Result(object, isolate());
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss) {
-  HandleScope scope(isolate);
-  Handle<Object> object = args.at<Object>(0);
-  UnaryOpIC ic(isolate);
-  return ic.Transition(object);
-}
-
-
 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
                                               Token::Value op) {
   v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
index 7820d407ec138a781f436fcd4fc3488c3597cd2b..fcf0de58f1a85e7694cffaa68fc062fe45ab24fa 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -714,14 +714,6 @@ class KeyedStoreIC: public StoreIC {
 };
 
 
-class UnaryOpIC: public IC {
- public:
-  explicit UnaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
-
-  MUST_USE_RESULT MaybeObject* Transition(Handle<Object> object);
-};
-
-
 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
 class BinaryOpIC: public IC {
  public:
index b89c2bfba01ba2c675a06f3fbe94cfea540c7622..a1e5a6752b1b733135e3f7c3deddacf4a38a5e35 100644 (file)
@@ -1644,7 +1644,6 @@ void Logger::LogCodeObject(Object* object) {
     case Code::FUNCTION:
     case Code::OPTIMIZED_FUNCTION:
       return;  // We log this later using LogCompiledFunctions.
-    case Code::UNARY_OP_IC:   // fall through
     case Code::BINARY_OP_IC:   // fall through
     case Code::COMPARE_IC:  // fall through
     case Code::COMPARE_NIL_IC:   // fall through
index 8d533b36f409b0411a208e8d4f2d778c707dc06d..cb0896a8dedb16446c2f93304c7a1a2cbc14902b 100644 (file)
@@ -358,6 +358,11 @@ class Operand BASE_EMBEDDED {
   // Return true if this is a register operand.
   INLINE(bool is_reg() const);
 
+  inline int32_t immediate() const {
+    ASSERT(!is_reg());
+    return imm32_;
+  }
+
   Register rm() const { return rm_; }
 
  private:
index 0dd8ec4685b2e606c905d7e8f9bc112bb1398f40..8a03a9a31a592faa84ce21f1e77625e5481719ea 100644 (file)
@@ -247,17 +247,6 @@ void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
 }
 
 
-void UnaryOpStub::InitializeInterfaceDescriptor(
-    Isolate* isolate,
-    CodeStubInterfaceDescriptor* descriptor) {
-  static Register registers[] = { a0 };
-  descriptor->register_param_count_ = 1;
-  descriptor->register_params_ = registers;
-  descriptor->deoptimization_handler_ =
-      FUNCTION_ADDR(UnaryOpIC_Miss);
-}
-
-
 void StoreGlobalStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
index 0a26dbe431cafd0db210a40d9d6c454d8ceea196..b60502c9a5bffa8bdb23daa3ea27fe425b5ab123 100644 (file)
@@ -4382,32 +4382,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       break;
     }
 
-    case Token::BIT_NOT:
-      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
-      break;
-
     default:
       UNREACHABLE();
   }
 }
 
 
-void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
-                                           const char* comment) {
-  ASSERT_EQ(Token::BIT_NOT, expr->op());
-  // TODO(svenpanne): Allowing format strings in Comment would be nice here...
-  Comment cmt(masm_, comment);
-  UnaryOpStub stub(expr->op());
-  // GenericUnaryOpStub expects the argument to be in a0.
-  VisitForAccumulatorValue(expr->expression());
-  SetSourcePosition(expr->position());
-  __ mov(a0, result_register());
-  CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
-         expr->UnaryOperationFeedbackId());
-  context()->Plug(v0);
-}
-
-
 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
index 8f3423ecd777b585ebabeee4b525b82d15909d00..644919741f3f0860be9b9420a056938b15be3824 100644 (file)
@@ -1509,7 +1509,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
       __ Or(result, left, right);
       break;
     case Token::BIT_XOR:
-      __ Xor(result, left, right);
+      if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
+        __ Nor(result, zero_reg, left);
+      } else {
+        __ Xor(result, left, right);
+      }
       break;
     default:
       UNREACHABLE();
@@ -1787,13 +1791,6 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
 }
 
 
-void LCodeGen::DoBitNotI(LBitNotI* instr) {
-  Register input = ToRegister(instr->value());
-  Register result = ToRegister(instr->result());
-  __ Nor(result, zero_reg, Operand(input));
-}
-
-
 void LCodeGen::DoThrow(LThrow* instr) {
   Register input_reg = EmitLoadRegister(instr->value(), at);
   __ push(input_reg);
index cc3873d8454b5154169aaf7f98a48fdfb9d98249..670c4cc87a7927d8c04fec47c36e14c059e93123 100644 (file)
@@ -114,7 +114,7 @@ class LCodeGen BASE_EMBEDDED {
   DoubleRegister EmitLoadDoubleRegister(LOperand* op,
                                         FloatRegister flt_scratch,
                                         DoubleRegister dbl_scratch);
-  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
index 5adcff240952218b6997308537e5a2e334b01815..38ac19f609c2d8e4294b73a32f86efa78ae81db7 100644 (file)
@@ -1327,15 +1327,6 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
-  ASSERT(instr->value()->representation().IsInteger32());
-  ASSERT(instr->representation().IsInteger32());
-  if (instr->HasNoUses()) return NULL;
-  LOperand* value = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new(zone()) LBitNotI(value));
-}
-
-
 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
index 75ab77dacebea31efbdde3ef6055d8de02965be6..a21c32342e538311bf81d71f23b251124aa08c6a 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -1355,18 +1354,6 @@ class LThrow: public LTemplateInstruction<0, 1, 0> {
 };
 
 
-class LBitNotI: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LBitNotI(LOperand* value) {
-    inputs_[0] = value;
-  }
-
-  LOperand* value() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
-};
-
-
 class LAddI: public LTemplateInstruction<1, 2, 0> {
  public:
   LAddI(LOperand* left, LOperand* right) {
index ed266436f190d18637170c15226fa180cf314fe2..169475791d05ff9672dfff163ba14dde0506bea5 100644 (file)
@@ -3822,7 +3822,6 @@ inline void Code::set_is_crankshafted(bool value) {
 
 int Code::major_key() {
   ASSERT(kind() == STUB ||
-         kind() == UNARY_OP_IC ||
          kind() == BINARY_OP_IC ||
          kind() == COMPARE_IC ||
          kind() == COMPARE_NIL_IC ||
@@ -3837,7 +3836,6 @@ int Code::major_key() {
 
 void Code::set_major_key(int major) {
   ASSERT(kind() == STUB ||
-         kind() == UNARY_OP_IC ||
          kind() == BINARY_OP_IC ||
          kind() == COMPARE_IC ||
          kind() == COMPARE_NIL_IC ||
@@ -4027,21 +4025,6 @@ void Code::set_check_type(CheckType value) {
 }
 
 
-byte Code::unary_op_type() {
-  ASSERT(is_unary_op_stub());
-  return UnaryOpTypeField::decode(
-      READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
-}
-
-
-void Code::set_unary_op_type(byte value) {
-  ASSERT(is_unary_op_stub());
-  int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
-  int updated = UnaryOpTypeField::update(previous, value);
-  WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
-}
-
-
 byte Code::to_boolean_state() {
   return extended_extra_ic_state();
 }
index 529808a34a9d8734403baf23170787133da0c503..b2dc1816f8ef6ceb4bd25ef6572c6c04d0c8b399 100644 (file)
@@ -4781,7 +4781,6 @@ class Code: public HeapObject {
   V(KEYED_CALL_IC)      \
   V(STORE_IC)           \
   V(KEYED_STORE_IC)     \
-  V(UNARY_OP_IC)        \
   V(BINARY_OP_IC)       \
   V(COMPARE_IC)         \
   V(COMPARE_NIL_IC)     \
@@ -4900,8 +4899,7 @@ class Code: public HeapObject {
     // TODO(danno): This is a bit of a hack right now since there are still
     // clients of this API that pass "extra" values in for argc. These clients
     // should be retrofitted to used ExtendedExtraICState.
-    return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC ||
-           kind == UNARY_OP_IC;
+    return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC;
   }
 
   inline StubType type();  // Only valid for monomorphic IC stubs.
@@ -4916,7 +4914,6 @@ class Code: public HeapObject {
   inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
   inline bool is_call_stub() { return kind() == CALL_IC; }
   inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
-  inline bool is_unary_op_stub() { return kind() == UNARY_OP_IC; }
   inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
   inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
   inline bool is_compare_nil_ic_stub() { return kind() == COMPARE_NIL_IC; }
@@ -4990,10 +4987,6 @@ class Code: public HeapObject {
   inline CheckType check_type();
   inline void set_check_type(CheckType value);
 
-  // [type-recording unary op type]: For kind UNARY_OP_IC.
-  inline byte unary_op_type();
-  inline void set_unary_op_type(byte value);
-
   // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
   inline byte to_boolean_state();
 
@@ -5232,9 +5225,6 @@ class Code: public HeapObject {
   // KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION)
   static const int kStackSlotsFirstBit = 0;
   static const int kStackSlotsBitCount = 24;
-  static const int kUnaryOpTypeFirstBit =
-      kStackSlotsFirstBit + kStackSlotsBitCount;
-  static const int kUnaryOpTypeBitCount = 3;
   static const int kHasFunctionCacheFirstBit =
       kStackSlotsFirstBit + kStackSlotsBitCount;
   static const int kHasFunctionCacheBitCount = 1;
@@ -5243,15 +5233,12 @@ class Code: public HeapObject {
   static const int kMarkedForDeoptimizationBitCount = 1;
 
   STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
-  STATIC_ASSERT(kUnaryOpTypeFirstBit + kUnaryOpTypeBitCount <= 32);
   STATIC_ASSERT(kHasFunctionCacheFirstBit + kHasFunctionCacheBitCount <= 32);
   STATIC_ASSERT(kMarkedForDeoptimizationFirstBit +
                 kMarkedForDeoptimizationBitCount <= 32);
 
   class StackSlotsField: public BitField<int,
       kStackSlotsFirstBit, kStackSlotsBitCount> {};  // NOLINT
-  class UnaryOpTypeField: public BitField<int,
-      kUnaryOpTypeFirstBit, kUnaryOpTypeBitCount> {};  // NOLINT
   class HasFunctionCacheField: public BitField<bool,
       kHasFunctionCacheFirstBit, kHasFunctionCacheBitCount> {};  // NOLINT
   class MarkedForDeoptimizationField: public BitField<bool,
index aa83969e99977ac61b9e12adc5427a74ff8c0851..4947790395f3c431db7ef1ef68f30d47fccb8e5b 100644 (file)
@@ -3204,6 +3204,13 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
                                            factory()->NewNumberLiteral(-1),
                                            position);
     }
+    // ...and one more time for '~foo' => 'foo^(~0)'.
+    if (op == Token::BIT_NOT) {
+      return factory()->NewBinaryOperation(Token::BIT_XOR,
+                                           expression,
+                                           factory()->NewNumberLiteral(~0),
+                                           position);
+    }
 
     return factory()->NewUnaryOperation(op, expression, position);
 
index 0a8fbebfb0cd0ae3c316438ae79d432d55818a71..17784181bdd3d37ee454a8cd6364597faeffc496 100644 (file)
@@ -7245,15 +7245,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
-  SealHandleScope shs(isolate);
-  ASSERT(args.length() == 1);
-
-  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
-  return isolate->heap()->NumberFromInt32(~x);
-}
-
-
 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 2);
index df557c1dc7d20e898e5427a5c11e7c072855beda..6b68f241dcbdeb9e546c66a656f2c6901882a9d3 100644 (file)
@@ -158,7 +158,6 @@ namespace internal {
   F(NumberOr, 2, 1) \
   F(NumberAnd, 2, 1) \
   F(NumberXor, 2, 1) \
-  F(NumberNot, 1, 1) \
   \
   F(NumberShl, 2, 1) \
   F(NumberShr, 2, 1) \
index f1b4585d3bbd111ccd4ef777dc96ae7b0f8bc21b..5339570ef6ee6d8e42430765caf828d7d4efa64e 100644 (file)
@@ -294,13 +294,6 @@ function BIT_XOR(y) {
 }
 
 
-// ECMA-262, section 11.4.8, page 48.
-function BIT_NOT() {
-  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
-  return %NumberNot(x);
-}
-
-
 // ECMA-262, section 11.7.1, page 51.
 function SHL(y) {
   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
index 769df07e4fa20b97186ebbaeaa20e1aca4ef3ec5..336b459d6b7b2aa230c24cb4fdba1efca2569e24 100644 (file)
@@ -384,17 +384,6 @@ void TypeFeedbackOracle::CompareType(TypeFeedbackId id,
 }
 
 
-Handle<Type> TypeFeedbackOracle::UnaryType(TypeFeedbackId id) {
-  Handle<Object> object = GetInfo(id);
-  if (!object->IsCode()) {
-    return handle(Type::None(), isolate());
-  }
-  Handle<Code> code = Handle<Code>::cast(object);
-  ASSERT(code->is_unary_op_stub());
-  return UnaryOpStub(code->extended_extra_ic_state()).GetType(isolate());
-}
-
-
 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id,
                                     Handle<Type>* left,
                                     Handle<Type>* right,
@@ -658,7 +647,6 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
         }
         break;
 
-      case Code::UNARY_OP_IC:
       case Code::BINARY_OP_IC:
       case Code::COMPARE_IC:
       case Code::TO_BOOLEAN_IC:
index 1a7c67dfb88ffc399843d53843e3e658e767fe67..4b376c84bdcd0b630dfd1a52622e2f54aba644fd 100644 (file)
@@ -297,7 +297,6 @@ class TypeFeedbackOracle: public ZoneObject {
   byte ToBooleanTypes(TypeFeedbackId id);
 
   // Get type information for arithmetic operations and compares.
-  Handle<Type> UnaryType(TypeFeedbackId id);
   void BinaryType(TypeFeedbackId id,
                   Handle<Type>* left,
                   Handle<Type>* right,
index 0611d7e0781079a7c228e81c3cd174df11e6e51e..df2cee51e9e7553404a10004922c53de4ee89294 100644 (file)
@@ -497,8 +497,6 @@ void AstTyper::VisitCallRuntime(CallRuntime* expr) {
 
 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
   // Collect type feedback.
-  Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId());
-  NarrowLowerType(expr->expression(), op_type);
   if (expr->op() == Token::NOT) {
     // TODO(rossberg): only do in test or value context.
     expr->expression()->RecordToBooleanTypeFeedback(oracle());
@@ -514,9 +512,6 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
     case Token::VOID:
       NarrowType(expr, Bounds(Type::Undefined(), isolate_));
       break;
-    case Token::BIT_NOT:
-      NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
-      break;
     case Token::TYPEOF:
       NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
       break;
index 76479d3e2ebec5dc63fa69a001f818fae339b7fc..ad33a8c6319b7a0a5919b7be75458068a1d1f929 100644 (file)
@@ -246,17 +246,6 @@ void ToBooleanStub::InitializeInterfaceDescriptor(
 }
 
 
-void UnaryOpStub::InitializeInterfaceDescriptor(
-    Isolate* isolate,
-    CodeStubInterfaceDescriptor* descriptor) {
-  static Register registers[] = { rax };
-  descriptor->register_param_count_ = 1;
-  descriptor->register_params_ = registers;
-  descriptor->deoptimization_handler_ =
-     FUNCTION_ADDR(UnaryOpIC_Miss);
-}
-
-
 void StoreGlobalStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
index f3e5a5032397a99bd8005ed8f5b0d15d3620102f..6333e87bea1b6c2ed82cd2b4ea153dd0cc917890 100644 (file)
@@ -4335,32 +4335,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       break;
     }
 
-    case Token::BIT_NOT:
-      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
-      break;
-
     default:
       UNREACHABLE();
   }
 }
 
 
-void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
-                                           const char* comment) {
-  ASSERT_EQ(Token::BIT_NOT, expr->op());
-  // TODO(svenpanne): Allowing format strings in Comment would be nice here...
-  Comment cmt(masm_, comment);
-  UnaryOpStub stub(expr->op());
-  // UnaryOpStub expects the argument to be in the
-  // accumulator register rax.
-  VisitForAccumulatorValue(expr->expression());
-  SetSourcePosition(expr->position());
-  CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
-         expr->UnaryOperationFeedbackId());
-  context()->Plug(rax);
-}
-
-
 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
index b129d4b7e9967bbce88e46ff9024dc1a625268e3..d4c125bcdc6e9a62ab74cfd01ee7c9504ec456f9 100644 (file)
@@ -1270,7 +1270,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
   bool can_overflow =
       instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
   if (right->IsConstantOperand()) {
-    int right_value = ToInteger32(LConstantOperand::cast(right));
+    int32_t right_value = ToInteger32(LConstantOperand::cast(right));
     if (right_value == -1) {
       __ negl(left);
     } else if (right_value == 0) {
@@ -1362,7 +1362,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
   ASSERT(left->IsRegister());
 
   if (right->IsConstantOperand()) {
-    int right_operand = ToInteger32(LConstantOperand::cast(right));
+    int32_t right_operand = ToInteger32(LConstantOperand::cast(right));
     switch (instr->op()) {
       case Token::BIT_AND:
         __ andl(ToRegister(left), Immediate(right_operand));
@@ -1371,7 +1371,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
         __ orl(ToRegister(left), Immediate(right_operand));
         break;
       case Token::BIT_XOR:
-        __ xorl(ToRegister(left), Immediate(right_operand));
+        if (right_operand == int32_t(~0)) {
+          __ not_(ToRegister(left));
+        } else {
+          __ xorl(ToRegister(left), Immediate(right_operand));
+        }
         break;
       default:
         UNREACHABLE();
@@ -1442,7 +1446,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
         break;
     }
   } else {
-    int value = ToInteger32(LConstantOperand::cast(right));
+    int32_t value = ToInteger32(LConstantOperand::cast(right));
     uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
     switch (instr->op()) {
       case Token::ROR:
@@ -1656,13 +1660,6 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
 }
 
 
-void LCodeGen::DoBitNotI(LBitNotI* instr) {
-  LOperand* input = instr->value();
-  ASSERT(input->Equals(instr->result()));
-  __ not_(ToRegister(input));
-}
-
-
 void LCodeGen::DoThrow(LThrow* instr) {
   __ push(ToRegister(instr->value()));
   CallRuntime(Runtime::kThrow, 1, instr);
@@ -2898,8 +2895,8 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
 
   if (instr->length()->IsConstantOperand() &&
       instr->index()->IsConstantOperand()) {
-    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
-    int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
+    int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length()));
     int index = (const_length - const_index) + 1;
     __ movq(result, Operand(arguments, index * kPointerSize));
   } else {
@@ -3086,7 +3083,7 @@ Operand LCodeGen::BuildFastArrayOperand(
   Register elements_pointer_reg = ToRegister(elements_pointer);
   int shift_size = ElementsKindToShiftSize(elements_kind);
   if (key->IsConstantOperand()) {
-    int constant_value = ToInteger32(LConstantOperand::cast(key));
+    int32_t constant_value = ToInteger32(LConstantOperand::cast(key));
     if (constant_value & 0xF0000000) {
       Abort(kArrayIndexConstantValueTooBig);
     }
@@ -4096,7 +4093,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
       __ AssertZeroExtended(reg);
     }
     if (instr->index()->IsConstantOperand()) {
-      int constant_index =
+      int32_t constant_index =
           ToInteger32(LConstantOperand::cast(instr->index()));
       if (instr->hydrogen()->length()->representation().IsSmi()) {
         __ Cmp(reg, Smi::FromInt(constant_index));
@@ -4113,7 +4110,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
   } else {
     Operand length = ToOperand(instr->length());
     if (instr->index()->IsConstantOperand()) {
-      int constant_index =
+      int32_t constant_index =
           ToInteger32(LConstantOperand::cast(instr->index()));
       if (instr->hydrogen()->length()->representation().IsSmi()) {
         __ Cmp(length, Smi::FromInt(constant_index));
@@ -4400,7 +4397,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
   // DoStringCharCodeAt above.
   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   if (instr->index()->IsConstantOperand()) {
-    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
     __ Push(Smi::FromInt(const_index));
   } else {
     Register index = ToRegister(instr->index());
index e5e87d0cd9601dd69f8baacf48c5c7d4048d30b0..e13422950fa6d8641cfef7669dda451ada8ac433 100644 (file)
@@ -102,7 +102,6 @@ class LCodeGen BASE_EMBEDDED {
   XMMRegister ToDoubleRegister(LOperand* op) const;
   bool IsInteger32Constant(LConstantOperand* op) const;
   bool IsSmiConstant(LConstantOperand* op) const;
-  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
index 6be237351c5dafa7fa3e239f6aaedb47235832ea..913e170595d4d9a9d2ac4dd4eefbecc88fbc70fa 100644 (file)
@@ -1321,16 +1321,6 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
-  ASSERT(instr->value()->representation().IsInteger32());
-  ASSERT(instr->representation().IsInteger32());
-  if (instr->HasNoUses()) return NULL;
-  LOperand* input = UseRegisterAtStart(instr->value());
-  LBitNotI* result = new(zone()) LBitNotI(input);
-  return DefineSameAsFirst(result);
-}
-
-
 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
index 6716f484779817b89cca34cf416ba6de069ba5f7..c3b9db4c592461f6afa3b2137fe54e3f8e283642 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -1311,18 +1310,6 @@ class LThrow: public LTemplateInstruction<0, 1, 0> {
 };
 
 
-class LBitNotI: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LBitNotI(LOperand* value) {
-    inputs_[0] = value;
-  }
-
-  LOperand* value() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
-};
-
-
 class LAddI: public LTemplateInstruction<1, 2, 0> {
  public:
   LAddI(LOperand* left, LOperand* right) {