Remove (H|L)JSArrayLength instructions

BUG=

Review URL: https://codereview.chromium.org/12491023

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14127 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dslomov@chromium.org 2013-04-03 16:25:24 +00:00
parent e559b72e40
commit a172a5e839
18 changed files with 85 additions and 179 deletions

View File

@ -1740,12 +1740,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LJSArrayLength(array));
}
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());

View File

@ -120,7 +120,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@ -1165,19 +1164,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 1> {
};
class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LJSArrayLength(LOperand* value) {
inputs_[0] = value;
}
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
};
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {

View File

@ -1918,13 +1918,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());
__ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
}
void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());

View File

@ -287,9 +287,8 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
AddInstruction(new(zone) HTrapAllocationMemento(js_array));
HInstruction* array_length =
AddInstruction(new(zone) HJSArrayLength(js_array,
js_array,
HType::Smi()));
AddInstruction(HLoadNamedField::NewArrayLength(
zone, js_array, js_array, HType::Smi()));
ElementsKind to_kind = casted_stub()->to_kind();
BuildNewSpaceArrayCheck(array_length, to_kind);

View File

@ -1468,15 +1468,6 @@ void HChange::PrintDataTo(StringStream* stream) {
}
void HJSArrayLength::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
if (HasTypeCheck()) {
stream->Add(" ");
typecheck()->PrintNameTo(stream);
}
}
HValue* HUnaryMathOperation::Canonicalize() {
if (op() == kMathFloor) {
// If the input is integer32 then we replace the floor instruction
@ -2416,6 +2407,10 @@ void HParameter::PrintDataTo(StringStream* stream) {
void HLoadNamedField::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
if (HasTypeCheck()) {
stream->Add(" ");
typecheck()->PrintNameTo(stream);
}
}

View File

@ -134,7 +134,6 @@ class LChunkBuilder;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(LeaveInlined) \
V(LoadContextSlot) \
V(LoadElements) \
@ -2392,45 +2391,6 @@ class HCallRuntime: public HCall<1> {
};
class HJSArrayLength: public HTemplateInstruction<2> {
public:
HJSArrayLength(HValue* value, HValue* typecheck,
HType type = HType::Tagged()) {
set_type(type);
// The length of an array is stored as a tagged value in the array
// object. It is guaranteed to be 32 bit integer, but it can be
// represented as either a smi or heap number.
SetOperandAt(0, value);
SetOperandAt(1, typecheck != NULL ? typecheck : value);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetGVNFlag(kDependsOnArrayLengths);
SetGVNFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
}
virtual void PrintDataTo(StringStream* stream);
HValue* value() { return OperandAt(0); }
HValue* typecheck() {
ASSERT(HasTypeCheck());
return OperandAt(1);
}
bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
protected:
virtual bool DataEquals(HValue* other_raw) { return true; }
private:
virtual bool IsDeletable() const { return true; }
};
class HFixedArrayBaseLength: public HUnaryOperation {
public:
explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
@ -5192,12 +5152,16 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
};
class HLoadNamedField: public HUnaryOperation {
class HLoadNamedField: public HTemplateInstruction<2> {
public:
HLoadNamedField(HValue* object, bool is_in_object, int offset)
: HUnaryOperation(object),
is_in_object_(is_in_object),
HLoadNamedField(HValue* object, bool is_in_object, int offset,
HValue* typecheck = NULL)
: is_in_object_(is_in_object),
offset_(offset) {
ASSERT(object != NULL);
SetOperandAt(0, object);
SetOperandAt(1, typecheck != NULL ? typecheck : object);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetGVNFlag(kDependsOnMaps);
@ -5208,7 +5172,24 @@ class HLoadNamedField: public HUnaryOperation {
}
}
static HLoadNamedField* NewArrayLength(Zone* zone, HValue* object,
HValue* typecheck,
HType type = HType::Tagged()) {
HLoadNamedField* result = new(zone) HLoadNamedField(
object, true, JSArray::kLengthOffset, typecheck);
result->set_type(type);
result->SetGVNFlag(kDependsOnArrayLengths);
result->ClearGVNFlag(kDependsOnInobjectFields);
return result;
}
HValue* object() { return OperandAt(0); }
HValue* typecheck() {
ASSERT(HasTypeCheck());
return OperandAt(1);
}
bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
bool is_in_object() const { return is_in_object_; }
int offset() const { return offset_; }

View File

@ -1165,8 +1165,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
}
HInstruction* length = NULL;
if (is_js_array) {
length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
HType::Smi()));
length = AddInstruction(
HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi()));
} else {
length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
}
@ -1235,13 +1235,6 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
}
HInstruction* HGraphBuilder::BuildFastArrayLengthLoad(HValue* object,
HValue* typecheck) {
Zone* zone = this->zone();
return new (zone) HJSArrayLength(object, typecheck, HType::Smi());
}
HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
ElementsKind kind,
HValue* capacity) {
@ -6429,7 +6422,8 @@ bool HOptimizedGraphBuilder::HandlePolymorphicArrayLengthLoad(
AddInstruction(new(zone()) HCheckNonSmi(object));
HInstruction* typecheck =
AddInstruction(HCheckInstanceType::NewIsJSArray(object, zone()));
HInstruction* instr = BuildFastArrayLengthLoad(object, typecheck);
HInstruction* instr =
HLoadNamedField::NewArrayLength(zone(), object, typecheck);
instr->set_position(expr->position());
ast_context()->ReturnInstruction(instr, expr->id());
return true;
@ -7094,7 +7088,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
if (name->Equals(isolate()->heap()->length_string())) {
if (map->instance_type() == JS_ARRAY_TYPE) {
AddCheckMapsWithTransitions(object, map);
return BuildFastArrayLengthLoad(object, NULL);
return HLoadNamedField::NewArrayLength(zone(), object, object);
}
}
@ -7387,8 +7381,9 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
set_current_block(if_jsarray);
HInstruction* length;
length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
HType::Smi()));
length = AddInstruction(
HLoadNamedField::NewArrayLength(zone(), object, typecheck,
HType::Smi()));
checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind_branch,

