| Index: src/crankshaft/hydrogen.cc
|
| diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc
|
| index 5de76742a46959cb0b61bf9c6b1e45669f158d33..5a1e40308e9f099ce7871dd40b784b24ebaaca77 100644
|
| --- a/src/crankshaft/hydrogen.cc
|
| +++ b/src/crankshaft/hydrogen.cc
|
| @@ -6780,18 +6780,48 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
|
| }
|
| }
|
|
|
| -
|
| -static bool ComputeReceiverTypes(Expression* expr,
|
| - HValue* receiver,
|
| +static bool ComputeReceiverTypes(Expression* expr, HValue* receiver,
|
| SmallMapList** t,
|
| - Zone* zone) {
|
| + HOptimizedGraphBuilder* builder) {
|
| + Zone* zone = builder->zone();
|
| SmallMapList* maps = expr->GetReceiverTypes();
|
| *t = maps;
|
| bool monomorphic = expr->IsMonomorphic();
|
| if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
|
| - Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
|
| - maps->FilterForPossibleTransitions(root_map);
|
| - monomorphic = maps->length() == 1;
|
| + if (maps->length() > 0) {
|
| + Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
|
| + maps->FilterForPossibleTransitions(root_map);
|
| + monomorphic = maps->length() == 1;
|
| + } else {
|
| + // No type feedback, see if we can infer the type. This is safely
|
| + // possible if the receiver had a known map at some point, and no
|
| + // map-changing stores have happened to it since.
|
| + Handle<Map> candidate_map = receiver->GetMonomorphicJSObjectMap();
|
| + if (candidate_map->is_observed()) return false;
|
| + for (HInstruction* current = builder->current_block()->last();
|
| + current != nullptr; current = current->previous()) {
|
| + if (current->IsBlockEntry()) break;
|
| + if (current->CheckChangesFlag(kMaps)) {
|
| + // Only allow map changes that store the candidate map. We don't
|
| + // need to care which object the map is being written into.
|
| + if (!current->IsStoreNamedField()) break;
|
| + HStoreNamedField* map_change = HStoreNamedField::cast(current);
|
| + if (!map_change->value()->IsConstant()) break;
|
| + HConstant* map_constant = HConstant::cast(map_change->value());
|
| + if (!map_constant->representation().IsTagged()) break;
|
| + Handle<Object> map = map_constant->handle(builder->isolate());
|
| + if (!map.is_identical_to(candidate_map)) break;
|
| + }
|
| + if (current == receiver) {
|
| + // We made it all the way back to the receiver without encountering
|
| + // a map change! So we can assume that the receiver still has the
|
| + // candidate_map we know about.
|
| + maps->Add(candidate_map, zone);
|
| + monomorphic = true;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| }
|
| return monomorphic && CanInlinePropertyAccess(maps->first());
|
| }
|
| @@ -7700,7 +7730,7 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
| HInstruction* instr = NULL;
|
|
|
| SmallMapList* maps;
|
| - bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());
|
| + bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, this);
|
|
|
| bool force_generic = false;
|
| if (expr->GetKeyType() == PROPERTY) {
|
| @@ -7857,7 +7887,7 @@ HValue* HOptimizedGraphBuilder::BuildNamedAccess(
|
| Expression* expr, FeedbackVectorSlot slot, HValue* object,
|
| Handle<Name> name, HValue* value, bool is_uninitialized) {
|
| SmallMapList* maps;
|
| - ComputeReceiverTypes(expr, object, &maps, zone());
|
| + ComputeReceiverTypes(expr, object, &maps, this);
|
| DCHECK(maps != NULL);
|
|
|
| if (maps->length() > 0) {
|
| @@ -9701,7 +9731,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| HValue* receiver = Top();
|
|
|
| SmallMapList* maps;
|
| - ComputeReceiverTypes(expr, receiver, &maps, zone());
|
| + ComputeReceiverTypes(expr, receiver, &maps, this);
|
|
|
| if (prop->key()->IsPropertyName() && maps->length() > 0) {
|
| Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
|
|
|