Do not explicitly record undetectable objects in the ToBoolean stub.
Loading the map within the stub already implies a check for an undetectable object, so there is no need to record this separately. Furthermore, this brings the size of the type info to record down to 8 bits, removing the need to find a place for the ninth bit in the Code object. ;-) Review URL: http://codereview.chromium.org/7484022 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8722 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c081c550d6
commit
73f8cec70e
@ -342,7 +342,6 @@ void ToBooleanStub::Types::Print(StringStream* stream) {
|
||||
if (Contains(BOOLEAN)) stream->Add("Bool");
|
||||
if (Contains(SMI)) stream->Add("Smi");
|
||||
if (Contains(NULL_TYPE)) stream->Add("Null");
|
||||
if (Contains(UNDETECTABLE)) stream->Add("Undetectable");
|
||||
if (Contains(SPEC_OBJECT)) stream->Add("SpecObject");
|
||||
if (Contains(STRING)) stream->Add("String");
|
||||
if (Contains(HEAP_NUMBER)) stream->Add("HeapNumber");
|
||||
@ -378,22 +377,20 @@ bool ToBooleanStub::Types::Record(Handle<Object> object) {
|
||||
} else if (object->IsSmi()) {
|
||||
Add(SMI);
|
||||
return Smi::cast(*object)->value() != 0;
|
||||
} else if (object->IsUndetectableObject()) {
|
||||
Add(UNDETECTABLE);
|
||||
return false;
|
||||
} else if (object->IsSpecObject()) {
|
||||
Add(SPEC_OBJECT);
|
||||
return true;
|
||||
return !object->IsUndetectableObject();
|
||||
} else if (object->IsString()) {
|
||||
Add(STRING);
|
||||
return String::cast(*object)->length() != 0;
|
||||
return !object->IsUndetectableObject() &&
|
||||
String::cast(*object)->length() != 0;
|
||||
} else if (object->IsHeapNumber()) {
|
||||
Add(HEAP_NUMBER);
|
||||
double value = HeapNumber::cast(*object)->value();
|
||||
return value != 0 && !isnan(value);
|
||||
return !object->IsUndetectableObject() && value != 0 && !isnan(value);
|
||||
} else {
|
||||
Add(INTERNAL_OBJECT);
|
||||
return true;
|
||||
return !object->IsUndetectableObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -905,7 +905,6 @@ class ToBooleanStub: public CodeStub {
|
||||
BOOLEAN,
|
||||
NULL_TYPE,
|
||||
SMI,
|
||||
UNDETECTABLE,
|
||||
SPEC_OBJECT,
|
||||
STRING,
|
||||
HEAP_NUMBER,
|
||||
@ -913,21 +912,25 @@ class ToBooleanStub: public CodeStub {
|
||||
NUMBER_OF_TYPES
|
||||
};
|
||||
|
||||
// At most 8 different types can be distinguished, because the Code object
|
||||
// only has room for a single byte to hold a set of these types. :-P
|
||||
STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
|
||||
|
||||
class Types {
|
||||
public:
|
||||
Types() {}
|
||||
explicit Types(int bits) : set_(bits) {}
|
||||
explicit Types(byte bits) : set_(bits) {}
|
||||
|
||||
bool IsEmpty() const { return set_.IsEmpty(); }
|
||||
bool Contains(Type type) const { return set_.Contains(type); }
|
||||
void Add(Type type) { set_.Add(type); }
|
||||
int ToInt() const { return set_.ToIntegral(); }
|
||||
byte ToByte() const { return set_.ToIntegral(); }
|
||||
void Print(StringStream* stream);
|
||||
void TraceTransition(Types to);
|
||||
bool Record(Handle<Object> object);
|
||||
|
||||
private:
|
||||
EnumSet<Type> set_;
|
||||
EnumSet<Type, byte> set_;
|
||||
};
|
||||
|
||||
explicit ToBooleanStub(Register tos, Types types = Types())
|
||||
@ -939,7 +942,11 @@ class ToBooleanStub: public CodeStub {
|
||||
|
||||
private:
|
||||
Major MajorKey() { return ToBoolean; }
|
||||
int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToInt(); }
|
||||
int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); }
|
||||
|
||||
virtual void FinishCode(Code* code) {
|
||||
code->set_to_boolean_state(types_.ToByte());
|
||||
}
|
||||
|
||||
void CheckOddball(MacroAssembler* masm,
|
||||
Type type,
|
||||
|
@ -259,7 +259,6 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
|
||||
CheckOddball(masm, NULL_TYPE, factory->null_value(), false, &patch);
|
||||
|
||||
bool need_map =
|
||||
types_.Contains(UNDETECTABLE) |
|
||||
types_.Contains(SPEC_OBJECT) |
|
||||
types_.Contains(STRING) |
|
||||
types_.Contains(HEAP_NUMBER) |
|
||||
@ -286,17 +285,12 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
|
||||
// Everything with a map could be undetectable, so check this now.
|
||||
__ test_b(FieldOperand(map, Map::kBitFieldOffset),
|
||||
1 << Map::kIsUndetectable);
|
||||
if (types_.Contains(UNDETECTABLE)) {
|
||||
// Undetectable -> false.
|
||||
Label not_undetectable;
|
||||
__ j(zero, ¬_undetectable, Label::kNear);
|
||||
__ Set(tos_, Immediate(0));
|
||||
__ ret(1 * kPointerSize);
|
||||
__ bind(¬_undetectable);
|
||||
} else {
|
||||
// We've seen an undetectable value for the first time -> patch.
|
||||
__ j(not_zero, &patch, Label::kNear);
|
||||
}
|
||||
// Undetectable -> false.
|
||||
Label not_undetectable;
|
||||
__ j(zero, ¬_undetectable, Label::kNear);
|
||||
__ Set(tos_, Immediate(0));
|
||||
__ ret(1 * kPointerSize);
|
||||
__ bind(¬_undetectable);
|
||||
}
|
||||
|
||||
if (types_.Contains(SPEC_OBJECT)) {
|
||||
@ -385,7 +379,7 @@ void ToBooleanStub::CheckOddball(MacroAssembler* masm,
|
||||
void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||
__ pop(ecx); // Get return address, operand is now on top of stack.
|
||||
__ push(Immediate(Smi::FromInt(tos_.code())));
|
||||
__ push(Immediate(Smi::FromInt(types_.ToInt())));
|
||||
__ push(Immediate(Smi::FromInt(types_.ToByte())));
|
||||
__ push(ecx); // Push return address.
|
||||
// Patch the caller to an appropriate specialized stub and return the
|
||||
// operation result to the caller of the stub.
|
||||
|
Loading…
Reference in New Issue
Block a user