View File

@ -939,8 +939,6 @@ class HGraphBuilder {
KeyedAccessStoreMode store_mode,
Representation checked_index_representation = Representation::None());
HInstruction* BuildFastArrayLengthLoad(HValue* object, HValue* typecheck);
HInstruction* BuildStoreMap(HValue* object, HValue* map, BailoutId id);
HInstruction* BuildStoreMap(HValue* object, Handle<Map> map, BailoutId id);

View File

@ -1740,13 +1740,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());
__ mov(result, FieldOperand(array, JSArray::kLengthOffset));
}
void LCodeGen::DoFixedArrayBaseLength(
LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());

View File

@ -1749,12 +1749,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LJSArrayLength(array));
}
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());

View File

@ -114,7 +114,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@ -1147,19 +1146,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 0> {
};
class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LJSArrayLength(LOperand* value) {
inputs_[0] = value;
}
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
};
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {

View File

@ -1492,13 +1492,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());
__ lw(result, FieldMemOperand(array, JSArray::kLengthOffset));
}
void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());

View File

@ -1585,12 +1585,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LJSArrayLength(array));
}
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());

View File

@ -120,7 +120,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@ -1110,19 +1109,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 1> {
};
class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LJSArrayLength(LOperand* value) {
inputs_[0] = value;
}
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
};
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {

View File

@ -1574,13 +1574,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());
__ movq(result, FieldOperand(array, JSArray::kLengthOffset));
}
void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());

View File

@ -1661,12 +1661,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LJSArrayLength(array));
}
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());

View File

@ -121,7 +121,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@ -1109,19 +1108,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 0> {
};
class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LJSArrayLength(LOperand* value) {
inputs_[0] = value;
}
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
};
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {

View File

@ -0,0 +1,46 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
function TestNonSmiArrayLength() {
function f(a) {
return a.length+1;
}
var a = [];
a.length = 0xFFFF;
assertSame(0x10000, f(a));
assertSame(0x10000, f(a));
%OptimizeFunctionOnNextCall(f);
a.length = 0xFFFFFFFF;
assertSame(0x100000000, f(a));
}
TestNonSmiArrayLength();