Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 51ae7f5a44c29fc4b69f66651b95fcfef7a6f2fa..bad612c825a44a1dce4dbbf5a95e84c340379eb2 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, ie, are elements |
danno
2012/11/13 22:52:32
nit: i.e.
Toon Verwaest
2012/11/14 11:57:38
Done.
|
+// 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) { |
danno
2012/11/13 22:52:32
Maybe this should be a static method on Map? I kno
Toon Verwaest
2012/11/14 11:57:38
For now I'd keep it here. I doubt that he can reus
|
+ 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) { |
danno
2012/11/13 22:52:32
since you handle both cases, why not make it "if (
Toon Verwaest
2012/11/14 11:57:38
Done.
|
+ Map* family_map = CheckSameElementsFamily(types); |
+ if (family_map != NULL) { |
+ receiver_map = Handle<Map>(family_map); |
+ monomorphic = expr->ComputeTarget(receiver_map, name); |
+ } |
+ } else { |
+ receiver_map = (types == NULL || types->is_empty()) |
? Handle<Map>::null() |
: types->first(); |
+ } |
+ |
+ HValue* receiver = |
+ environment()->ExpressionStackAt(expr->arguments()->length()); |
+ if (monomorphic) { |
if (TryInlineBuiltinMethodCall(expr, |
receiver, |
receiver_map, |