| Index: src/hydrogen-instructions.cc
|
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
|
| index ec23e1971b7923d14b11ca23622cb900dbcbcd24..d61944645950963c8eb34de52bf350a19401a1cd 100644
|
| --- a/src/hydrogen-instructions.cc
|
| +++ b/src/hydrogen-instructions.cc
|
| @@ -2069,7 +2069,8 @@ HValue* HLoadKeyedGeneric::Canonicalize() {
|
| index_cache,
|
| key_load->key(),
|
| key_load->key(),
|
| - key_load->elements_kind());
|
| + key_load->elements_kind(),
|
| + block()->zone());
|
| map_check->InsertBefore(this);
|
| index->InsertBefore(this);
|
| HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
|
| @@ -2721,6 +2722,142 @@ Representation HPhi::RepresentationFromUseRequirements() {
|
| }
|
|
|
|
|
| +TransitionElementsBookmark::TransitionElementsBookmark(
|
| + HTransitionElementsKind* transition,
|
| + Handle<Map> map_from, Handle<Map> map_to, Isolate* isolate)
|
| + : transition_(transition),
|
| + from_(map_from),
|
| + to_(map_to),
|
| + pessimistic_holey_() {
|
| +
|
| + // When transition records are created, we have the chance to create map
|
| + // transitions we might need later. Transitions are unified during
|
| + // optimization, and we may need to transition from a packed fastmap to a
|
| + // holey version of same. But we can't create those transitions during
|
| + // optimization. Do it now, recognizing that when the handle disappears these
|
| + // maps may be collected if they didn't make it into usage in the optimized
|
| + // graph.
|
| +
|
| + // TODO(mvstanton): generalize this service into
|
| + // "MakeWorstCaseMapForElementsKindTransition" (ie, not "holey")
|
| + if (IsFastPackedElementsKind(map_to->elements_kind())) {
|
| + ElementsKind holey_kind = GetHoleyElementsKind(map_to->elements_kind());
|
| + // The transition might already exist
|
| + Handle<Map> holey_map_handle(FindClosestElementsTransition(*map_to,
|
| + holey_kind));
|
| + ASSERT(!holey_map_handle.is_null());
|
| + if (holey_map_handle->elements_kind() != holey_kind) {
|
| + MaybeObject* holey_map = map_to->AddMissingElementsTransitions(
|
| + holey_kind);
|
| + holey_map->ToHandle<Map>(&pessimistic_holey_, isolate);
|
| + } else {
|
| + pessimistic_holey_ = holey_map_handle;
|
| + }
|
| + } else {
|
| + pessimistic_holey_ = map_to;
|
| + }
|
| +
|
| + ASSERT(!pessimistic_holey_.is_null());
|
| +
|
| + // fill in map_family_
|
| + // Walk up to the base map from the map_to();
|
| + Handle<Map> end_map(FindClosestElementsTransition(*map_to,
|
| + TERMINAL_FAST_ELEMENTS_KIND));
|
| + ASSERT(!end_map.is_null());
|
| + family_ = end_map;
|
| +}
|
| +
|
| +
|
| +void ArrayInstruction::PrintElementPlacementTo(StringStream* stream) {
|
| + stream->Add("SITE: block%d %d: ", block()->block_id(),
|
| + id());
|
| + PrintTo(stream);
|
| + stream->Add("\n");
|
| +
|
| + // Print validness
|
| + stream->Add(" HOISTABLE: %s\n", hoistable() ? "true" : "false");
|
| +
|
| + // Print score
|
| + // stream->Add(" SCORE: (+%d,%d,-%d)\n", score_[0], score_[1], score_[2]);
|
| +
|
| + // Find the def point for the instruction
|
| + HValue *element = elements();
|
| + ASSERT(element != NULL);
|
| + // Now get the item from the elements
|
| + ASSERT(element->IsLoadElements());
|
| + HValue *elements_value = HLoadElements::cast(element)->value();
|
| + stream->Add(" OBJECT: ");
|
| + elements_value->PrintNameTo(stream);
|
| + stream->Add(" ");
|
| + elements_value->PrintTo(stream);
|
| + stream->Add(" %s\n", elements_value->IsPhi() ? "PHI" : "");
|
| + stream->Add(" TRANSITIONS:\n");
|
| + ElementsKind transitionElementsKind = FAST_SMI_ELEMENTS;
|
| + for (int i = 0; i < bookmarks(); i++) {
|
| + TransitionElementsBookmark* b = bookmark(i);
|
| + stream->Add(" %s", ElementsKindToString(b->elementskind_from()));
|
| + stream->Add("(0x%p)-> ", *(b->from()));
|
| + transitionElementsKind = b->elementskind_to();
|
| + stream->Add("%s", ElementsKindToString(transitionElementsKind));
|
| + stream->Add("(0x%p)\n", *(b->to()));
|
| + }
|
| +
|
| + /*
|
| + // Print possibly externally computed map
|
| + const char *signifier = (transitionElementsKind !=
|
| + most_general_map()->elements_kind())
|
| + ? "*" : "";
|
| + stream->Add(" COMPUTED MOST GENERAL MAP: %s%s(0x%p)\n", signifier,
|
| + ElementsKindToString(most_general_map()->elements_kind()),
|
| + most_general_map());
|
| +
|
| + // Print terminal nodes if available
|
| +
|
| + stream->Add(" TRANSITION INPUT VALUES:\n");
|
| + for (int j = 0; j < transition_inputs(); j++) {
|
| + HValue* node = transition_input(j);
|
| + stream->Add(" block%d %d: ", node->block()->block_id(), node->id());
|
| + node->PrintNameTo(stream);
|
| + stream->Add(" ");
|
| + node->PrintTo(stream);
|
| + stream->Add("\n");
|
| + }
|
| + */
|
| +}
|
| +
|
| +
|
| +void ArrayInstruction::AddBookmarks(const ZoneList<TransitionElementsBookmark>&
|
| + records) {
|
| + ASSERT(records.length() > 0);
|
| + Map* first_to_map = *(records[0].to().location());
|
| +
|
| + // Doesn't check for duplicates.
|
| + // The "to" map values should be the same for the whole group
|
| + for (int i = 0; i < records.length(); i++) {
|
| + bookmarks_->Add(records[i], zone_);
|
| + ASSERT(first_to_map == *(records[i].to().location()));
|
| + }
|
| +
|
| + // set_most_general_map(first_to_map);
|
| +}
|
| +
|
| +
|
| +Map* ArrayInstruction::map_family() {
|
| + Map* family = NULL;
|
| + if (bookmarks()) {
|
| + family = *(bookmark(0)->family().location());
|
| + }
|
| +
|
| +#ifdef DEBUG
|
| + for (int i = 1; i < bookmarks(); i++) {
|
| + TransitionElementsBookmark* tr = bookmark(i);
|
| + ASSERT(*(tr->family().location()) == family);
|
| + }
|
| +#endif
|
| + return family;
|
| +}
|
| +
|
| +
|
| // Node-specific verification code is only included in debug mode.
|
| #ifdef DEBUG
|
|
|
|
|