From d557425a0cae251473dd1c629b00f1e900c1b8d1 Mon Sep 17 00:00:00 2001 From: "jarin@chromium.org" Date: Fri, 25 Apr 2014 11:29:02 +0000 Subject: [PATCH] Preserve Smi representation of non-escaping fields. R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/251493004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20971 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/hydrogen-escape-analysis.cc | 22 ++++++++++++-- src/hydrogen-escape-analysis.h | 2 ++ .../regress-escape-preserve-smi-representation.js | 35 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 test/mjsunit/regress/regress-escape-preserve-smi-representation.js diff --git a/src/hydrogen-escape-analysis.cc b/src/hydrogen-escape-analysis.cc index 1023019..6a03c57 100644 --- a/src/hydrogen-escape-analysis.cc +++ b/src/hydrogen-escape-analysis.cc @@ -161,6 +161,23 @@ HValue* HEscapeAnalysisPhase::NewMapCheckAndInsert(HCapturedObject* state, } +// Replace a field load with a given value, forcing Smi representation if +// necessary. +HValue* HEscapeAnalysisPhase::NewLoadReplacement( + HLoadNamedField* load, HValue* load_value) { + HValue* replacement = load_value; + Representation representation = load->representation(); + if (representation.IsSmi()) { + Zone* zone = graph()->zone(); + HInstruction* new_instr = + HForceRepresentation::New(zone, NULL, load_value, representation); + new_instr->InsertAfter(load); + replacement = new_instr; + } + return replacement; +} + + // Performs a forward data-flow analysis of all loads and stores on the // given captured allocation. This uses a reverse post-order iteration // over affected basic blocks. All non-escaping instructions are handled @@ -196,10 +213,11 @@ void HEscapeAnalysisPhase::AnalyzeDataFlow(HInstruction* allocate) { int index = load->access().offset() / kPointerSize; if (load->object() != allocate) continue; ASSERT(load->access().IsInobject()); - HValue* replacement = state->OperandAt(index); + HValue* replacement = + NewLoadReplacement(load, state->OperandAt(index)); load->DeleteAndReplaceWith(replacement); if (FLAG_trace_escape_analysis) { - PrintF("Replacing load #%d with #%d (%s)\n", instr->id(), + PrintF("Replacing load #%d with #%d (%s)\n", load->id(), replacement->id(), replacement->Mnemonic()); } break; diff --git a/src/hydrogen-escape-analysis.h b/src/hydrogen-escape-analysis.h index 3e27cc1..9818db3 100644 --- a/src/hydrogen-escape-analysis.h +++ b/src/hydrogen-escape-analysis.h @@ -62,6 +62,8 @@ class HEscapeAnalysisPhase : public HPhase { HValue* NewMapCheckAndInsert(HCapturedObject* state, HCheckMaps* mapcheck); + HValue* NewLoadReplacement(HLoadNamedField* load, HValue* load_value); + HCapturedObject* StateAt(HBasicBlock* block) { return block_states_.at(block->block_id()); } diff --git a/test/mjsunit/regress/regress-escape-preserve-smi-representation.js b/test/mjsunit/regress/regress-escape-preserve-smi-representation.js new file mode 100644 index 0000000..551147e --- /dev/null +++ b/test/mjsunit/regress/regress-escape-preserve-smi-representation.js @@ -0,0 +1,35 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function deepEquals(a, b) { + if (a === b) { if (a === 0) return (1 / a) === (1 / b); return true; } + if (typeof a != typeof b) return false; + if (typeof a == "number") return isNaN(a) && isNaN(b); + if (typeof a !== "object" && typeof a !== "function") return false; + if (objectClass === "RegExp") { return (a.toString() === b.toString()); } + if (objectClass === "Function") return false; + if (objectClass === "Array") { + var elementCount = 0; + if (a.length != b.length) { return false; } + for (var i = 0; i < a.length; i++) { + if (!deepEquals(a[i], b[i])) return false; + } + return true; + } +} + + +function __f_1(){ + var __v_0 = []; + for(var i=0; i<2; i++){ + var __v_1=[]; + __v_0.push([]) + deepEquals(2, __v_0.length); + } +} +__f_1(); +%OptimizeFunctionOnNextCall(__f_1); +__f_1(); -- 2.7.4