Desugar bitwise negation into XOR and kill all UnaryOp stuff.

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
This commit is contained in:
svenpanne@chromium.org 2013-08-06 13:34:51 +00:00
parent 45f4b685bf
commit bc6fe88030
50 changed files with 76 additions and 639 deletions

View 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) {

View 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());

View 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);

View 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) {

View 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);

View 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;

View 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.

View File

@ -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:

View 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) \

View 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();

View 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;

View 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.

View 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())) {

View 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);

View 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;
}

View 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,

View 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.

View 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());

View 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);

View 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) {

View 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());

View 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));

View 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;

View 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);

View 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) {

View File

@ -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);

View File

@ -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:

View 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

View 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:

View 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) {

View 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());

View 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);

View 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;

View 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);

View 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) {

View 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();
}

View 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,

View 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);

View 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);

View 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) \

View 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);

View 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:

View 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,

View 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;

View 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) {

View 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());

View 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());

View 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;

View 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);

View 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) {