}
-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());
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
};
-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) {
}
-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());
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);
}
-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
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);
+ }
}
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(LeaveInlined) \
V(LoadContextSlot) \
V(LoadElements) \
};
-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) {
};
-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);
}
}
+ 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_; }
}
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));
}
}
-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) {
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;
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);
}
}
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,
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);
}
-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());
}
-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());
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
};
-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) {
}
-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());
}
-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());
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
};
-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) {
}
-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());
}
-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());
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
};
-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) {
--- /dev/null
+// 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();
+