Merge polymorphic load/store handling
R=dcarney@chromium.org Review URL: https://codereview.chromium.org/150573010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19106 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9743d254f3
commit
cb044fa2d8
153
src/hydrogen.cc
153
src/hydrogen.cc
@ -5610,10 +5610,12 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreMonomorphic(
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
||||
void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
|
||||
PropertyAccessType access_type,
|
||||
BailoutId ast_id,
|
||||
BailoutId return_id,
|
||||
HValue* object,
|
||||
HValue* value,
|
||||
SmallMapList* types,
|
||||
Handle<String> name) {
|
||||
// Something did not match; must use a polymorphic load.
|
||||
@ -5623,8 +5625,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
||||
bool handled_string = false;
|
||||
|
||||
bool handle_smi = false;
|
||||
STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
|
||||
for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
|
||||
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
|
||||
PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
|
||||
if (info.type()->Is(Type::String())) {
|
||||
if (handled_string) continue;
|
||||
handled_string = true;
|
||||
@ -5643,7 +5646,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
||||
handled_string = false;
|
||||
|
||||
for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
|
||||
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
|
||||
PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
|
||||
if (info.type()->Is(Type::String())) {
|
||||
if (handled_string) continue;
|
||||
handled_string = true;
|
||||
@ -5692,16 +5695,28 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
||||
|
||||
set_current_block(if_true);
|
||||
|
||||
HInstruction* load = BuildLoadMonomorphic(
|
||||
&info, object, dependency, ast_id,
|
||||
return_id, FLAG_polymorphic_inlining);
|
||||
if (load == NULL) {
|
||||
HInstruction* access = NULL;
|
||||
HValue* result = NULL;
|
||||
switch (access_type) {
|
||||
case LOAD:
|
||||
access = BuildLoadMonomorphic(
|
||||
&info, object, dependency, ast_id,
|
||||
return_id, FLAG_polymorphic_inlining);
|
||||
result = access;
|
||||
break;
|
||||
case STORE:
|
||||
access = BuildStoreMonomorphic(
|
||||
&info, dependency, value, ast_id, return_id,
|
||||
FLAG_polymorphic_inlining);
|
||||
result = value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (access == NULL) {
|
||||
if (HasStackOverflow()) return;
|
||||
} else {
|
||||
if (!load->IsLinked()) {
|
||||
AddInstruction(load);
|
||||
}
|
||||
if (!ast_context()->IsEffect()) Push(load);
|
||||
if (!access->IsLinked()) AddInstruction(access);
|
||||
if (!ast_context()->IsEffect()) Push(result);
|
||||
}
|
||||
|
||||
if (current_block() != NULL) Goto(join);
|
||||
@ -5716,10 +5731,28 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
||||
// that the environment stack matches the depth on deopt that it otherwise
|
||||
// would have had after a successful load.
|
||||
if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
|
||||
FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
|
||||
const char* message = "";
|
||||
switch (access_type) {
|
||||
case LOAD:
|
||||
message = "Unknown map in polymorphic load";
|
||||
break;
|
||||
case STORE:
|
||||
message = "Unknown map in polymorphic store";
|
||||
break;
|
||||
}
|
||||
FinishExitWithHardDeoptimization(message, join);
|
||||
} else {
|
||||
HInstruction* load = Add<HLoadNamedGeneric>(object, name);
|
||||
if (!ast_context()->IsEffect()) Push(load);
|
||||
HValue* result = NULL;
|
||||
switch (access_type) {
|
||||
case LOAD:
|
||||
result = Add<HLoadNamedGeneric>(object, name);
|
||||
break;
|
||||
case STORE:
|
||||
AddInstruction(BuildStoreNamedGeneric(object, name, value));
|
||||
result = value;
|
||||
break;
|
||||
}
|
||||
if (!ast_context()->IsEffect()) Push(result);
|
||||
|
||||
if (join != NULL) {
|
||||
Goto(join);
|
||||
@ -5737,90 +5770,6 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
||||
BailoutId assignment_id,
|
||||
BailoutId return_id,
|
||||
HValue* object,
|
||||
HValue* value,
|
||||
SmallMapList* types,
|
||||
Handle<String> name) {
|
||||
int count = 0;
|
||||
HBasicBlock* join = NULL;
|
||||
// TODO(verwaest): Unify with polymorphic load handling.
|
||||
for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
|
||||
PropertyAccessInfo info(this, STORE, ToType(types->at(i)), name);
|
||||
if (info.CanAccessMonomorphic()) {
|
||||
if (count == 0) {
|
||||
BuildCheckHeapObject(object);
|
||||
join = graph()->CreateBasicBlock();
|
||||
}
|
||||
++count;
|
||||
HBasicBlock* if_true = graph()->CreateBasicBlock();
|
||||
HBasicBlock* if_false = graph()->CreateBasicBlock();
|
||||
HCompareMap* compare = New<HCompareMap>(
|
||||
object, info.map(), if_true, if_false);
|
||||
FinishCurrentBlock(compare);
|
||||
|
||||
set_current_block(if_true);
|
||||
|
||||
HInstruction* store;
|
||||
store = BuildStoreMonomorphic(
|
||||
&info, compare, value, assignment_id, return_id,
|
||||
FLAG_polymorphic_inlining);
|
||||
|
||||
if (store == NULL) {
|
||||
if (HasStackOverflow()) return;
|
||||
} else {
|
||||
ASSERT(!store->IsLinked());
|
||||
AddInstruction(store);
|
||||
if (!ast_context()->IsEffect()) Push(value);
|
||||
}
|
||||
|
||||
if (current_block() != NULL) Goto(join);
|
||||
set_current_block(if_false);
|
||||
}
|
||||
}
|
||||
|
||||
// Finish up. Unconditionally deoptimize if we've handled all the maps we
|
||||
// know about and do not want to handle ones we've never seen. Otherwise
|
||||
// use a generic IC.
|
||||
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
|
||||
FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
|
||||
} else {
|
||||
HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
|
||||
AddInstruction(instr);
|
||||
|
||||
if (join != NULL) {
|
||||
if (!ast_context()->IsEffect()) {
|
||||
Push(value);
|
||||
}
|
||||
Goto(join);
|
||||
} else {
|
||||
// The HSimulate for the store should not see the stored value in
|
||||
// effect contexts (it is not materialized at expr->id() in the
|
||||
// unoptimized code).
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
if (ast_context()->IsEffect()) {
|
||||
Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
|
||||
} else {
|
||||
Push(value);
|
||||
Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
|
||||
Drop(1);
|
||||
}
|
||||
}
|
||||
return ast_context()->ReturnValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(join != NULL);
|
||||
join->SetJoinId(assignment_id);
|
||||
set_current_block(join);
|
||||
if (!ast_context()->IsEffect()) {
|
||||
ast_context()->ReturnValue(Pop());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool ComputeReceiverTypes(Expression* expr,
|
||||
HValue* receiver,
|
||||
SmallMapList** t,
|
||||
@ -5882,8 +5831,8 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr,
|
||||
if (types->length() > 0) {
|
||||
PropertyAccessInfo info(this, STORE, ToType(types->first()), name);
|
||||
if (!info.CanAccessAsMonomorphic(types)) {
|
||||
return HandlePolymorphicStoreNamedField(
|
||||
ast_id, return_id, object, value, types, name);
|
||||
return HandlePolymorphicNamedFieldAccess(
|
||||
STORE, ast_id, return_id, object, value, types, name);
|
||||
}
|
||||
|
||||
ASSERT(!info.type()->Is(Type::Number()));
|
||||
@ -6734,8 +6683,8 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
|
||||
if (types->length() > 0) {
|
||||
PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
|
||||
if (!info.CanAccessAsMonomorphic(types)) {
|
||||
return HandlePolymorphicLoadNamedField(
|
||||
ast_id, expr->LoadId(), object, types, name);
|
||||
return HandlePolymorphicNamedFieldAccess(
|
||||
LOAD, ast_id, expr->LoadId(), object, NULL, types, name);
|
||||
}
|
||||
|
||||
HValue* checked_object;
|
||||
|
@ -2187,6 +2187,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
Type* ToType(Handle<Map> map) { return IC::MapToType<Type>(map, zone()); }
|
||||
|
||||
private:
|
||||
enum PropertyAccessType { LOAD, STORE };
|
||||
|
||||
// Helpers for flow graph construction.
|
||||
enum GlobalPropertyAccess {
|
||||
kUseCell,
|
||||
@ -2251,11 +2253,13 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
|
||||
void HandlePropertyAssignment(Assignment* expr);
|
||||
void HandleCompoundAssignment(Assignment* expr);
|
||||
void HandlePolymorphicLoadNamedField(BailoutId ast_id,
|
||||
BailoutId return_id,
|
||||
HValue* object,
|
||||
SmallMapList* types,
|
||||
Handle<String> name);
|
||||
void HandlePolymorphicNamedFieldAccess(PropertyAccessType access_type,
|
||||
BailoutId ast_id,
|
||||
BailoutId return_id,
|
||||
HValue* object,
|
||||
HValue* value,
|
||||
SmallMapList* types,
|
||||
Handle<String> name);
|
||||
|
||||
void VisitTypedArrayInitialize(CallRuntime* expr);
|
||||
|
||||
@ -2264,7 +2268,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
|
||||
void VisitDataViewInitialize(CallRuntime* expr);
|
||||
|
||||
enum PropertyAccessType { LOAD, STORE };
|
||||
class PropertyAccessInfo {
|
||||
public:
|
||||
PropertyAccessInfo(HOptimizedGraphBuilder* builder,
|
||||
@ -2390,12 +2393,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
BailoutId return_id,
|
||||
bool can_inline_accessor = true);
|
||||
|
||||
void HandlePolymorphicStoreNamedField(BailoutId assignment_id,
|
||||
BailoutId return_id,
|
||||
HValue* object,
|
||||
HValue* value,
|
||||
SmallMapList* types,
|
||||
Handle<String> name);
|
||||
void HandlePolymorphicCallNamed(Call* expr,
|
||||
HValue* receiver,
|
||||
SmallMapList* types,
|
||||
|
Loading…
Reference in New Issue
Block a user