diff --git a/src/hydrogen-escape-analysis.cc b/src/hydrogen-escape-analysis.cc index 1023019923..6a03c5773a 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 3e27cc1b48..9818db3557 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 0000000000..551147ed55 --- /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();