Implement KnownSuccessor method to some control instructions.

R=jkummerow@chromium.org
BUG=v8:3118
LOG=N

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19759 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2014-03-10 14:50:01 +00:00
parent be8e2885d3
commit 78d23e5662
5 changed files with 221 additions and 60 deletions

View File

@ -1215,18 +1215,52 @@ void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
stream->Add(" == %o", *type_literal_);
stream->Add(" == %o", *type_literal_.handle());
HControlInstruction::PrintDataTo(stream);
}
bool HTypeofIsAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (value()->representation().IsSpecialization()) {
if (compares_number_type()) {
*block = FirstSuccessor();
} else {
*block = SecondSuccessor();
static String* TypeOfString(HConstant* constant, Isolate* isolate) {
Heap* heap = isolate->heap();
if (constant->HasNumberValue()) return heap->number_string();
if (constant->IsUndetectable()) return heap->undefined_string();
if (constant->HasStringValue()) return heap->string_string();
switch (constant->GetInstanceType()) {
case ODDBALL_TYPE: {
Unique<Object> unique = constant->GetUnique();
if (unique.IsKnownGlobal(heap->true_value()) ||
unique.IsKnownGlobal(heap->false_value())) {
return heap->boolean_string();
}
if (unique.IsKnownGlobal(heap->null_value())) {
return FLAG_harmony_typeof ? heap->null_string()
: heap->object_string();
}
ASSERT(unique.IsKnownGlobal(heap->undefined_value()));
return heap->undefined_string();
}
case SYMBOL_TYPE:
return heap->symbol_string();
case JS_FUNCTION_TYPE:
case JS_FUNCTION_PROXY_TYPE:
return heap->function_string();
default:
return heap->object_string();
}
}
bool HTypeofIsAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
HConstant* constant = HConstant::cast(value());
String* type_string = TypeOfString(constant, isolate());
bool same_type = type_literal_.IsKnownGlobal(type_string);
*block = same_type ? FirstSuccessor() : SecondSuccessor();
return true;
} else if (value()->representation().IsSpecialization()) {
bool number_type =
type_literal_.IsKnownGlobal(isolate()->heap()->number_string());
*block = number_type ? FirstSuccessor() : SecondSuccessor();
return true;
}
*block = NULL;
@ -2498,13 +2532,16 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
has_int32_value_(false),
has_double_value_(false),
has_external_reference_value_(false),
is_internalized_string_(false),
is_not_in_new_space_(true),
is_cell_(false),
boolean_value_(handle->BooleanValue()) {
boolean_value_(handle->BooleanValue()),
is_undetectable_(false),
instance_type_(kUnknownInstanceType) {
if (handle->IsHeapObject()) {
Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap();
Handle<HeapObject> heap_obj = Handle<HeapObject>::cast(handle);
Heap* heap = heap_obj->GetHeap();
is_not_in_new_space_ = !heap->InNewSpace(*handle);
instance_type_ = heap_obj->map()->instance_type();
is_undetectable_ = heap_obj->map()->is_undetectable();
}
if (handle->IsNumber()) {
double n = handle->Number();
@ -2514,12 +2551,8 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
double_value_ = n;
has_double_value_ = true;
// TODO(titzer): if this heap number is new space, tenure a new one.
} else {
is_internalized_string_ = handle->IsInternalizedString();
}
is_cell_ = !handle.is_null() &&
(handle->IsCell() || handle->IsPropertyCell());
Initialize(r);
}
@ -2527,20 +2560,20 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
HConstant::HConstant(Unique<Object> unique,
Representation r,
HType type,
bool is_internalize_string,
bool is_not_in_new_space,
bool is_cell,
bool boolean_value)
bool boolean_value,
bool is_undetectable,
InstanceType instance_type)
: HTemplateInstruction<0>(type),
object_(unique),
has_smi_value_(false),
has_int32_value_(false),
has_double_value_(false),
has_external_reference_value_(false),
is_internalized_string_(is_internalize_string),
is_not_in_new_space_(is_not_in_new_space),
is_cell_(is_cell),
boolean_value_(boolean_value) {
boolean_value_(boolean_value),
is_undetectable_(is_undetectable),
instance_type_(instance_type) {
ASSERT(!unique.handle().is_null());
ASSERT(!type.IsTaggedNumber());
Initialize(r);
@ -2556,12 +2589,12 @@ HConstant::HConstant(int32_t integer_value,
has_int32_value_(true),
has_double_value_(true),
has_external_reference_value_(false),
is_internalized_string_(false),
is_not_in_new_space_(is_not_in_new_space),
is_cell_(false),
boolean_value_(integer_value != 0),
is_undetectable_(false),
int32_value_(integer_value),
double_value_(FastI2D(integer_value)) {
double_value_(FastI2D(integer_value)),
instance_type_(kUnknownInstanceType) {
// It's possible to create a constant with a value in Smi-range but stored
// in a (pre-existing) HeapNumber. See crbug.com/349878.
bool could_be_heapobject = r.IsTagged() && !object.handle().is_null();
@ -2579,12 +2612,12 @@ HConstant::HConstant(double double_value,
has_int32_value_(IsInteger32(double_value)),
has_double_value_(true),
has_external_reference_value_(false),
is_internalized_string_(false),
is_not_in_new_space_(is_not_in_new_space),
is_cell_(false),
boolean_value_(double_value != 0 && !std::isnan(double_value)),
is_undetectable_(false),
int32_value_(DoubleToInt32(double_value)),
double_value_(double_value) {
double_value_(double_value),
instance_type_(kUnknownInstanceType) {
has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
// It's possible to create a constant with a value in Smi-range but stored
// in a (pre-existing) HeapNumber. See crbug.com/349878.
@ -2602,11 +2635,11 @@ HConstant::HConstant(ExternalReference reference)
has_int32_value_(false),
has_double_value_(false),
has_external_reference_value_(true),
is_internalized_string_(false),
is_not_in_new_space_(true),
is_cell_(false),
boolean_value_(true),
external_reference_value_(reference) {
is_undetectable_(false),
external_reference_value_(reference),
instance_type_(kUnknownInstanceType) {
Initialize(Representation::External());
}
@ -2705,10 +2738,10 @@ HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
return new(zone) HConstant(object_,
r,
type_,
is_internalized_string_,
is_not_in_new_space_,
is_cell_,
boolean_value_);
boolean_value_,
is_undetectable_,
instance_type_);
}
@ -3022,12 +3055,77 @@ void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) {
bool HCompareObjectEqAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (left()->IsConstant() && right()->IsConstant()) {
bool comparison_result =
HConstant::cast(left())->Equals(HConstant::cast(right()));
*block = comparison_result
? FirstSuccessor()
: SecondSuccessor();
if (FLAG_fold_constants && left()->IsConstant() && right()->IsConstant()) {
*block = HConstant::cast(left())->Equals(HConstant::cast(right()))
? FirstSuccessor() : SecondSuccessor();
return true;
}
*block = NULL;
return false;
}
bool ConstantIsObject(HConstant* constant, Isolate* isolate) {
if (constant->HasNumberValue()) return false;
if (constant->GetUnique().IsKnownGlobal(isolate->heap()->null_value())) {
return true;
}
if (constant->IsUndetectable()) return false;
InstanceType type = constant->GetInstanceType();
return (FIRST_NONCALLABLE_SPEC_OBJECT_TYPE <= type) &&
(type <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
}
bool HIsObjectAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
*block = ConstantIsObject(HConstant::cast(value()), isolate())
? FirstSuccessor() : SecondSuccessor();
return true;
}
*block = NULL;
return false;
}
bool HIsStringAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
*block = HConstant::cast(value())->HasStringValue()
? FirstSuccessor() : SecondSuccessor();
return true;
}
*block = NULL;
return false;
}
bool HIsSmiAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
*block = HConstant::cast(value())->HasSmiValue()
? FirstSuccessor() : SecondSuccessor();
return true;
}
*block = NULL;
return false;
}
bool HIsUndetectableAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
*block = HConstant::cast(value())->IsUndetectable()
? FirstSuccessor() : SecondSuccessor();
return true;
}
*block = NULL;
return false;
}
bool HHasInstanceTypeAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
InstanceType type = HConstant::cast(value())->GetInstanceType();
*block = (from_ <= type) && (type <= to_)
? FirstSuccessor() : SecondSuccessor();
return true;
}
*block = NULL;
@ -3042,6 +3140,14 @@ void HCompareHoleAndBranch::InferRepresentation(
bool HCompareMinusZeroAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
HConstant* constant = HConstant::cast(value());
if (constant->HasDoubleValue()) {
*block = IsMinusZero(constant->DoubleValue())
? FirstSuccessor() : SecondSuccessor();
}
return true;
}
if (value()->representation().IsSmiOrInteger32()) {
// A Smi or Integer32 cannot contain minus zero.
*block = SecondSuccessor();

View File

@ -3451,8 +3451,8 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
bool is_not_in_new_space,
HInstruction* instruction) {
return instruction->Prepend(new(zone) HConstant(
unique, Representation::Tagged(), HType::Tagged(), false,
is_not_in_new_space, false, false));
unique, Representation::Tagged(), HType::Tagged(),
is_not_in_new_space, false, false, kUnknownInstanceType));
}
Handle<Object> handle(Isolate* isolate) {
@ -3487,7 +3487,7 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
bool ImmortalImmovable() const;
bool IsCell() const {
return is_cell_;
return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
}
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
@ -3535,14 +3535,14 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
bool HasStringValue() const {
if (has_double_value_ || has_int32_value_) return false;
ASSERT(!object_.handle().is_null());
return type_.IsString();
return instance_type_ < FIRST_NONSTRING_TYPE;
}
Handle<String> StringValue() const {
ASSERT(HasStringValue());
return Handle<String>::cast(object_.handle());
}
bool HasInternalizedStringValue() const {
return HasStringValue() && is_internalized_string_;
return HasStringValue() && StringShape(instance_type_).IsInternalized();
}
bool HasExternalReferenceValue() const {
@ -3554,6 +3554,8 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
bool HasBooleanValue() const { return type_.IsBoolean(); }
bool BooleanValue() const { return boolean_value_; }
bool IsUndetectable() const { return is_undetectable_; }
InstanceType GetInstanceType() const { return instance_type_; }
virtual intptr_t Hashcode() V8_OVERRIDE {
if (has_int32_value_) {
@ -3630,10 +3632,10 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
HConstant(Unique<Object> unique,
Representation r,
HType type,
bool is_internalized_string,
bool is_not_in_new_space,
bool is_cell,
bool boolean_value);
bool boolean_value,
bool is_undetectable,
InstanceType instance_type);
explicit HConstant(ExternalReference reference);
@ -3656,13 +3658,15 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
bool has_int32_value_ : 1;
bool has_double_value_ : 1;
bool has_external_reference_value_ : 1;
bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType.
bool is_not_in_new_space_ : 1;
bool is_cell_ : 1;
bool boolean_value_ : 1;
bool is_undetectable_: 1;
int32_t int32_value_;
double double_value_;
ExternalReference external_reference_value_;
static const InstanceType kUnknownInstanceType = FILLER_TYPE;
InstanceType instance_type_;
};
@ -4328,6 +4332,8 @@ class HIsObjectAndBranch V8_FINAL : public HUnaryControlInstruction {
return Representation::Tagged();
}
virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
private:
@ -4348,6 +4354,8 @@ class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
return Representation::Tagged();
}
virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
protected:
@ -4373,6 +4381,8 @@ class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
return Representation::Tagged();
}
virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
protected:
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
virtual int RedefinedOperandIndex() { return 0; }
@ -4395,6 +4405,8 @@ class HIsUndetectableAndBranch V8_FINAL : public HUnaryControlInstruction {
return Representation::Tagged();
}
virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
private:
@ -4477,6 +4489,8 @@ class HHasInstanceTypeAndBranch V8_FINAL : public HUnaryControlInstruction {
return Representation::Tagged();
}
virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
private:
@ -4558,8 +4572,7 @@ class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
public:
DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
Handle<String> type_literal() { return type_literal_; }
bool compares_number_type() { return compares_number_type_; }
Handle<String> type_literal() { return type_literal_.handle(); }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
@ -4570,16 +4583,16 @@ class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
virtual void FinalizeUniqueness() V8_OVERRIDE {
type_literal_ = Unique<String>(type_literal_.handle());
}
private:
HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
: HUnaryControlInstruction(value, NULL, NULL),
type_literal_(type_literal) {
Heap* heap = type_literal->GetHeap();
compares_number_type_ = type_literal->Equals(heap->number_string());
}
type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
Handle<String> type_literal_;
bool compares_number_type_ : 1;
Unique<String> type_literal_;
};

