Minor cleanup of CompareIC state
Allow transitioning from KNOWN_OBJECT to KNONW_OBJECT or OBJECT. Also, rename HEAP_NUMBER IC states to NUMBER, since they handle Smis, too. R=jkummerow@chromium.org BUG= Review URL: https://codereview.chromium.org/12254036 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13775 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
b22c7eaed9
commit
8924d03e16
@ -1711,7 +1711,7 @@ static void ICCompareStub_CheckInputType(MacroAssembler* masm,
|
||||
Label ok;
|
||||
if (expected == CompareIC::SMI) {
|
||||
__ JumpIfNotSmi(input, fail);
|
||||
} else if (expected == CompareIC::HEAP_NUMBER) {
|
||||
} else if (expected == CompareIC::NUMBER) {
|
||||
__ JumpIfSmi(input, &ok);
|
||||
__ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
|
||||
DONT_DO_SMI_CHECK);
|
||||
@ -2111,8 +2111,8 @@ void UnaryOpStub::Generate(MacroAssembler* masm) {
|
||||
case UnaryOpIC::SMI:
|
||||
GenerateSmiStub(masm);
|
||||
break;
|
||||
case UnaryOpIC::HEAP_NUMBER:
|
||||
GenerateHeapNumberStub(masm);
|
||||
case UnaryOpIC::NUMBER:
|
||||
GenerateNumberStub(masm);
|
||||
break;
|
||||
case UnaryOpIC::GENERIC:
|
||||
GenerateGenericStub(masm);
|
||||
@ -2192,13 +2192,13 @@ void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
||||
|
||||
|
||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||
void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
||||
switch (op_) {
|
||||
case Token::SUB:
|
||||
GenerateHeapNumberStubSub(masm);
|
||||
GenerateNumberStubSub(masm);
|
||||
break;
|
||||
case Token::BIT_NOT:
|
||||
GenerateHeapNumberStubBitNot(masm);
|
||||
GenerateNumberStubBitNot(masm);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -2206,7 +2206,7 @@ void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||
void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
|
||||
Label non_smi, slow, call_builtin;
|
||||
GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
|
||||
__ bind(&non_smi);
|
||||
@ -2218,7 +2218,7 @@ void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) {
|
||||
void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) {
|
||||
Label non_smi, slow;
|
||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||
__ bind(&non_smi);
|
||||
@ -2680,8 +2680,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
|
||||
masm, right, destination, d7, d8, r2, r3, heap_number_map,
|
||||
scratch1, scratch2, s0, miss);
|
||||
} else {
|
||||
Label* fail = (right_type == BinaryOpIC::HEAP_NUMBER) ? miss
|
||||
: not_numbers;
|
||||
Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
|
||||
FloatingPointHelper::LoadNumber(
|
||||
masm, destination, right, d7, r2, r3, heap_number_map,
|
||||
scratch1, scratch2, fail);
|
||||
@ -2693,8 +2692,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
|
||||
masm, left, destination, d6, d8, r0, r1, heap_number_map,
|
||||
scratch1, scratch2, s0, miss);
|
||||
} else {
|
||||
Label* fail = (left_type == BinaryOpIC::HEAP_NUMBER) ? miss
|
||||
: not_numbers;
|
||||
Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
|
||||
FloatingPointHelper::LoadNumber(
|
||||
masm, destination, left, d6, r0, r1, heap_number_map,
|
||||
scratch1, scratch2, fail);
|
||||
@ -3090,7 +3088,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||
__ bind(&return_heap_number);
|
||||
// Return a heap number, or fall through to type transition or runtime
|
||||
// call if we can't.
|
||||
if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER
|
||||
if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::NUMBER
|
||||
: BinaryOpIC::INT32)) {
|
||||
// We are using vfp registers so r5 is available.
|
||||
heap_number_result = r5;
|
||||
@ -3314,11 +3312,11 @@ void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||
}
|
||||
__ bind(&done);
|
||||
|
||||
GenerateHeapNumberStub(masm);
|
||||
GenerateNumberStub(masm);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
||||
Label call_runtime, transition;
|
||||
BinaryOpStub_GenerateFPOperation(
|
||||
masm, left_type_, right_type_, false,
|
||||
@ -6941,8 +6939,8 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::HEAP_NUMBER);
|
||||
void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::NUMBER);
|
||||
|
||||
Label generic_stub;
|
||||
Label unordered, maybe_undefined1, maybe_undefined2;
|
||||
|
@ -119,9 +119,9 @@ class UnaryOpStub: public PlatformCodeStub {
|
||||
void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
|
||||
void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
|
||||
|
||||
void GenerateHeapNumberStub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateNumberStub(MacroAssembler* masm);
|
||||
void GenerateNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
|
||||
void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
|
||||
|
||||
|
@ -193,8 +193,8 @@ void BinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
case BinaryOpIC::INT32:
|
||||
GenerateInt32Stub(masm);
|
||||
break;
|
||||
case BinaryOpIC::HEAP_NUMBER:
|
||||
GenerateHeapNumberStub(masm);
|
||||
case BinaryOpIC::NUMBER:
|
||||
GenerateNumberStub(masm);
|
||||
break;
|
||||
case BinaryOpIC::ODDBALL:
|
||||
GenerateOddballStub(masm);
|
||||
@ -364,8 +364,8 @@ void ICCompareStub::Generate(MacroAssembler* masm) {
|
||||
case CompareIC::SMI:
|
||||
GenerateSmis(masm);
|
||||
break;
|
||||
case CompareIC::HEAP_NUMBER:
|
||||
GenerateHeapNumbers(masm);
|
||||
case CompareIC::NUMBER:
|
||||
GenerateNumbers(masm);
|
||||
break;
|
||||
case CompareIC::STRING:
|
||||
GenerateStrings(masm);
|
||||
@ -376,7 +376,7 @@ void ICCompareStub::Generate(MacroAssembler* masm) {
|
||||
case CompareIC::OBJECT:
|
||||
GenerateObjects(masm);
|
||||
break;
|
||||
case CompareIC::KNOWN_OBJECTS:
|
||||
case CompareIC::KNOWN_OBJECT:
|
||||
ASSERT(*known_map_ != NULL);
|
||||
GenerateKnownObjects(masm);
|
||||
break;
|
||||
|
@ -736,7 +736,7 @@ class BinaryOpStub: public PlatformCodeStub {
|
||||
void GenerateBothStringStub(MacroAssembler* masm);
|
||||
void GenerateGeneric(MacroAssembler* masm);
|
||||
void GenerateGenericStub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStub(MacroAssembler* masm);
|
||||
void GenerateNumberStub(MacroAssembler* masm);
|
||||
void GenerateInt32Stub(MacroAssembler* masm);
|
||||
void GenerateLoadArguments(MacroAssembler* masm);
|
||||
void GenerateOddballStub(MacroAssembler* masm);
|
||||
@ -808,7 +808,7 @@ class ICCompareStub: public PlatformCodeStub {
|
||||
virtual int GetCodeKind() { return Code::COMPARE_IC; }
|
||||
|
||||
void GenerateSmis(MacroAssembler* masm);
|
||||
void GenerateHeapNumbers(MacroAssembler* masm);
|
||||
void GenerateNumbers(MacroAssembler* masm);
|
||||
void GenerateSymbols(MacroAssembler* masm);
|
||||
void GenerateStrings(MacroAssembler* masm);
|
||||
void GenerateObjects(MacroAssembler* masm);
|
||||
@ -821,7 +821,7 @@ class ICCompareStub: public PlatformCodeStub {
|
||||
|
||||
virtual void AddToSpecialCache(Handle<Code> new_object);
|
||||
virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
|
||||
virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECTS; }
|
||||
virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
|
||||
|
||||
Token::Value op_;
|
||||
CompareIC::State left_;
|
||||
|
@ -915,8 +915,8 @@ void UnaryOpStub::Generate(MacroAssembler* masm) {
|
||||
case UnaryOpIC::SMI:
|
||||
GenerateSmiStub(masm);
|
||||
break;
|
||||
case UnaryOpIC::HEAP_NUMBER:
|
||||
GenerateHeapNumberStub(masm);
|
||||
case UnaryOpIC::NUMBER:
|
||||
GenerateNumberStub(masm);
|
||||
break;
|
||||
case UnaryOpIC::GENERIC:
|
||||
GenerateGenericStub(masm);
|
||||
@ -1020,13 +1020,13 @@ void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) {
|
||||
|
||||
|
||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||
void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
||||
switch (op_) {
|
||||
case Token::SUB:
|
||||
GenerateHeapNumberStubSub(masm);
|
||||
GenerateNumberStubSub(masm);
|
||||
break;
|
||||
case Token::BIT_NOT:
|
||||
GenerateHeapNumberStubBitNot(masm);
|
||||
GenerateNumberStubBitNot(masm);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -1034,7 +1034,7 @@ void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||
void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
|
||||
Label non_smi, undo, slow, call_builtin;
|
||||
GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear);
|
||||
__ bind(&non_smi);
|
||||
@ -1048,7 +1048,7 @@ void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void UnaryOpStub::GenerateHeapNumberStubBitNot(
|
||||
void UnaryOpStub::GenerateNumberStubBitNot(
|
||||
MacroAssembler* masm) {
|
||||
Label non_smi, slow;
|
||||
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
||||
@ -1943,11 +1943,11 @@ void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||
}
|
||||
__ bind(&done);
|
||||
|
||||
GenerateHeapNumberStub(masm);
|
||||
GenerateNumberStub(masm);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
||||
Label call_runtime;
|
||||
|
||||
// Floating point case.
|
||||
@ -4429,7 +4429,7 @@ static void CheckInputType(MacroAssembler* masm,
|
||||
Label ok;
|
||||
if (expected == CompareIC::SMI) {
|
||||
__ JumpIfNotSmi(input, fail);
|
||||
} else if (expected == CompareIC::HEAP_NUMBER) {
|
||||
} else if (expected == CompareIC::NUMBER) {
|
||||
__ JumpIfSmi(input, &ok);
|
||||
__ cmp(FieldOperand(input, HeapObject::kMapOffset),
|
||||
Immediate(masm->isolate()->factory()->heap_number_map()));
|
||||
@ -6740,8 +6740,8 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::HEAP_NUMBER);
|
||||
void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::NUMBER);
|
||||
|
||||
Label generic_stub;
|
||||
Label unordered, maybe_undefined1, maybe_undefined2;
|
||||
|
@ -131,9 +131,9 @@ class UnaryOpStub: public PlatformCodeStub {
|
||||
Label::Distance non_smi_near = Label::kFar);
|
||||
void GenerateSmiCodeUndo(MacroAssembler* masm);
|
||||
|
||||
void GenerateHeapNumberStub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateNumberStub(MacroAssembler* masm);
|
||||
void GenerateNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
|
||||
void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
|
||||
|
||||
|
90
src/ic.cc
90
src/ic.cc
@ -399,7 +399,7 @@ void CompareIC::Clear(Address address, Code* target) {
|
||||
ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
|
||||
&handler_state, &op);
|
||||
// Only clear CompareICs that can retain objects.
|
||||
if (handler_state != KNOWN_OBJECTS) return;
|
||||
if (handler_state != KNOWN_OBJECT) return;
|
||||
SetTargetAtAddress(address, GetRawUninitialized(op));
|
||||
PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
|
||||
}
|
||||
@ -2042,7 +2042,7 @@ const char* UnaryOpIC::GetName(TypeInfo type_info) {
|
||||
switch (type_info) {
|
||||
case UNINITIALIZED: return "Uninitialized";
|
||||
case SMI: return "Smi";
|
||||
case HEAP_NUMBER: return "HeapNumbers";
|
||||
case NUMBER: return "Number";
|
||||
case GENERIC: return "Generic";
|
||||
default: return "Invalid";
|
||||
}
|
||||
@ -2054,7 +2054,7 @@ UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) {
|
||||
case UNINITIALIZED:
|
||||
return ::v8::internal::UNINITIALIZED;
|
||||
case SMI:
|
||||
case HEAP_NUMBER:
|
||||
case NUMBER:
|
||||
return MONOMORPHIC;
|
||||
case GENERIC:
|
||||
return ::v8::internal::GENERIC;
|
||||
@ -2069,7 +2069,7 @@ UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
|
||||
if (operand_type.IsSmi()) {
|
||||
return SMI;
|
||||
} else if (operand_type.IsNumber()) {
|
||||
return HEAP_NUMBER;
|
||||
return NUMBER;
|
||||
} else {
|
||||
return GENERIC;
|
||||
}
|
||||
@ -2077,24 +2077,22 @@ UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
|
||||
|
||||
|
||||
UnaryOpIC::TypeInfo UnaryOpIC::ComputeNewType(
|
||||
UnaryOpIC::TypeInfo current_type,
|
||||
UnaryOpIC::TypeInfo previous_type) {
|
||||
TypeInfo current_type,
|
||||
TypeInfo previous_type) {
|
||||
switch (previous_type) {
|
||||
case UnaryOpIC::UNINITIALIZED:
|
||||
case UNINITIALIZED:
|
||||
return current_type;
|
||||
case UnaryOpIC::SMI:
|
||||
return (current_type == UnaryOpIC::GENERIC)
|
||||
? UnaryOpIC::GENERIC
|
||||
: UnaryOpIC::HEAP_NUMBER;
|
||||
case UnaryOpIC::HEAP_NUMBER:
|
||||
return UnaryOpIC::GENERIC;
|
||||
case UnaryOpIC::GENERIC:
|
||||
case SMI:
|
||||
return (current_type == GENERIC) ? GENERIC : NUMBER;
|
||||
case NUMBER:
|
||||
return GENERIC;
|
||||
case GENERIC:
|
||||
// We should never do patching if we are in GENERIC state.
|
||||
UNREACHABLE();
|
||||
return UnaryOpIC::GENERIC;
|
||||
return GENERIC;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return UnaryOpIC::GENERIC;
|
||||
return GENERIC;
|
||||
}
|
||||
|
||||
|
||||
@ -2106,9 +2104,9 @@ void BinaryOpIC::patch(Code* code) {
|
||||
const char* BinaryOpIC::GetName(TypeInfo type_info) {
|
||||
switch (type_info) {
|
||||
case UNINITIALIZED: return "Uninitialized";
|
||||
case SMI: return "SMI";
|
||||
case SMI: return "Smi";
|
||||
case INT32: return "Int32";
|
||||
case HEAP_NUMBER: return "HeapNumber";
|
||||
case NUMBER: return "Number";
|
||||
case ODDBALL: return "Oddball";
|
||||
case STRING: return "String";
|
||||
case GENERIC: return "Generic";
|
||||
@ -2123,7 +2121,7 @@ BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
|
||||
return ::v8::internal::UNINITIALIZED;
|
||||
case SMI:
|
||||
case INT32:
|
||||
case HEAP_NUMBER:
|
||||
case NUMBER:
|
||||
case ODDBALL:
|
||||
case STRING:
|
||||
return MONOMORPHIC;
|
||||
@ -2199,7 +2197,7 @@ static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
|
||||
if (kSmiValueSize == 32) return BinaryOpIC::SMI;
|
||||
return BinaryOpIC::INT32;
|
||||
}
|
||||
if (type.IsNumber()) return BinaryOpIC::HEAP_NUMBER;
|
||||
if (type.IsNumber()) return BinaryOpIC::NUMBER;
|
||||
if (type.IsString()) return BinaryOpIC::STRING;
|
||||
if (value->IsUndefined()) {
|
||||
if (op == Token::BIT_AND ||
|
||||
@ -2263,7 +2261,7 @@ RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
|
||||
// That is the only way to get here from the Smi stub.
|
||||
// With 32-bit Smis, all overflows give heap numbers, but with
|
||||
// 31-bit Smis, most operations overflow to int32 results.
|
||||
result_type = BinaryOpIC::HEAP_NUMBER;
|
||||
result_type = BinaryOpIC::NUMBER;
|
||||
} else {
|
||||
// Other operations on SMIs that overflow yield int32s.
|
||||
result_type = BinaryOpIC::INT32;
|
||||
@ -2272,7 +2270,7 @@ RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
|
||||
if (new_overall == BinaryOpIC::INT32 &&
|
||||
previous_overall == BinaryOpIC::INT32) {
|
||||
if (new_left == previous_left && new_right == previous_right) {
|
||||
result_type = BinaryOpIC::HEAP_NUMBER;
|
||||
result_type = BinaryOpIC::NUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2377,11 +2375,11 @@ const char* CompareIC::GetStateName(State state) {
|
||||
switch (state) {
|
||||
case UNINITIALIZED: return "UNINITIALIZED";
|
||||
case SMI: return "SMI";
|
||||
case HEAP_NUMBER: return "HEAP_NUMBER";
|
||||
case OBJECT: return "OBJECTS";
|
||||
case KNOWN_OBJECTS: return "KNOWN_OBJECTS";
|
||||
case NUMBER: return "NUMBER";
|
||||
case SYMBOL: return "SYMBOL";
|
||||
case STRING: return "STRING";
|
||||
case OBJECT: return "OBJECT";
|
||||
case KNOWN_OBJECT: return "KNOWN_OBJECT";
|
||||
case GENERIC: return "GENERIC";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -2395,17 +2393,17 @@ static CompareIC::State InputState(CompareIC::State old_state,
|
||||
switch (old_state) {
|
||||
case CompareIC::UNINITIALIZED:
|
||||
if (value->IsSmi()) return CompareIC::SMI;
|
||||
if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER;
|
||||
if (value->IsHeapNumber()) return CompareIC::NUMBER;
|
||||
if (value->IsSymbol()) return CompareIC::SYMBOL;
|
||||
if (value->IsString()) return CompareIC::STRING;
|
||||
if (value->IsJSObject()) return CompareIC::OBJECT;
|
||||
break;
|
||||
case CompareIC::SMI:
|
||||
if (value->IsSmi()) return CompareIC::SMI;
|
||||
if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER;
|
||||
if (value->IsHeapNumber()) return CompareIC::NUMBER;
|
||||
break;
|
||||
case CompareIC::HEAP_NUMBER:
|
||||
if (value->IsNumber()) return CompareIC::HEAP_NUMBER;
|
||||
case CompareIC::NUMBER:
|
||||
if (value->IsNumber()) return CompareIC::NUMBER;
|
||||
break;
|
||||
case CompareIC::SYMBOL:
|
||||
if (value->IsSymbol()) return CompareIC::SYMBOL;
|
||||
@ -2419,7 +2417,7 @@ static CompareIC::State InputState(CompareIC::State old_state,
|
||||
break;
|
||||
case CompareIC::GENERIC:
|
||||
break;
|
||||
case CompareIC::KNOWN_OBJECTS:
|
||||
case CompareIC::KNOWN_OBJECT:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -2436,13 +2434,13 @@ CompareIC::State CompareIC::TargetState(State old_state,
|
||||
switch (old_state) {
|
||||
case UNINITIALIZED:
|
||||
if (x->IsSmi() && y->IsSmi()) return SMI;
|
||||
if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER;
|
||||
if (x->IsNumber() && y->IsNumber()) return NUMBER;
|
||||
if (Token::IsOrderedRelationalCompareOp(op_)) {
|
||||
// Ordered comparisons treat undefined as NaN, so the
|
||||
// HEAP_NUMBER stub will do the right thing.
|
||||
// NUMBER stub will do the right thing.
|
||||
if ((x->IsNumber() && y->IsUndefined()) ||
|
||||
(y->IsNumber() && x->IsUndefined())) {
|
||||
return HEAP_NUMBER;
|
||||
return NUMBER;
|
||||
}
|
||||
}
|
||||
if (x->IsSymbol() && y->IsSymbol()) {
|
||||
@ -2454,27 +2452,31 @@ CompareIC::State CompareIC::TargetState(State old_state,
|
||||
if (!Token::IsEqualityOp(op_)) return GENERIC;
|
||||
if (x->IsJSObject() && y->IsJSObject()) {
|
||||
if (Handle<JSObject>::cast(x)->map() ==
|
||||
Handle<JSObject>::cast(y)->map() &&
|
||||
Token::IsEqualityOp(op_)) {
|
||||
return KNOWN_OBJECTS;
|
||||
Handle<JSObject>::cast(y)->map()) {
|
||||
return KNOWN_OBJECT;
|
||||
} else {
|
||||
return OBJECT;
|
||||
}
|
||||
}
|
||||
return GENERIC;
|
||||
case SMI:
|
||||
return x->IsNumber() && y->IsNumber()
|
||||
? HEAP_NUMBER
|
||||
: GENERIC;
|
||||
return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
|
||||
case SYMBOL:
|
||||
ASSERT(Token::IsEqualityOp(op_));
|
||||
return x->IsString() && y->IsString() ? STRING : GENERIC;
|
||||
case HEAP_NUMBER:
|
||||
if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER;
|
||||
if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER;
|
||||
case NUMBER:
|
||||
// If the failure was due to one side changing from smi to heap number,
|
||||
// then keep the state (if other changed at the same time, we will get
|
||||
// a second miss and then go to generic).
|
||||
if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
|
||||
if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
|
||||
return GENERIC;
|
||||
case KNOWN_OBJECT:
|
||||
ASSERT(Token::IsEqualityOp(op_));
|
||||
if (x->IsJSObject() && y->IsJSObject()) return OBJECT;
|
||||
return GENERIC;
|
||||
case STRING:
|
||||
case OBJECT:
|
||||
case KNOWN_OBJECTS:
|
||||
case GENERIC:
|
||||
return GENERIC;
|
||||
}
|
||||
@ -2493,7 +2495,7 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
|
||||
State state = TargetState(previous_state, previous_left, previous_right,
|
||||
HasInlinedSmiCode(address()), x, y);
|
||||
ICCompareStub stub(op_, new_left, new_right, state);
|
||||
if (state == KNOWN_OBJECTS) {
|
||||
if (state == KNOWN_OBJECT) {
|
||||
stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
|
||||
}
|
||||
set_target(*stub.GetCode(isolate()));
|
||||
|
16
src/ic.h
16
src/ic.h
@ -709,7 +709,7 @@ class UnaryOpIC: public IC {
|
||||
enum TypeInfo {
|
||||
UNINITIALIZED,
|
||||
SMI,
|
||||
HEAP_NUMBER,
|
||||
NUMBER,
|
||||
GENERIC
|
||||
};
|
||||
|
||||
@ -734,7 +734,7 @@ class BinaryOpIC: public IC {
|
||||
UNINITIALIZED,
|
||||
SMI,
|
||||
INT32,
|
||||
HEAP_NUMBER,
|
||||
NUMBER,
|
||||
ODDBALL,
|
||||
STRING, // Only used for addition operation.
|
||||
GENERIC
|
||||
@ -752,14 +752,20 @@ class BinaryOpIC: public IC {
|
||||
|
||||
class CompareIC: public IC {
|
||||
public:
|
||||
// The type/state lattice is defined by the following inequations:
|
||||
// UNINITIALIZED < ...
|
||||
// ... < GENERIC
|
||||
// SMI < NUMBER
|
||||
// SYMBOL < STRING
|
||||
// KNOWN_OBJECT < OBJECT
|
||||
enum State {
|
||||
UNINITIALIZED,
|
||||
SMI,
|
||||
HEAP_NUMBER,
|
||||
NUMBER,
|
||||
SYMBOL,
|
||||
STRING,
|
||||
OBJECT,
|
||||
KNOWN_OBJECTS,
|
||||
OBJECT, // JSObject
|
||||
KNOWN_OBJECT, // JSObject with specific map (faster check)
|
||||
GENERIC
|
||||
};
|
||||
|
||||
|
@ -120,9 +120,9 @@ class UnaryOpStub: public PlatformCodeStub {
|
||||
void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
|
||||
void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
|
||||
|
||||
void GenerateHeapNumberStub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateNumberStub(MacroAssembler* masm);
|
||||
void GenerateNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
|
||||
void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
|
||||
|
||||
|
@ -8744,7 +8744,7 @@ void Code::ClearTypeFeedbackCells(Heap* heap) {
|
||||
bool Code::allowed_in_shared_map_code_cache() {
|
||||
return is_keyed_load_stub() || is_keyed_store_stub() ||
|
||||
(is_compare_ic_stub() &&
|
||||
ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECTS);
|
||||
ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -319,14 +319,14 @@ static TypeInfo TypeFromCompareType(CompareIC::State state) {
|
||||
return TypeInfo::Uninitialized();
|
||||
case CompareIC::SMI:
|
||||
return TypeInfo::Smi();
|
||||
case CompareIC::HEAP_NUMBER:
|
||||
case CompareIC::NUMBER:
|
||||
return TypeInfo::Number();
|
||||
case CompareIC::SYMBOL:
|
||||
return TypeInfo::Symbol();
|
||||
case CompareIC::STRING:
|
||||
return TypeInfo::String();
|
||||
case CompareIC::OBJECT:
|
||||
case CompareIC::KNOWN_OBJECTS:
|
||||
case CompareIC::KNOWN_OBJECT:
|
||||
// TODO(kasperl): We really need a type for JS objects here.
|
||||
return TypeInfo::NonPrimitive();
|
||||
case CompareIC::GENERIC:
|
||||
@ -368,7 +368,7 @@ Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) {
|
||||
Handle<Code> code = Handle<Code>::cast(object);
|
||||
if (!code->is_compare_ic_stub()) return Handle<Map>::null();
|
||||
CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
|
||||
if (state != CompareIC::KNOWN_OBJECTS) {
|
||||
if (state != CompareIC::KNOWN_OBJECT) {
|
||||
return Handle<Map>::null();
|
||||
}
|
||||
Map* first_map = code->FindFirstMap();
|
||||
@ -390,7 +390,7 @@ TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) {
|
||||
switch (type) {
|
||||
case UnaryOpIC::SMI:
|
||||
return TypeInfo::Smi();
|
||||
case UnaryOpIC::HEAP_NUMBER:
|
||||
case UnaryOpIC::NUMBER:
|
||||
return TypeInfo::Double();
|
||||
default:
|
||||
return unknown;
|
||||
@ -404,7 +404,7 @@ static TypeInfo TypeFromBinaryOpType(BinaryOpIC::TypeInfo binary_type) {
|
||||
case BinaryOpIC::UNINITIALIZED: return TypeInfo::Uninitialized();
|
||||
case BinaryOpIC::SMI: return TypeInfo::Smi();
|
||||
case BinaryOpIC::INT32: return TypeInfo::Integer32();
|
||||
case BinaryOpIC::HEAP_NUMBER: return TypeInfo::Double();
|
||||
case BinaryOpIC::NUMBER: return TypeInfo::Double();
|
||||
case BinaryOpIC::ODDBALL: return TypeInfo::Unknown();
|
||||
case BinaryOpIC::STRING: return TypeInfo::String();
|
||||
case BinaryOpIC::GENERIC: return TypeInfo::Unknown();
|
||||
@ -471,7 +471,7 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
|
||||
return TypeInfo::Smi();
|
||||
case BinaryOpIC::INT32:
|
||||
return TypeInfo::Integer32();
|
||||
case BinaryOpIC::HEAP_NUMBER:
|
||||
case BinaryOpIC::NUMBER:
|
||||
return TypeInfo::Double();
|
||||
case BinaryOpIC::STRING:
|
||||
case BinaryOpIC::GENERIC:
|
||||
|
@ -775,8 +775,8 @@ void UnaryOpStub::Generate(MacroAssembler* masm) {
|
||||
case UnaryOpIC::SMI:
|
||||
GenerateSmiStub(masm);
|
||||
break;
|
||||
case UnaryOpIC::HEAP_NUMBER:
|
||||
GenerateHeapNumberStub(masm);
|
||||
case UnaryOpIC::NUMBER:
|
||||
GenerateNumberStub(masm);
|
||||
break;
|
||||
case UnaryOpIC::GENERIC:
|
||||
GenerateGenericStub(masm);
|
||||
@ -857,13 +857,13 @@ void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
||||
|
||||
|
||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||
void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
||||
switch (op_) {
|
||||
case Token::SUB:
|
||||
GenerateHeapNumberStubSub(masm);
|
||||
GenerateNumberStubSub(masm);
|
||||
break;
|
||||
case Token::BIT_NOT:
|
||||
GenerateHeapNumberStubBitNot(masm);
|
||||
GenerateNumberStubBitNot(masm);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -871,7 +871,7 @@ void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||
void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
|
||||
Label non_smi, slow, call_builtin;
|
||||
GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
|
||||
__ bind(&non_smi);
|
||||
@ -883,7 +883,7 @@ void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void UnaryOpStub::GenerateHeapNumberStubBitNot(
|
||||
void UnaryOpStub::GenerateNumberStubBitNot(
|
||||
MacroAssembler* masm) {
|
||||
Label non_smi, slow;
|
||||
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
||||
@ -1435,7 +1435,7 @@ void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||
}
|
||||
__ bind(&done);
|
||||
|
||||
GenerateHeapNumberStub(masm);
|
||||
GenerateNumberStub(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -1463,7 +1463,7 @@ static void BinaryOpStub_CheckSmiInput(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
||||
Label gc_required, not_number;
|
||||
|
||||
// It could be that only SMIs have been seen at either the left
|
||||
@ -3552,7 +3552,7 @@ static void CheckInputType(MacroAssembler* masm,
|
||||
Label ok;
|
||||
if (expected == CompareIC::SMI) {
|
||||
__ JumpIfNotSmi(input, fail);
|
||||
} else if (expected == CompareIC::HEAP_NUMBER) {
|
||||
} else if (expected == CompareIC::NUMBER) {
|
||||
__ JumpIfSmi(input, &ok);
|
||||
__ CompareMap(input, masm->isolate()->factory()->heap_number_map(), NULL);
|
||||
__ j(not_equal, fail);
|
||||
@ -5754,8 +5754,8 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::HEAP_NUMBER);
|
||||
void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::NUMBER);
|
||||
|
||||
Label generic_stub;
|
||||
Label unordered, maybe_undefined1, maybe_undefined2;
|
||||
|
@ -127,9 +127,9 @@ class UnaryOpStub: public PlatformCodeStub {
|
||||
Label* non_smi,
|
||||
Label::Distance non_smi_near);
|
||||
|
||||
void GenerateHeapNumberStub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateNumberStub(MacroAssembler* masm);
|
||||
void GenerateNumberStubSub(MacroAssembler* masm);
|
||||
void GenerateNumberStubBitNot(MacroAssembler* masm);
|
||||
void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
|
||||
void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user