}
+// 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);
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,