View File

@ -707,10 +707,10 @@ HConstant* HGraph::GetConstant##Name() { \
Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
Representation::Tagged(), \
htype, \
false, \
true, \
boolean_value, \
false, \
boolean_value); \
ODDBALL_TYPE); \
constant->InsertAfter(entry_block()->first()); \
constant_##name##_.set(constant); \
} \

View File

@ -2082,7 +2082,6 @@ bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
}
void Object::VerifyApiCallResultType() {
#if ENABLE_EXTRA_CHECKS
if (!(IsSmi() ||

View File

@ -0,0 +1,43 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --fold-constants
function test() {
assertEquals("string", typeof "");
assertEquals("number", typeof 1.1);
assertEquals("number", typeof 1);
assertEquals("boolean", typeof true);
assertEquals("function", typeof function() {});
assertEquals("object", typeof null);
assertEquals("object", typeof {});
assertTrue(%_IsObject({}));
assertTrue(%_IsObject(null));
assertTrue(%_IsObject(/regex/));
assertFalse(%_IsObject(0));
assertFalse(%_IsObject(""));
assertTrue(%_IsSmi(1));
assertFalse(%_IsSmi(1.1));
assertFalse(%_IsSmi({}));
assertTrue(%_IsRegExp(/regexp/));
assertFalse(%_IsRegExp({}));
assertTrue(%_IsArray([1]));
assertFalse(%_IsArray(function() {}));
assertTrue(%_IsFunction(function() {}));
assertFalse(%_IsFunction(null));
assertTrue(%_IsSpecObject(new Date()));
assertFalse(%_IsSpecObject(1));
}
test();
test();
%OptimizeFunctionOnNextCall(test);
test();