| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 51ae7f5a44c29fc4b69f66651b95fcfef7a6f2fa..0a25bb039ae0ffeb4d62ee77fa6d8fbca69484f0 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -7512,6 +7512,55 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
|
| }
|
|
|
|
|
| +// Checks if all maps in |types| are from the same family, i.e., are elements
|
| +// transitions of each other. Returns either NULL if they are not from the same
|
| +// family, or a Map* indicating the map with the first elements kind of the
|
| +// family that is in the list.
|
| +static Map* CheckSameElementsFamily(SmallMapList* types) {
|
| + if (types->length() <= 1) return NULL;
|
| + // Check if all maps belong to the same transition family.
|
| + Map* kinds[kFastElementsKindCount];
|
| + Map* first_map = *types->first();
|
| + ElementsKind first_kind = first_map->elements_kind();
|
| + if (!IsFastElementsKind(first_kind)) return NULL;
|
| + int first_index = GetSequenceIndexFromFastElementsKind(first_kind);
|
| + int last_index = first_index;
|
| +
|
| + for (int i = 0; i < kFastElementsKindCount; i++) kinds[i] = NULL;
|
| +
|
| + kinds[first_index] = first_map;
|
| +
|
| + for (int i = 1; i < types->length(); ++i) {
|
| + Map* map = *types->at(i);
|
| + ElementsKind elements_kind = map->elements_kind();
|
| + if (!IsFastElementsKind(elements_kind)) return NULL;
|
| + int index = GetSequenceIndexFromFastElementsKind(elements_kind);
|
| + if (index < first_index) {
|
| + first_index = index;
|
| + } else if (index > last_index) {
|
| + last_index = index;
|
| + } else if (kinds[index] != map) {
|
| + return NULL;
|
| + }
|
| + kinds[index] = map;
|
| + }
|
| +
|
| + Map* current = kinds[first_index];
|
| + for (int i = first_index + 1; i <= last_index; i++) {
|
| + Map* next = kinds[i];
|
| + if (next != NULL) {
|
| + ElementsKind current_kind = next->elements_kind();
|
| + if (next != current->LookupElementsTransitionMap(current_kind)) {
|
| + return NULL;
|
| + }
|
| + current = next;
|
| + }
|
| + }
|
| +
|
| + return kinds[first_index];
|
| +}
|
| +
|
| +
|
| void HGraphBuilder::VisitCall(Call* expr) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| @@ -7551,15 +7600,25 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
| CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
|
|
| Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
|
| -
|
| SmallMapList* types = expr->GetReceiverTypes();
|
|
|
| - HValue* receiver =
|
| - environment()->ExpressionStackAt(expr->arguments()->length());
|
| - if (expr->IsMonomorphic()) {
|
| - Handle<Map> receiver_map = (types == NULL || types->is_empty())
|
| + bool monomorphic = expr->IsMonomorphic();
|
| + Handle<Map> receiver_map;
|
| + if (monomorphic) {
|
| + receiver_map = (types == NULL || types->is_empty())
|
| ? Handle<Map>::null()
|
| : types->first();
|
| + } else {
|
| + Map* family_map = CheckSameElementsFamily(types);
|
| + if (family_map != NULL) {
|
| + receiver_map = Handle<Map>(family_map);
|
| + monomorphic = expr->ComputeTarget(receiver_map, name);
|
| + }
|
| + }
|
| +
|
| + HValue* receiver =
|
| + environment()->ExpressionStackAt(expr->arguments()->length());
|
| + if (monomorphic) {
|
| if (TryInlineBuiltinMethodCall(expr,
|
| receiver,
|
| receiver_map,
|
|
|